diff --git a/interactive-mining-3rdparty-madis/README.md b/interactive-mining-3rdparty-madis/README.md new file mode 100644 index 0000000..51ccda9 --- /dev/null +++ b/interactive-mining-3rdparty-madis/README.md @@ -0,0 +1,3 @@ +The package is a container for the [madIS](https://code.google.com/p/madis/) Python-based system developed by [NKUA](http://en.uoa.gr/). + +It requires the `apsw` Python package to be installed in the operating system. diff --git a/interactive-mining-3rdparty-madis/madis/.gitignore b/interactive-mining-3rdparty-madis/madis/.gitignore new file mode 100644 index 0000000..5bf95ce --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/.gitignore @@ -0,0 +1,40 @@ +\.orig$ +\.orig\..*$ +\.chg\..*$ +\.rej$ +\.conflict\~$ +^src/tests/(?!readme.txt$).*$ +^nbproject/.*$ +^.idea/.*$ +^src/docs/build/_static/.*$ +^/src/docs/build/_static/.*$ +^src/docs/build/_sources/.*$ +^/src/docs/build/_sources/.*$ +^src/docs/html/(?!readme.txt$).*$ +^/src/docs/html/(?!readme.txt$).*$ +^src/libexternal/(?!__init__.py$).*$ +^src/functionslocal/row/(?!__init__.py$).*$ +^/src/functionslocal/row/(?!__init__.py$).*$ +^src/functionslocal/aggregate/(?!__init__.py$).*$ +^/src/functionslocal/aggregate/(?!__init__.py$).*$ +^src/functionslocal/vtable/(?!__init__.py$).*$ +^/src/functionslocal/vtable/(?!__init__.py$).*$ +^src/docs/build/.*$ +^/src/docs/build/.*$ +^src/docs/source/row\.txt$ +^/src/docs/source/row\.txt$ +^src/docs/source/aggregate\.txt$ +^/src/docs/source/aggregate\.txt$ +^src/docs/source/vtable\.txt$ +^/src/docs/source/vtable\.txt$ + +# use glob syntax. +syntax: glob +*.pyc +*.db3 +mterm_tel +project.properties +project.xml +private.xml +private.properties +src/docs/html/_sources/row.txt diff --git a/interactive-mining-3rdparty-madis/madis/src/LICENSE.txt b/interactive-mining-3rdparty-madis/madis/src/LICENSE.txt new file mode 100644 index 0000000..983ea9f --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/LICENSE.txt @@ -0,0 +1,32 @@ +Copyright and License +===================== + +Copyright (C) 2009-2013 Lefteris Stamatogiannakis, Mei Li Triantafyllidi, +Ioannis Foufoulas, Maria Vayanou, Marialena Kyriakidi. + +The external libraries used throughout the madIS project are copyright +of their respective authors. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +* The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + +* Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. + +* This notice may not be removed or altered from any source + distribution. + + +Alternatively you may strike the license above and use it under any +OSI approved open source license such as those listed at +http://opensource.org/licenses/alphabetical diff --git a/interactive-mining-3rdparty-madis/madis/src/demo/continents.tsv b/interactive-mining-3rdparty-madis/madis/src/demo/continents.tsv new file mode 100644 index 0000000..21d351c --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/demo/continents.tsv @@ -0,0 +1,257 @@ +Asia AF +Europe AL +Africa AG +Oceania AQ +Europe AN +Africa AO +Americas AV +Americas AC +Americas AR +Asia AM +Americas AA +Oceania AS +Europe AU +Asia AJ +Americas BF +Asia BA +Asia BG +Americas BB +Europe BO +Europe BE +Americas BH +Africa BN +Americas BD +Asia BT +Americas BL +Europe BK +Africa BC +Americas BR +Americas VI +Asia BX +Europe BU +Africa UV +Africa BY +Asia CB +Africa CM +Americas CA +Africa CV +Americas CJ +Africa CT +Africa CD +Americas CI +Asia CH +Asia KT +Asia CK +Americas CO +Africa CN +Africa CF +Oceania CW +Americas CS +Africa IV +Europe HR +Americas CU +Asia CY +Europe EZ +Europe DA +Africa DJ +Americas DO +Americas DR +Americas EC +Africa EG +Americas ES +Africa EK +Africa ER +Europe EN +Africa ET +Americas FA +Europe FO +Oceania FJ +Europe FI +Europe FR +Americas FG +Oceania FP +Africa GB +Africa GA +Asia GG +Europe GM +Africa GH +Europe GI +Europe GR +Americas GL +Americas GJ +Americas GP +Oceania GQ +Americas GT +Africa GV +Africa PU +Americas GY +Americas HA +Europe VT +Americas HO +Europe HU +Europe IC +Asia IN +Asia ID +Asia IR +Asia IZ +Europe EI +Asia IS +Europe IT +Americas JM +Asia JA +Asia JO +Asia KZ +Africa KE +Oceania KR +Asia KN +Asia KS +Asia KU +Asia KG +Asia LA +Europe LG +Asia LE +Africa LT +Africa LI +Africa LY +Europe LS +Europe LH +Europe LU +Europe MK +Africa MA +Africa MI +Asia MY +Asia MV +Africa ML +Europe MT +Oceania RM +Americas MB +Africa MR +Africa MP +Africa MF +Americas MX +Oceania +Europe MD +Europe MN +Asia MG +Americas MH +Africa MO +Africa MZ +Asia BM +Africa WA +Oceania NR +Asia NP +Europe NL +Americas NT +Oceania NC +Oceania NZ +Americas NU +Africa NG +Africa NI +Oceania NE +Oceania NF +Oceania CQ +Europe NO +Asia MU +Asia PK +Oceania PS +Americas PM +Oceania PP +Americas PA +Americas PE +Asia RP +Oceania PC +Europe PL +Europe PO +Americas RQ +Asia QA +Africa RE +Europe RO +Asia RS +Africa RW +Americas SC +Americas ST +Americas SB +Americas VC +Europe SM +Africa TP +Asia SA +Africa SG +Europe SR +Africa SE +Africa SL +Asia SN +Europe LO +Europe SI +Oceania BP +Africa SO +Africa SF +Europe SP +Asia CE +Africa SU +Americas NS +Europe SV +Africa WZ +Europe SW +Europe SZ +Asia SY +Asia TW +Asia TI +Africa TZ +Asia TH +Africa TO +Oceania TL +Oceania TN +Americas TD +Africa TS +Asia TU +Asia TX +Americas TK +Oceania TV +Africa UG +Europe UP +Asia TC +Europe UK +Americas US +Americas UY +Asia UZ +Oceania NH +Americas VE +Asia VM +Americas VQ +Oceania WF +Africa WI +Oceania WS +Asia YM +Africa CG +Africa ZA +Africa ZI +Asia HK +Asia MC +Antarctica AY +Atlantic Ocean BV +Asia IO +Indian Ocean FS +Indian Ocean HM +Europe MW +Atlantic Ocean SH +Atlantic Ocean SX +Asia AT +Americas BQ +Oceania CR +Europe EE +Asia GZ +Europe IM +Oceania FM +Americas FA +Europe GK +Europe JE +Americas IP +Europe JN +Europe MJ +Asia PF +Asia PG +Europe RB +Asia TT +Asia WE +Oceania WQ +Americas UM diff --git a/interactive-mining-3rdparty-madis/madis/src/demo/countries.tsv b/interactive-mining-3rdparty-madis/madis/src/demo/countries.tsv new file mode 100644 index 0000000..27a7715 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/demo/countries.tsv @@ -0,0 +1,259 @@ +id name total_area land_area water_area coastline total_border population p_young p_adult p_old p_growth labor_force phone_mobiles phone_mainlines internet_users isps birth_rate death_rate +AA Aruba 193.00 193.00 0.00 69 0.00 100018.00 19.70 70.20 10.10 1.52 41500.00 98400 37100 24000 12.83 7.61 +AC Antigua and Barbuda 442.60 442.60 0.00 153 0.00 69481.00 27.30 69.00 3.70 0.53 30000.00 54000 38000 20000 16 16.62 5.31 +TC United Arab Emirates 83600.00 83600.00 0.00 1318 867.00 4444011.00 20.60 78.50 0.90 4.00 2968000.00 4535000 1237000 1397000 1 16.09 2.16 +AF Afghanistan 647500.00 647500.00 0.00 0 5529.00 31889923.00 44.60 53.00 2.40 2.63 15000000.00 1400000 280000 30000 1 46.21 19.96 +AG Algeria 2381740.00 2381740.00 0.00 998 6343.00 33333216.00 27.20 67.90 4.80 1.22 9310000.00 13661000 2572000 1920000 2 17.11 4.62 +AJ Azerbaijan 86600.00 86100.00 500.00 0 2013.00 8120247.00 25.40 67.70 7.00 0.69 5191000.00 2242000 1091000 678800 2 17.47 8.35 +AL Albania 28748.00 27398.00 1350.00 362 720.00 3600523.00 24.10 66.60 9.30 0.53 1090000.00 1259000 255000 75000 10 15.16 5.33 +AM Armenia 29800.00 28400.00 1400.00 0 1254.00 2971650.00 19.50 69.30 11.20 -0.13 1200000.00 320000 600000 150000 9 12.34 8.29 +AN Andorra 468.00 468.00 0.00 0 120.30 71822.00 14.50 71.20 14.30 0.84 42420.00 64600 35400 21900 1 8.45 6.45 +AO Angola 1246700.00 1246700.00 0.00 1600 5198.00 12263596.00 43.70 53.50 2.80 2.18 6393000.00 1094000 94300 172000 1 44.51 24.81 +AQ American Samoa 199.00 199.00 0.00 116 0.00 57663.00 33.60 63.50 2.90 -0.26 17630.00 2377 15000 1 21.83 3.24 +AR Argentina 2766890.00 2736690.00 30200.00 4989 9861.00 40301927.00 24.90 64.40 10.70 0.94 15350000.00 22100000 8800000 10000000 33 16.53 7.55 +AS Australia 7686850.00 7617930.00 68920.00 25760 0.00 20434176.00 19.30 67.40 13.20 0.82 10660000.00 18420000 11460000 14664000 571 12.02 7.56 +AT Ashmore and Cartier Islands 5.00 5.00 0.00 74 0.00 0.00 +AU Austria 83870.00 82444.00 1426.00 0 2562.00 8199783.00 15.10 67.50 17.50 0.08 3880000.00 8160000 3705000 4650000 37 8.69 9.84 +AV Anguilla 102.00 102.00 0.00 61 0.00 13677.00 22.30 70.80 6.90 1.38 6049.00 1800 6200 3000 16 13.97 5.34 +AX Akrotiri 123.00 56 47.40 0.00 +AY Antarctica 14000000.00 14000000.00 17968 0.00 0.00 0 +BA Bahrain 665.00 665.00 0.00 161 0.00 708573.00 26.90 69.50 3.70 1.39 352000.00 748700 196500 152700 1 17.53 4.21 +BB Barbados 431.00 431.00 0.00 97 0.00 280946.00 19.70 71.40 8.90 0.37 128500.00 206200 134900 160000 19 12.61 8.61 +BC Botswana 600370.00 585370.00 15000.00 0 4013.00 1815508.00 35.80 60.30 3.90 1.50 288400.00 823100 132000 60000 11 23.17 13.63 +BD Bermuda 53.30 53.30 0.00 103 0.00 66163.00 18.30 69.20 12.50 0.58 38360.00 49000 56000 39000 20 11.26 7.84 +BE Belgium 30528.00 30278.00 250.00 67 1385.00 10392226.00 16.50 66.10 17.40 0.12 4890000.00 9460000 4801000 5100000 61 10.29 10.32 +BF The Bahamas 13940.00 10070.00 3870.00 3542 0.00 305655.00 27.00 66.50 6.50 0.60 176300.00 186000 139900 93000 19 17.30 9.13 +BG Bangladesh 144000.00 133910.00 10090.00 580 4246.00 150448339.00 33.10 63.40 3.50 2.06 68000000.00 9000000 1070000 300000 10 29.36 8.13 +BH Belize 22966.00 22806.00 160.00 386 516.00 294385.00 38.90 57.50 3.50 2.26 113000.00 93100 33300 35000 2 28.34 5.76 +BK Bosnia and Herzegovina 51129.00 51129.00 0.00 20 1459.00 4552198.00 15.00 70.40 14.60 1.00 1026000.00 1594000 968900 806400 3 8.80 8.42 +BL Bolivia 1098580.00 1084390.00 14190.00 0 6940.00 9119152.00 34.30 61.10 4.60 1.42 4300000.00 2421000 646300 480000 9 22.82 7.44 +BM Burma 678500.00 657740.00 20760.00 1930 5876.00 47373958.00 26.10 68.60 5.30 0.82 28490000.00 183400 476200 78000 1 17.48 9.33 +BN Benin 112620.00 110620.00 2000.00 121 1989.00 8078314.00 43.90 53.70 2.40 2.67 3211000.00 386700 76300 425000 4 38.10 11.94 +BO Belarus 207600.00 207600.00 0.00 0 2900.00 9724723.00 14.70 70.40 14.90 -0.41 4300000.00 4098000 3284300 3394000 23 9.50 13.98 +BP Solomon Islands 28450.00 27540.00 910.00 5313 0.00 566842.00 40.70 55.90 3.30 2.54 249200.00 6000 7400 8400 1 29.27 3.87 +BQ Navassa Island 5.40 5.40 0.00 8 0.00 0.00 +BR Brazil 8511965.00 8456510.00 55455.00 7491 16885.00 190010647.00 25.30 68.40 6.30 1.01 96340000.00 86210000 42382000 25900000 50 16.30 6.19 +BT Bhutan 47000.00 47000.00 0.00 0 1075.00 2327849.00 38.60 57.40 4.00 2.08 37800 32700 25000 33.28 12.46 +BU Bulgaria 110910.00 110550.00 360.00 354 1808.00 7322858.00 13.90 68.70 17.40 -0.84 3510000.00 6245000 2483000 2200000 200 9.62 14.28 +BV Bouvet Island 49.00 49.00 0.00 30 0.00 0.00 +BX Brunei 5770.00 5270.00 500.00 161 381.00 374577.00 27.80 69.00 3.20 1.81 180400.00 205900 90000 56000 2 18.56 3.26 +BY Burundi 27830.00 25650.00 2180.00 0 974.00 8390505.00 46.30 51.20 2.60 3.59 2990000.00 153000 27700 25000 1 41.97 13.17 +CA Canada 9984670.00 9093507.00 891163.00 202080 8893.00 33390141.00 17.30 69.20 13.50 0.87 17590000.00 16600000 18276000 21900000 760 10.75 7.86 +CB Cambodia 181040.00 176520.00 4520.00 443 2572.00 13995904.00 34.00 62.40 3.60 1.73 7000000.00 1062000 36400 41000 2 25.53 8.24 +CD Chad 1284000.00 1259200.00 24800.00 0 5968.00 9885661.00 47.30 49.80 2.90 2.32 2719000.00 210000 13000 35000 1 42.35 16.69 +CE Sri Lanka 65610.00 64740.00 870.00 1340 0.00 20926315.00 24.30 67.90 7.80 0.98 7500000.00 4284000 1510000 280000 5 17.00 6.01 +CF Republic of the Congo 342000.00 341500.00 500.00 169 5504.00 3800610.00 46.30 50.80 2.90 2.64 490000 13800 36000 1 42.16 12.59 +CG Democratic Republic of the Congo 2345410.00 2267600.00 77810.00 37 10730.00 65751512.00 47.60 49.90 2.60 3.39 15000000.00 2746000 10600 140600 1 42.96 10.34 +CH China 9596960.00 9326410.00 270550.00 14500 22117.00 1321851888.00 20.40 71.70 7.90 0.61 798000000.00 437480000 350433000 123000000 3 13.45 7.00 +CI Chile 756950.00 748800.00 8150.00 6435 6339.00 16284741.00 24.10 67.40 8.50 0.92 6940000.00 10570000 3436000 6700000 7 15.03 5.87 +CJ Cayman Islands 262.00 262.00 0.00 160 0.00 46600.00 20.30 71.00 8.60 2.50 23450.00 17000 38000 9909 16 12.60 4.98 +CK Cocos Islands 14.00 14.00 0.00 26 0.00 596.00 0.00 287 2 +CM Cameroon 475440.00 469440.00 6000.00 402 4591.00 18060382.00 41.30 55.50 3.20 2.24 6394000.00 2259000 99400 167000 1 35.07 12.66 +CN Comoros 2170.00 2170.00 0.00 340 0.00 711417.00 42.60 54.40 3.00 2.84 144500.00 16100 16900 20000 1 36.35 7.95 +CO Colombia 1138910.00 1038700.00 100210.00 3208 6309.00 44379598.00 29.80 64.80 5.40 1.43 20810000.00 21850000 7678800 4739000 18 20.16 5.54 +CQ Northern Mariana Islands 477.00 477.00 0.00 1482 0.00 84546.00 18.90 79.50 1.60 2.46 44470.00 20500 21000 10000 1 19.27 2.29 +CR Coral Sea Islands 0.00 3095 0.00 0.00 +CS Costa Rica 51100.00 50660.00 440.00 1290 639.00 4133884.00 27.80 66.40 5.80 1.41 1866000.00 1101000 1388000 1000000 3 18.02 4.39 +CT Central African Republic 622984.00 622984.00 0.00 0 5203.00 4369038.00 41.60 54.20 4.10 1.51 60000 10000 9000 1 33.52 18.46 +CU Cuba 110860.00 110860.00 0.00 3735 29.00 11394043.00 18.80 70.50 10.70 0.27 4820000.00 134500 849900 190000 5 11.44 7.14 +CV Cape Verde 4033.00 4033.00 0.00 965 0.00 423613.00 36.90 56.40 6.70 0.61 120600.00 81700 71400 25000 1 24.40 6.50 +CW Cook Islands 236.70 236.70 0.00 120 0.00 21750.00 34.10 59.50 6.40 -1.20 6820.00 1500 6200 3600 3 21.00 +CY Cyprus 9250.00 9240.00 10.00 648 0.00 788457.00 19.90 68.30 11.80 0.53 298000 6 12.56 7.72 +DA Denmark 43094.00 42394.00 700.00 7314 68.00 5468120.00 18.60 66.00 15.40 0.31 2910000.00 5469000 3350000 3763000 13 10.91 10.30 +DJ Djibouti 23000.00 22980.00 20.00 314 516.00 496374.00 43.40 53.20 3.40 1.98 282000.00 34500 11100 9000 1 39.07 19.23 +DO Dominica 754.00 754.00 0.00 148 0.00 72386.00 25.60 64.20 10.20 0.18 25000.00 41800 21000 20500 16 15.75 8.44 +DR Dominican Republic 48730.00 48380.00 350.00 1288 360.00 9365818.00 32.10 62.20 5.70 1.50 3896000.00 3623000 894500 938300 24 22.91 5.32 +DX Dhekelia 130.80 28 360.00 +EC Ecuador 283560.00 276840.00 6720.00 2237 2010.00 13755680.00 32.60 62.30 5.10 1.55 4570000.00 6246000 1701000 616000 31 21.91 4.21 +EE European Union 4324782.00 65993 12440.80 490426060.00 15.72 67.16 17.11 0.16 222700000.00 466000000 238000000 247000000 10.00 10.00 +EG Egypt 1001450.00 995450.00 6000.00 2450 2665.00 80335036.00 32.20 63.20 4.60 1.72 21800000.00 14045000 10396000 5000000 50 22.53 5.11 +EI Ireland 70280.00 68890.00 1390.00 1448 360.00 4109086.00 20.80 67.50 11.70 1.14 2120000.00 4210000 2033000 2060000 22 14.40 7.79 +EK Equatorial Guinea 28051.00 28051.00 0.00 296 539.00 551201.00 41.50 54.80 3.80 2.02 96900 10000 5000 1 35.16 15.01 +EN Estonia 45226.00 43211.00 2015.00 3794 633.00 1315912.00 15.00 67.50 17.50 -0.64 673000.00 1445000 442000 690000 38 10.17 13.30 +ER Eritrea 121320.00 121320.00 0.00 2234 1626.00 4906585.00 43.50 52.90 3.60 2.46 58000 37700 70000 5 33.97 9.36 +ES El Salvador 21040.00 20720.00 320.00 307 545.00 6948073.00 36.10 58.70 5.20 1.70 2856000.00 2412000 971500 637100 4 26.13 5.60 +ET Ethiopia 1127127.00 1119683.00 7444.00 0 5328.00 76511887.00 43.40 53.80 2.70 2.27 27270000.00 410600 610300 113000 1 37.39 14.67 +EZ Czech Republic 78866.00 77276.00 1590.00 0 2290.20 10228744.00 14.10 71.20 14.70 -0.07 5310000.00 11776000 3217300 5100000 8.96 10.64 +FI Finland 338145.00 304473.00 33672.00 1250 2681.00 5238460.00 16.90 66.70 16.40 0.13 2620000.00 5231000 2120000 3286000 3 10.42 9.93 +FJ Fiji 18270.00 18270.00 0.00 1129 0.00 918675.00 30.90 64.70 4.40 1.39 137000.00 142200 102000 61000 2 22.37 5.66 +FA Falkland Islands 12173.00 12173.00 0.00 1288 0.00 3105.00 2.44 1724.00 0 2400 1900 2 +FM Federated States of Micronesia 702.00 702.00 0.00 6112 0.00 107862.00 35.90 61.20 2.90 -0.15 37410.00 14100 12400 14000 1 24.14 4.66 +FO Faroe Islands 1399.00 1399.00 0.00 1117 0.00 47511.00 20.60 65.30 14.10 0.54 24250.00 42500 23800 33000 2 14.12 8.69 +FP French Polynesia 4167.00 3660.00 507.00 2525 0.00 278963.00 25.40 68.20 6.30 1.46 65930.00 87000 53400 55000 2 16.41 4.61 +FR France 643427.00 640053.00 3374.00 4668 0.00 18.60 65.20 16.20 0.59 27880000.00 49370000 38433000 29945000 62 12.91 8.55 +FS French Southern and Antarctic Lands 28 0.00 0.00 +GA The Gambia 11300.00 10000.00 1300.00 80 740.00 1688359.00 44.10 53.20 2.80 2.78 400000.00 247500 44000 49000 2 38.86 11.99 +GB Gabon 267667.00 257667.00 10000.00 885 2551.00 1454867.00 42.10 53.90 4.00 2.04 581000.00 649800 39100 67000 1 35.96 12.45 +GG Georgia 69700.00 69700.00 0.00 310 1461.00 4646003.00 16.70 66.60 16.70 -0.33 2040000.00 1459000 683200 175600 6 10.54 9.37 +GH Ghana 239460.00 230940.00 8520.00 539 2094.00 22931299.00 38.20 58.20 3.60 1.97 10870000.00 2842000 321500 401300 12 29.85 9.55 +GI Gibraltar 6.50 6.50 0.00 12 1.20 27967.00 17.20 66.30 16.50 0.13 12690.00 9797 24512 6200 2 10.69 9.40 +GJ Grenada 344.00 344.00 0.00 121 0.00 89971.00 32.80 64.10 3.10 0.34 42300.00 43300 32700 19000 14 21.87 6.61 +GK Guernsey 78.00 78.00 0.00 50 0.00 65573.00 14.80 67.40 17.80 0.24 31470.00 43800 55100 36000 8.65 10.07 +GL Greenland 2166086.00 2166086.00 44087 0.00 56344.00 24.00 69.10 6.90 -0.03 32120.00 32200 25300 38000 1 16.01 7.93 +GM Germany 357021.00 349223.00 7798.00 2389 3621.00 82400996.00 13.90 66.30 19.80 -0.03 43660000.00 79200000 55046000 50616000 200 8.20 10.71 +GQ Guam 541.30 541.30 0.00 126 0.00 173456.00 28.60 64.50 6.90 1.40 62050.00 98000 84134 79000 20 18.56 4.56 +GR Greece 131940.00 130800.00 1140.00 13676 1228.00 10706290.00 14.30 66.70 19.00 0.16 4880000.00 10043000 6303000 3800000 27 9.62 10.33 +GT Guatemala 108890.00 108430.00 460.00 400 1687.00 12728111.00 40.80 55.50 3.60 2.15 5020000.00 3168000 1132000 756000 5 29.09 5.27 +GV Guinea 245857.00 245857.00 0.00 320 3399.00 9947814.00 44.30 52.50 3.20 2.62 3700000.00 189000 26200 46000 4 41.53 15.33 +GY Guyana 214970.00 196850.00 18120.00 459 2949.00 769095.00 26.10 68.60 5.30 0.23 418000.00 281400 110100 160000 3 18.09 8.28 +GZ Gaza Strip 360.00 360.00 0.00 40 62.00 1482405.00 47.60 49.90 2.50 3.66 259000.00 1095000 349000 243000 3 38.90 3.74 +HA Haiti 27750.00 27560.00 190.00 1771 360.00 8706497.00 42.10 54.40 3.50 2.45 3600000.00 400000 140000 500000 3 35.87 10.40 +HK Hong Kong 1092.00 1042.00 50.00 733 30.00 6980412.00 13.00 74.00 12.90 0.56 3630000.00 8693000 3795000 4879000 17 7.34 6.45 +HM Heard Island and McDonald Islands 412.00 412.00 0.00 102 0.00 0.00 +HO Honduras 112090.00 111890.00 200.00 820 1520.00 7483763.00 39.30 57.20 3.50 2.09 2589000.00 1282000 494400 223000 8 27.59 5.32 +HR Croatia 56542.00 56414.00 128.00 5835 2197.00 4493312.00 16.00 67.10 16.90 -0.04 1720000.00 2984000 1890000 1451000 9 9.63 11.57 +HU Hungary 93030.00 92340.00 690.00 0 2171.00 9956108.00 15.30 69.30 15.40 -0.25 4200000.00 9320000 3356000 3050000 16 9.66 13.05 +IC Iceland 103000.00 100250.00 2750.00 4970 0.00 301931.00 21.40 66.80 11.80 0.82 173000.00 304000 193900 258000 20 13.57 6.77 +ID Indonesia 1919440.00 1826440.00 93000.00 54716 2830.00 234693997.00 28.70 65.60 5.70 1.21 108200000.00 46910000 12772000 16000000 24 19.65 6.25 +IM Isle of Man 572.00 572.00 0.00 160 0.00 75831.00 17.10 65.80 17.10 0.51 39690.00 51000 10.96 11.10 +IN India 3287590.00 2973190.00 314400.00 7000 14103.00 1129866154.00 31.80 63.10 5.10 1.61 509300000.00 69193000 49750000 60000000 43 22.69 6.58 +IO British Indian Ocean Territory 54400.00 60.00 54340.00 698 0.00 0.00 1 +IP Clipperton Island 6.00 6.00 0.00 11 0.00 0.00 +IR Iran 1648000.00 1636000.00 12000.00 2440 5440.00 65397521.00 23.20 71.40 5.40 0.66 24360000.00 8500000 18986000 7500000 100 16.57 5.65 +IS Israel 20770.00 20330.00 440.00 273 1017.00 6426679.00 26.10 64.20 9.80 1.15 2600000.00 7757000 2936000 3700000 21 17.71 6.17 +IT Italy 301230.00 294020.00 7210.00 7600 1932.20 58147733.00 13.80 66.40 19.90 0.01 24630000.00 72200000 25049000 28870000 93 8.54 10.50 +IV Cote d'Ivoire 322460.00 318000.00 4460.00 515 3110.00 18013409.00 40.60 56.60 2.80 2.00 6738000.00 2190000 257900 160000 5 34.69 14.74 +IZ Iraq 437072.00 432162.00 4910.00 58 3650.00 27499638.00 39.40 57.60 3.00 2.62 7400000.00 8700000 1547000 36000 1 31.44 5.26 +JA Japan 377835.00 374744.00 3091.00 29751 0.00 127433494.00 13.80 65.20 21.00 -0.09 66440000.00 94745000 58780000 86300000 73 8.10 8.98 +JE Jersey 116.00 116.00 0.00 70 0.00 91321.00 16.90 67.30 15.80 0.24 53560.00 83900 73900 27000 9.02 9.32 +JM Jamaica 10991.00 10831.00 160.00 1022 0.00 2780132.00 32.50 60.10 7.40 0.78 1100000.00 2700000 342000 1067000 21 20.44 6.59 +JN Jan Mayen 377.00 377.00 0.00 124 0.00 0.00 13 +JO Jordan 92300.00 91971.00 329.00 26 1635.00 6053193.00 33.00 63.00 4.00 2.41 1512000.00 3013000 628200 629500 5 20.69 2.68 +KE Kenya 582650.00 569250.00 13400.00 536 3477.00 36913721.00 42.10 55.20 2.60 2.80 1955000.00 6500000 281800 1055000 65 38.94 10.95 +KG Kyrgyzstan 198500.00 191300.00 7200.00 0 3878.00 5284149.00 30.30 63.50 6.20 1.35 2700000.00 541700 438200 280000 23.08 7.02 +KN North Korea 120540.00 120410.00 130.00 2495 1673.00 23301725.00 23.30 68.10 8.50 0.79 9600000.00 980000 1 15.06 7.21 +KR Kiribati 811.00 811.00 0.00 1143 0.00 107817.00 38.20 58.40 3.40 2.24 7870.00 600 4500 2000 1 30.48 8.12 +KS South Korea 98480.00 98190.00 290.00 2413 238.00 49044790.00 18.30 72.10 9.60 0.39 23770000.00 38342000 23745000 33900000 11 9.93 5.99 +KT Christmas Island 135.00 135.00 0.00 139 0.00 1402.00 0.00 464 2 +KU Kuwait 17820.00 17820.00 0.00 499 462.00 2505559.00 26.70 70.50 2.80 3.56 1136000.00 2536000 510300 700000 3 21.95 2.39 +KZ Kazakhstan 2717300.00 2669800.00 47500.00 0 12012.00 15284929.00 22.50 69.20 8.30 0.35 7834000.00 4955000 2500000 400000 10 16.23 9.40 +LA Laos 236800.00 230800.00 6000.00 0 5083.00 6521998.00 41.20 55.70 3.10 2.37 2100000.00 520546 90067 25000 1 34.98 11.28 +LE Lebanon 10400.00 10230.00 170.00 225 454.00 3925502.00 26.20 66.70 7.10 1.20 1500000.00 1178000 990000 700000 22 18.08 6.10 +LG Latvia 64589.00 63589.00 1000.00 531 1368.00 2259810.00 13.60 69.60 16.70 -0.65 1136000.00 1872000 731000 1030000 41 9.43 13.64 +LH Lithuania 65200.00 90 1613.00 3575439.00 14.90 69.30 15.80 -0.29 1617000.00 4353000 801100 1222000 32 8.87 11.05 +LI Liberia 111370.00 96320.00 15050.00 579 1585.00 3195931.00 43.60 53.60 2.70 4.84 160000 6900 1000 2 43.75 22.24 +LO Slovakia 48845.00 48800.00 45.00 0 1524.00 5447502.00 16.40 71.50 12.20 0.15 2629000.00 4540000 1197000 2500000 6 10.65 9.48 +LS Liechtenstein 160.00 160.00 0.00 0 76.00 34247.00 17.10 70.00 12.80 0.75 29500.00 11400 19900 20000 44 10.02 7.30 +LT Lesotho 30355.00 30355.00 0.00 0 909.00 2125262.00 35.70 59.30 5.00 0.14 838000.00 245100 48000 43000 1 24.72 22.49 +LU Luxembourg 2586.00 2586.00 0.00 0 359.00 480222.00 18.80 66.60 14.70 1.21 203000.00 720000 244500 315000 8 11.84 8.42 +LY Libya 1759540.00 1759540.00 0.00 1770 4348.00 6036914.00 33.40 62.40 4.20 2.26 1787000.00 234800 750000 205000 1 26.09 3.47 +MA Madagascar 587040.00 581540.00 5500.00 4828 0.00 19448815.00 43.90 53.00 3.10 3.01 7300000.00 504700 66900 90000 2 38.60 8.51 +MC Macau 28.20 28.20 0.00 41 0.34 456989.00 15.40 76.60 8.00 0.84 248000.00 532800 174400 201000 1 8.57 4.59 +MD Moldova 33843.00 33371.00 472.00 0 1389.00 4320490.00 16.50 72.60 10.90 -0.11 1339000.00 1090000 929400 406000 2 10.88 10.85 +MF Mayotte 374.00 374.00 0.00 185 0.00 208783.00 45.80 52.50 1.80 3.62 44560.00 48100 10000 40.35 7.53 +MG Mongolia 1564116.00 0 8220.00 2951786.00 28.70 67.40 3.90 1.49 1577000.00 557200 156000 268300 5 21.07 6.21 +MH Montserrat 102.00 102.00 0.00 40 0.00 9538.00 23.50 65.70 10.80 1.05 4521.00 70 17 17.51 7.02 +MI Malawi 118480.00 94080.00 24400.00 0 2881.00 13603181.00 46.10 51.20 2.70 2.38 4500000.00 429300 102700 52500 3 42.09 18.25 +MJ Montenegro 14026.00 13812.00 214.00 294 625.00 684736.00 -1.00 259100.00 543220 177663 50000 11.18 8.39 +MK Macedonia 25333.00 24856.00 477.00 0 766.00 2055915.00 19.80 69.10 11.10 0.26 899000.00 1261000 533200 392671 6 12.02 8.78 +ML Mali 1240000.00 1220000.00 20000.00 0 7243.00 11995402.00 48.20 48.80 3.10 2.68 3930000.00 869600 75000 60000 13 49.61 16.51 +MN Monaco 1.95 1.95 0.00 4 4.40 32671.00 15.00 62.30 22.70 0.39 44000.00 19300 33700 16000 2 9.12 12.92 +MO Morocco 446550.00 446300.00 250.00 1835 2017.90 33757175.00 31.00 63.90 5.10 1.53 11250000.00 12393000 1341000 4600000 8 21.64 5.54 +MP Mauritius 2040.00 2030.00 10.00 177 0.00 1250882.00 23.50 69.80 6.70 0.80 555000.00 713300 359000 180000 2 15.26 6.88 +MR Mauritania 1030700.00 1030400.00 300.00 754 5074.00 3270065.00 45.50 52.40 2.20 2.87 786000.00 745600 41000 14000 5 40.56 11.89 +MT Malta 316.00 316.00 0.00 197 0.00 401880.00 16.70 69.50 13.80 0.41 164000.00 324000 202100 127200 6 10.28 8.19 +MU Oman 212460.00 212460.00 0.00 2092 1374.00 3204897.00 42.70 54.60 2.70 3.23 920000.00 1333000 265200 245000 1 35.76 3.78 +MV Maldives 300.00 300.00 0.00 644 0.00 369031.00 42.90 54.00 3.10 2.73 101300.00 271053 32181 19000 1 34.20 6.88 +MX Mexico 1972550.00 1923040.00 49510.00 9330 4353.00 108700891.00 30.10 64.00 5.90 1.15 38090000.00 47462000 19512000 18622000 51 20.36 4.76 +MY Malaysia 329750.00 328550.00 1200.00 4675 2669.00 24821286.00 32.20 62.90 4.80 1.76 10730000.00 19545000 4366000 11016000 7 22.65 5.05 +MZ Mozambique 801590.00 784090.00 17500.00 2470 4571.00 20905585.00 44.70 52.50 2.80 1.80 9400000.00 1220000 69700 138000 11 38.54 20.51 +NC New Caledonia 19060.00 18575.00 485.00 2254 0.00 221943.00 27.90 65.30 6.80 1.20 78990.00 134300 55300 76000 1 17.75 5.72 +NE Niue 260.00 260.00 0.00 64 0.00 1492.00 -0.03 663.00 400 1100 900 1 +NF Norfolk Island 34.60 34.60 0.00 32 0.00 2114.00 20.20 63.90 15.90 0.01 0 2532 700 2 +NG Niger 1267000.00 1266700.00 300.00 0 5697.00 12894865.00 46.90 50.60 2.40 2.90 70000.00 299900 24000 24000 1 50.16 20.59 +NH Vanuatu 12200.00 12200.00 0.00 2528 0.00 211971.00 31.90 64.30 3.80 1.46 76410.00 12700 6800 7500 1 22.35 7.75 +NI Nigeria 923768.00 910768.00 13000.00 853 4047.00 135031164.00 42.20 54.70 3.10 2.38 48990000.00 21571000 1223000 5000000 11 40.20 16.68 +NL Netherlands 41526.00 33883.00 7643.00 451 1027.00 16570613.00 17.80 67.80 14.40 0.46 7600000.00 15834000 7600000 10806000 52 10.70 8.69 +NO Norway 323802.00 307442.00 16360.00 25148 2542.00 4627926.00 19.00 66.10 14.80 0.36 2420000.00 4755000 2129000 3140000 13 11.27 9.37 +NP Nepal 147181.00 143181.00 4000.00 0 2926.00 28901790.00 38.30 57.90 3.80 2.13 11110000.00 248800 448600 175000 6 30.46 9.14 +NR Nauru 21.00 21.00 0.00 30 0.00 13528.00 36.40 61.60 2.00 1.78 1500 1900 300 1 24.47 6.65 +NS Suriname 163270.00 161470.00 1800.00 386 1703.00 470784.00 28.00 65.70 6.20 1.10 156700.00 232800 81100 30000 2 17.31 5.50 +NT Netherlands Antilles 960.00 960.00 0.00 364 15.00 223652.00 23.60 67.40 9.00 0.78 83600.00 200000 81000 2000 6 14.56 6.39 +NU Nicaragua 129494.00 120254.00 9240.00 910 1231.00 5675356.00 35.50 61.30 3.20 1.86 2261000.00 1119000 220900 140000 3 24.12 4.42 +NZ New Zealand 268680.00 268021.00 15134 0.00 4115771.00 20.80 67.30 11.90 0.95 2180000.00 3530000 1800000 3200000 36 13.61 7.54 +OO Southern Ocean 20327000.00 17968 0.00 +PA Paraguay 406750.00 397300.00 9450.00 0 3995.00 6669086.00 37.20 57.70 5.10 2.42 2742000.00 1887000 320300 200000 4 28.77 4.54 +PC Pitcairn Islands 47.00 47.00 0.00 51 0.00 48.00 0.00 15.00 1 +PE Peru 1285220.00 1280000.00 5220.00 2414 7461.00 28674757.00 30.30 64.20 5.40 1.29 9210000.00 5583000 2250000 4600000 10 20.09 6.21 +PF Paracel Islands 0.00 518 0.00 0.00 +PG Spratly Islands 0.00 926 0.00 0.00 +PK Pakistan 803940.00 778720.00 25220.00 1046 6774.00 164741924.00 36.90 58.80 4.30 1.83 48290000.00 48289136 5162798 10500000 30 27.52 8.00 +PL Poland 312685.00 304465.00 8220.00 491 3056.00 38518241.00 15.50 71.10 13.30 -0.05 17260000.00 29166000 11803000 10600000 19 9.94 9.94 +PM Panama 78200.00 75990.00 2210.00 2490 555.00 3242173.00 30.00 63.60 6.40 1.56 1441000.00 1352000 440100 300000 6 21.45 5.44 +PO Portugal 92391.00 91951.00 440.00 1793 1214.00 10642836.00 16.50 66.30 17.30 0.33 5580000.00 11448000 4234000 7783000 16 10.59 10.56 +PP Papua New Guinea 462840.00 452860.00 9980.00 5152 820.00 5795887.00 37.60 58.50 3.90 2.16 3477000.00 26000 62000 170000 3 28.76 7.14 +PS Palau 458.00 458.00 0.00 1519 0.00 20842.00 26.00 69.20 4.70 1.23 9777.00 1000 6700 1 17.70 6.77 +PU Guinea-Bissau 36120.00 28000.00 8120.00 350 724.00 1472780.00 41.20 55.80 3.00 2.05 480000.00 67000 10600 26000 2 36.81 16.29 +QA Qatar 11437.00 11437.00 0.00 563 60.00 907229.00 23.10 72.90 4.00 2.39 508000.00 854900 205400 219000 1 15.56 4.82 +RB Serbia 88361.00 88361.00 0.00 0 2027.00 10150265.00 2961000.00 5229000 2685000 1400000 +RM Marshall Islands 11854.30 181.30 11673.00 370 0.00 61815.00 38.30 58.90 2.80 2.21 14680.00 1198 5510 2000 1 32.37 4.66 +RO Romania 237500.00 230340.00 7160.00 225 2508.00 22276056.00 15.60 69.60 14.70 -0.13 9330000.00 13354000 4391000 4940000 38 10.67 11.81 +RP Philippines 300000.00 298170.00 1830.00 36289 0.00 91077287.00 34.50 61.30 4.10 1.76 35790000.00 32810000 3438000 7820000 33 24.48 5.36 +RQ Puerto Rico 13790.00 8870.00 4921.00 501 0.00 3944259.00 21.00 65.90 13.10 0.39 1300000.00 2682000 1112000 1000000 76 12.79 7.78 +RS Russia 17075200.00 16995800.00 79400.00 37653 20096.50 141377752.00 14.60 71.10 14.40 -0.48 73880000.00 120000000 40100000 23700000 300 10.92 16.04 +RW Rwanda 26338.00 24948.00 1390.00 0 893.00 9907509.00 41.90 55.70 2.50 2.77 4600000.00 290000 23000 38000 2 40.16 14.91 +SA Saudi Arabia 2149690.00 2149690.00 0.00 2640 4431.00 27601038.00 38.20 59.40 2.40 2.06 7125000.00 13300000 4500000 3200000 22 29.10 2.55 +SB Saint Pierre and Miquelon 242.00 242.00 0.00 120 0.00 7036.00 23.00 65.90 11.10 0.13 3450.00 4800 1 13.08 6.82 +SC Saint Kitts and Nevis 261.00 261.00 0.00 135 0.00 39349.00 27.20 64.90 7.90 0.62 18170.00 10000 25000 10000 16 17.89 8.16 +SE Seychelles 455.00 455.00 0.00 491 0.00 81895.00 25.40 68.50 6.10 0.43 30900.00 57000 21400 20000 1 15.83 6.25 +SF South Africa 1219912.00 1219912.00 0.00 2798 4862.00 43997828.00 29.10 65.50 5.40 -0.46 16090000.00 33960000 4729000 5100000 150 17.94 22.45 +SG Senegal 196190.00 192000.00 4190.00 531 2640.00 12521851.00 42.00 55.00 3.00 2.65 4749000.00 1730000 266600 540000 1 37.40 10.96 +SH Saint Helena 413.00 0.00 60 0.00 7543.00 18.70 71.10 10.20 0.53 2486.00 2200 1000 1 11.93 6.63 +SI Slovenia 20273.00 20151.00 122.00 47 1382.00 2009245.00 13.70 70.30 16.00 -0.07 1026000.00 1759000 816400 1090000 11 9.00 10.41 +SL Sierra Leone 71740.00 71620.00 120.00 402 958.00 6144562.00 44.80 52.00 3.20 2.29 1369000.00 113200 24000 10000 1 45.41 22.64 +SM San Marino 61.20 61.20 0.00 0 39.00 29615.00 16.80 66.10 17.10 1.22 20470.00 16800 20600 14300 2 9.89 8.27 +SN Singapore 692.70 682.70 10.00 193 0.00 4553009.00 15.20 76.30 8.50 1.28 2400000.00 4385000 1848000 2422000 9 9.17 4.40 +SO Somalia 637657.00 627337.00 10320.00 3025 2340.00 9118773.00 44.40 53.00 2.60 2.83 3700000.00 500000 100000 90000 3 44.60 16.28 +SP Spain 504782.00 499542.00 5240.00 4964 1917.80 40448191.00 14.40 67.80 17.80 0.12 21770000.00 41328000 18322000 19205000 56 9.98 9.81 + 0.00 6852.00 +ST Saint Lucia 616.00 606.00 10.00 158 0.00 170649.00 29.40 65.50 5.10 1.30 43800.00 93000 51100 55000 15 19.28 5.03 +SU Sudan 2505810.00 2376000.00 129810.00 853 7687.00 39379358.00 41.60 56.00 2.40 2.08 7415000.00 1828000 670000 2800000 2 34.86 14.39 +SV Svalbard 61020.00 61020.00 0.00 3587 0.00 2214.00 -0.01 13 +SW Sweden 449964.00 410934.00 39030.00 3218 2233.00 9031088.00 16.40 65.70 17.90 0.16 4590000.00 8436000 6447000 6800000 29 10.20 10.27 +SX South Georgia and the South Sandwich Islands 3903.00 3903.00 0.00 0.00 0.00 +SY Syria 185180.00 184050.00 1130.00 193 2253.00 19314747.00 36.50 60.10 3.30 2.24 5505000.00 3128000 2903000 1100000 1 27.19 4.74 +SZ Switzerland 41290.00 39770.00 1520.00 0 1852.00 7554661.00 16.10 68.20 15.80 0.38 3810000.00 6847000 5123000 5098000 44 9.66 8.51 +TD Trinidad and Tobago 5128.00 5128.00 0.00 362 0.00 1056608.00 19.50 71.60 8.90 -0.88 618000.00 800000 323500 160000 17 13.07 10.76 +TH Thailand 514000.00 511770.00 2230.00 3219 4863.00 65068149.00 21.60 70.10 8.20 0.66 36410000.00 27379000 7035000 8420000 15 13.73 7.10 +TI Tajikistan 143100.00 142700.00 400.00 0 3651.00 7076598.00 35.00 61.20 3.80 1.90 3700000.00 265000 245200 5000 4 27.33 7.05 +TK Turks and Caicos Islands 430.00 430.00 0.00 389 0.00 21746.00 31.30 64.80 3.90 2.72 4848.00 1700 5700 14 21.48 4.23 +TL Tokelau 10.00 10.00 0.00 101 0.00 1449.00 42.00 53.00 5.00 -0.02 440.00 0 300 1 +TN Tonga 748.00 718.00 30.00 419 0.00 116921.00 34.60 61.20 4.20 1.85 33910.00 16400 11200 3000 2 23.67 5.20 +TO Togo 56785.00 54385.00 2400.00 56 1647.00 5701579.00 42.00 55.30 2.70 2.72 1302000.00 443600 58600 300000 3 36.83 9.65 +TP Sao Tome and Principe 1001.00 1001.00 0.00 209 0.00 199579.00 47.30 49.00 3.70 3.13 35050.00 12000 7000 20000 1 39.72 6.28 +TS Tunisia 163610.00 155360.00 8250.00 1148 1424.00 10276158.00 24.00 69.20 6.90 0.99 3502000.00 5681000 1258000 953800 1 15.54 5.17 +TT East Timor 15007.00 706 228.00 1084971.00 35.70 61.10 3.20 2.06 1000 26.77 6.19 +TU Turkey 780580.00 770760.00 9820.00 7200 2648.00 71158647.00 24.90 68.10 6.90 1.04 24800000.00 43609000 18978000 16000000 50 16.40 6.00 +TV Tuvalu 26.00 26.00 0.00 24 0.00 11992.00 29.80 65.20 5.00 1.54 3615.00 0 700 1300 1 22.43 7.00 +TW Taiwan 35980.00 32260.00 3720.00 1566 0.00 22858872.00 17.80 72.00 10.20 0.30 10460000.00 22170000 13615000 13210000 8 8.97 6.54 +TX Turkmenistan 488100.00 488100.00 0 3736.00 5097028.00 34.70 60.90 4.40 1.62 2320000.00 52000 495000 36000 1 25.36 6.17 +TZ Tanzania 945087.00 886037.00 59050.00 1424 3861.00 39384223.00 43.90 53.30 2.80 2.09 19350000.00 1942000 148400 333000 6 35.95 13.36 +UG Uganda 236040.00 199710.00 36330.00 0 2698.00 30262610.00 50.20 47.60 2.20 3.57 13760000.00 1525000 100800 500000 2 48.12 12.64 +UK United Kingdom 244820.00 241590.00 3230.00 12429 360.00 60776238.00 17.20 67.00 15.80 0.28 31100000.00 61091000 32943000 37600000 10.67 10.09 +UM United States Pacific Island Wildlife Refuges 5 360.00 0.00 +UP Ukraine 603700.00 603700.00 0.00 2782 4663.00 46299862.00 14.00 69.60 16.30 -0.68 22300000.00 17214000 12142000 5278000 260 9.45 16.07 +US United States 9826630.00 9161923.00 664707.00 19924 12034.00 301139947.00 20.20 67.20 12.60 0.89 151400000.00 219400000 268000000 205327000 7000 14.16 8.26 +UV Burkina Faso 274200.00 273800.00 400.00 0 3193.00 14326203.00 46.70 50.90 2.50 3.00 5000000.00 572200 97400 64600 1 45.28 15.31 +UY Uruguay 176220.00 173620.00 2600.00 660 1648.00 3460607.00 23.00 63.80 13.20 0.50 1270000.00 600000 1000000 680000 14 14.41 9.16 +UZ Uzbekistan 447400.00 425400.00 22000.00 0 6221.00 27780059.00 32.40 62.80 4.80 1.73 14440000.00 1100000 1717000 880000 42 26.46 7.73 +VC Saint Vincent and the Grenadines 389.00 389.00 0.00 84 0.00 118149.00 25.90 67.60 6.50 0.25 41680.00 70600 22500 8000 15 16.02 5.97 +VE Venezuela 912050.00 882050.00 30000.00 2800 4993.00 26023528.00 31.60 63.40 5.10 1.49 12500000.00 12496000 3605000 3040000 16 21.22 5.08 +VI British Virgin Islands 153.00 153.00 0.00 80 0.00 23552.00 20.20 74.50 5.40 1.92 12770.00 8000 11700 4000 16 14.82 4.42 +VM Vietnam 329560.00 325360.00 4200.00 3444 4639.00 85262356.00 26.30 67.90 5.80 1.00 44580000.00 9593000 15845000 13100000 5 16.63 6.19 +VQ Virgin Islands 1910.00 346.00 1564.00 188 0.00 108448.00 21.80 66.50 11.70 -0.17 43980.00 64200 70900 30000 50 13.68 6.59 +VT Holy See 0.44 0.44 0.00 0 3.20 821.00 0.00 5120 93 +WA Namibia 825418.00 825418.00 0.00 1572 3936.00 2055080.00 37.70 58.60 3.80 0.48 653000.00 495000 127900 75000 2 23.52 19.15 +WE West Bank 5860.00 5640.00 220.00 0 404.00 2535927.00 42.40 54.20 3.40 2.99 568000.00 1095000 349000 243000 8 30.99 3.85 +WF Wallis and Futuna 274.00 274.00 0.00 129 0.00 16309.00 3104.00 0 1900 900 1 +WI Western Sahara 266000.00 266000.00 0.00 1110 2046.00 382617.00 45.40 52.30 2.30 12000.00 0 1 +WQ Wake Island 6.50 6.50 0.00 19 0.00 0.00 +WS Samoa 2944.00 2934.00 10.00 403 0.00 214265.00 38.10 56.30 5.60 1.29 90000.00 24000 13300 6000 2 28.28 5.88 +WZ Swaziland 17363.00 17203.00 160.00 0 535.00 1133066.00 40.30 56.10 3.60 -0.34 300000.00 200000 35000 36000 5 26.98 30.35 +XO Indian Ocean 68556000.00 66526 535.00 +XQ Arctic Ocean 14056000.00 45389 535.00 +YM Yemen 527970.00 527970.00 0.00 1906 1746.00 22230531.00 46.30 51.10 2.60 3.46 5759000.00 2075000 900000 220000 1 42.67 8.05 +ZA Zambia 752614.00 740724.00 11890.00 0 5664.00 11477447.00 45.70 51.90 2.40 1.66 4903000.00 946600 94700 231000 5 40.78 21.46 +ZH Atlantic Ocean 76762000.00 111866 5664.00 +ZI Zimbabwe 390580.00 386670.00 3910.00 0 3066.00 12311143.00 37.20 59.30 3.50 0.60 3958000.00 699000 328000 1000000 6 27.72 21.76 +ZN Pacific Ocean 155557000.00 135663 3066.00 +ZZ Iles Eparses 35 3066.00 0.00 diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/builddocs.sh b/interactive-mining-3rdparty-madis/madis/src/docs/builddocs.sh new file mode 100755 index 0000000..bff1635 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/builddocs.sh @@ -0,0 +1,2 @@ +python generate_function_doc.py +sphinx-build -E -b html ./source/ ./html diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/generate_function_doc.py b/interactive-mining-3rdparty-madis/madis/src/docs/generate_function_doc.py new file mode 100644 index 0000000..9097ace --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/generate_function_doc.py @@ -0,0 +1,65 @@ +import sys, os +sys.path.append((os.path.join(sys.path[0],'..'))) + +import functions +from shutil import copyfile + +functions.register() + +curpath = os.path.abspath(sys.path[0]) + +def gendoc(funtype, toplevelonly=False): + file=open(os.path.join(curpath, 'source', funtype+'.txt'),'w') + + tmpstr=".. _"+(funtype.lower()+' functions list:').replace(' ','-')+'\n\n' + tmpstr+=funtype[0].upper()+funtype[1:]+' functions list' + file.write(tmpstr+'\n') + file.write('='*len(tmpstr)+'\n\n') + file.write('.. automodule:: functions.'+funtype+'.__init__\n\n') + + docs={} + + if not toplevelonly: + for i,v in functions.functions[funtype].iteritems(): + if not v.__name__.startswith('functionslocal'): + if v.__module__ not in docs: + docs[v.__module__]=[] + docs[v.__module__].append(i) + else: + for i,v in functions.functions[funtype].iteritems(): + if not v.__name__.startswith('functionslocal'): + tstr='functions.vtable.'+i + if tstr not in docs: + docs[tstr]=True + + for i,v in sorted(docs.items()): + modulestr='.. module:: functions.'+funtype+'.'+i.split('.')[2]+'\n\n' + + if not toplevelonly: + modstr=':mod:`'+i.split('.')[2]+'` functions' + else: + modstr=':mod:`'+i.split('.')[2]+'` function' + file.write(modstr+'\n') + file.write('-'*len(modstr)+'\n\n') + file.write(modulestr) + file.write('') + + if not toplevelonly: + for i1 in sorted(v): + + tmpstr='**'+i1+' function**' + file.write(tmpstr) + if not functions.functions[funtype][i1].__doc__: + file.write('\n\n') + else: + file.write(str(functions.functions[funtype][i1].__doc__)+'\n\n') + else: + if not functions.functions[funtype][i.split('.')[-1]].__doc__: + file.write('\n\n') + else: + file.write(str(functions.functions[funtype][i.split('.')[-1]].__doc__)+'\n\n') + +copyfile(os.path.join(curpath, '..', 'LICENSE.txt'), os.path.join(curpath, 'source', 'license.txt')) +gendoc('row') +gendoc('aggregate') +gendoc('vtable', True) diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/html/readme.txt b/interactive-mining-3rdparty-madis/madis/src/docs/html/readme.txt new file mode 100644 index 0000000..76360d4 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/html/readme.txt @@ -0,0 +1,2 @@ +This directory contains Madis' html documentation. This directory isn't +tracked by mercurial \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/blank.gif b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/blank.gif new file mode 100644 index 0000000..8b27096 Binary files /dev/null and b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/blank.gif differ diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/easy/load.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/easy/load.js new file mode 100644 index 0000000..ce22bd8 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/easy/load.js @@ -0,0 +1,164 @@ +/********************************************************************** + * + * Customize the values given below to suit your needs. + * You can make additional copies of this file with + * different customizated settings if you need to load + * jsMath with different parameters. + * + * Load this page via: + * + * + * + * (If you are including this file into your page via Server-Side + * Includes, you should remove line above.) + * + * You can make copies of this file with different settings + * if you need to have several different configurations. + * + **********************************************************************/ + +if (!window.jsMath) {window.jsMath = {}} + +jsMath.Easy = { + // + // The URL of the root jsMath directory on your server + // (it must be in the same domain as the HTML page). + // It should include "http://yoursite.com/", or should + // be relative to the root of your server. It is possible + // to be a relative URL, but it will be relative to the + // HTML page loading this file. + // + // If you leave this blank, jsMath will try to look it up from + // the URL where it loaded this file, but that may not work. + // + root: "", + + // + // The default scaling factor for mathematics compared to the + // surrounding text. + // + scale: 120, + + // + // 1 means use the autoload plug-in to decide if jsMath should be loaded + // 0 means always load jsMath + // + autoload: 1, + + // + // Setting any of these will cause the tex2math plugin to be used + // to add the
and tags that jsMath needs. See the + // documentation for the tex2math plugin for more information. + // + processSlashParens: 1, // process \(...\) in text? + processSlashBrackets: 1, // process \[...\] in text? + processDoubleDollars: 1, // process $$...$$ in text? + processSingleDollars: 0, // process $...$ in text? + processLaTeXenvironments: 0, // process \begin{xxx}...\end{xxx} outside math mode? + fixEscapedDollars: 0, // convert \$ to $ outside of math mode? + doubleDollarsAreInLine: 0, // make $$...$$ be in-line math? + allowDisableTag: 1, // allow ID="tex2math_off" to disable tex2math? + // + // If you want to use your own custom delimiters for math instead + // of the usual ones, then uncomment the following four lines and + // insert your own delimiters within the quotes. You may want to + // turn off processing of the dollars and other delimiters above + // as well, though you can use them in combination with the + // custom delimiters if you wish. See the tex2math documentation + // for more details. + // + //customDelimiters: [ + // '[math]','[/math]', // to begin and end in-line math + // '[display]','[/display]' // to begin and end display math + //], + + // + // Disallow the use of the @(...) mechanism for including raw HTML + // in the contents of \hbox{}? (If used in a content-management system + // where users are allowed to enter mathematics, setting this to 0 + // would allow them to enter arbitrary HTML code within their + // math formulas, and that poses a security risk.) + // + safeHBoxes: 1, + + // + // Show TeX source when mathematics is double-clicked? + // + allowDoubleClicks: 1, + + // + // Show jsMath font warning messages? (Disabling this prevents yours + // users from finding out that they can have a better experience on your + // site by installing some fonts, so don't disable this). + // + showFontWarnings: 0, + + // + // Use "Process" or "ProcessBeforeShowing". See the jsMath + // author's documentation for the difference between these + // two routines. + // + method: "Process", + + // + // List of plug-ins and extensions that you want to be + // loaded automatically. E.g. + // ["plugins/mimeTeX.js","extensions/AMSsymbols.js"] + // + loadFiles: [], + + // + // List of fonts to load automatically. E.g. + // ["cmmib10"] + // + loadFonts: [], + + // + // List of macros to define. These are of the form + // name: value + // where 'value' is the replacement text for the macro \name. + // The 'value' can also be [value,n] where 'value' is the replacement + // text and 'n' is the number of parameters for the macro. + // Note that backslashes must be doubled in the replacement string. + // E.g., + // { + // RR: '{\\bf R}', + // bold: ['{\\bf #1}', 1] + // } + // + macros: {}, + + // + // Allow jsMath to enter global mode? + // (Uses frames, so may not always work with complex web sites) + // + allowGlobal: 1, + + // + // Disable image fonts? (In case you don't load them on your server.) + // + noImageFonts: 1 + +}; + +/****************************************************************/ +/****************************************************************/ +// +// DO NOT MAKE CHANGES BELOW THIS +// +/****************************************************************/ +/****************************************************************/ + +if (jsMath.Easy.root == "") { + jsMath.Easy.root = document.getElementsByTagName("script"); + jsMath.Easy.root = jsMath.Easy.root[jsMath.Easy.root.length-1].src + if (jsMath.Easy.root.match(/\/easy\/[^\/]*$/)) { + jsMath.Easy.root = jsMath.Easy.root.replace(/\/easy\/[^\/]*$/,""); + } else { + jsMath.Easy.root = jsMath.Easy.root.replace(/\/(jsMath\/(easy\/)?)?[^\/]*$/,"/jsMath"); + } +} +jsMath.Easy.root = jsMath.Easy.root.replace(/\/$/,""); // trim trailing "/" if any + +document.write(' + + + + + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-controls.html b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-controls.html new file mode 100644 index 0000000..e395ebe --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-controls.html @@ -0,0 +1,467 @@ + + + + + + + + + + + + +
+
+jsMath v +(type fonts) +[help] +

+ + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+
  + + + + + + + + + + +
+ +
+
+
+
+  + +
+
+
+
+
+  + + +
+Click the jsMath button or ALT-click +on mathematics to reopen this panel. +

+
+
+ + + +
+
+jsMath Options +[help] +

+

+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
Autoselect best font
Show font warnings
Use image alpha channels
Print image-font help
Always use hi-res fonts
Show progress messages
Force asynchronous processing
Don't show page until complete
Show jsMath button
+
+ + + + + + + + + + + + + + + + + + + + +
Scale all mathematics to %
+Use native TeX fonts +(download) +
+Use image fonts +( scalable)
+Use images for symbols only
+Use native Unicode fonts
Use Global mode + +
Save settings for + +
+ + + + + + +
  + +   + + +  +
+ +
+
+
+
+

+ + + + + + + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-easy-load.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-easy-load.js new file mode 100644 index 0000000..20a0dfa --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-easy-load.js @@ -0,0 +1,157 @@ +/* + * jsMath-easy-load.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file is used to load jsMath with one easy '); + +} else { + jsMath.Easy.tex2math = + (jsMath.Easy.processSingleDollars || + jsMath.Easy.processDoubleDollars || + jsMath.Easy.processSlashParens || + jsMath.Easy.processSlashBrackets || + jsMath.Easy.processLaTeXenvironments || + jsMath.Easy.fixEscapedDollars || + jsMath.Easy.customDelimiters); + + if (!jsMath.Setup) {jsMath.Setup = {}} + if (!jsMath.Setup.UserEvent) {jsMath.Setup.UserEvent = {}} + jsMath.Setup.UserEvent.onload = function () { + var easy = jsMath.Easy; + if (easy.tex2math) jsMath.Setup.Script("plugins/tex2math.js"); + var i; + if (easy.loadFiles) { + for (i = 0; i < easy.loadFiles.length; i++) + jsMath.Setup.Script(easy.loadFiles[i]); + } + if (easy.loadFonts) { + for (i = 0; i < easy.loadFonts.length; i++) + jsMath.Font.Load(easy.loadFonts[i]); + } + if (easy.macros) { + for (i in easy.macros) { + if (typeof(easy.macros[i]) == 'string') { + jsMath.Macro(i,easy.macros[i]); + } else { + jsMath.Macro(i,easy.macros[i][0],easy.macros[i][1]); + } + } + } + } + document.write(''+"\n"); +} + +jsMath.Easy.onload = function () { + if (jsMath.Easy.loaded) {return} else {jsMath.Easy.loaded = 1} + if (jsMath.Easy.autoloadCheck) jsMath.Autoload.Check(); + if (jsMath.Easy.tex2math) { + jsMath.Synchronize(function () { + if (jsMath.Easy.findCustomSettings) + jsMath.tex2math.Convert(document,jsMath.Easy.findCustomSettings); + if (jsMath.Easy.customDelimiters) { + var s = jsMath.Easy.customDelimiters; + jsMath.tex2math.CustomSearch(s[0],s[1],s[2],s[3]); + jsMath.tex2math.ConvertCustom(); + } + }); + } + (jsMath[jsMath.Easy.method])(); +} + +if (window.addEventListener) {window.addEventListener("load",jsMath.Easy.onload,false)} +else if (window.attachEvent) {window.attachEvent("onload",jsMath.Easy.onload)} +else {window.onload = jsMath.Easy.onload} diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-mac-mozilla.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-mac-mozilla.js new file mode 100644 index 0000000..bd2d429 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-mac-mozilla.js @@ -0,0 +1,107 @@ +/* + * jsMath-fallback-mac-mozilla.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file makes changes needed by Mozilla-based browsers on the Mac + * for when the TeX fonts are not available. + * + * --------------------------------------------------------------------- + * + * Copyright 2004-2006 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +/******************************************************************** + * + * Fix the default non-TeX-font characters to work with Mozilla + * + */ + +jsMath.Update.TeXfonts({ + cmmi10: { +// '41': // leftharpoondown +// '43': // rightharpoondown + '44': {c: '˓'}, + '45': {c: '˒'}, + '47': {c: ''}, +// '92': // natural + '126': {c: ''} + }, + + cmsy10: { + '0': {c: '–', tclass: 'normal'}, + '11': {c: '/', tclass: 'normal'}, + '42': {c: '⥣'}, '43': {c: '⥥'}, + '48': {c: '', tclass: 'normal'}, + '93': {c: '∪+'}, + '104': {c: ''}, + '105': {c: ''}, + '109': {c: '⥣'} +//, '116': // sqcup +// '117': // sqcap +// '118': // sqsubseteq +// '119': // sqsupseteq + }, + + cmex10: { + '10': {c: ''}, + '11': {c: ''}, + '14': {c: '/'}, '15': {c: '\\'}, + '28': {c: ''}, + '29': {c: ''}, + '30': {c: '/'}, '31': {c: '\\'}, + '42': {c: ''}, + '43': {c: ''}, + '44': {c: '/'}, '45': {c: '\\'}, + '46': {c: '/'}, '47': {c: '\\'}, + '68': {c: ''}, + '69': {c: ''}, +// '70': // sqcup +// '71': // big sqcup + '72': {ic: .194}, '73': {ic: .444}, + '82': {tclass: 'bigop1cx', ic: .15}, '90': {tclass: 'bigop2cx', ic:.6}, + '85': {c: '∪+'}, + '93': {c: '∪+'} + } + +}); + +jsMath.Setup.Styles({ + '.typeset .symbol': "font-family: Osaka", + '.typeset .arrow1': "font-family: Osaka; position: relative; top: .125em; margin: -1px", + '.typeset .arrow2': "font-family: AppleGothic; font-size: 100%; position:relative; top: .11em; margin:-1px", + '.typeset .bigop1': "font-family: AppleGothic; font-size: 110%; position:relative; top: .9em; margin:-.05em", + '.typeset .bigop1b': "font-family: Osaka; font-size: 140%; position: relative; top: .8em; margin:-.1em", + '.typeset .bigop1c': "font-family: AppleGothic; font-size: 125%; position:relative; top: .85em; margin:-.3em", + '.typeset .bigop1cx': "font-family: 'Apple Chancery'; font-size: 125%; position:relative; top: .7em; margin:-.1em", + '.typeset .bigop2': "font-family: AppleGothic; font-size: 175%; position:relative; top: .85em; margin:-.1em", + '.typeset .bigop2b': "font-family: Osaka; font-size: 200%; position: relative; top: .75em; margin:-.15em", + '.typeset .bigop2c': "font-family: AppleGothic; font-size: 300%; position:relative; top: .75em; margin:-.35em", + '.typeset .bigop2cx': "font-family: 'Apple Chancery'; font-size: 250%; position:relative; top: .7em; margin-left:-.1em; margin-right:-.2em", + '.typeset .delim1b': "font-family: Times; font-size: 150%; position:relative; top:.8em; margin:.01em", + '.typeset .delim2b': "font-family: Times; font-size: 210%; position:relative; top:.8em; margin:.01em", + '.typeset .delim3b': "font-family: Times; font-size: 300%; position:relative; top:.75em; margin:.01em", + '.typeset .delim4b': "font-family: Times; font-size: 400%; position:relative; top:.725em; margin:.01em" +}); + + +/* + * replace \not and \joinrel with better dimensions + */ + +jsMath.Macro('not','\\mathrel{\\rlap{\\kern 3mu/}}'); +jsMath.Macro('joinrel','\\mathrel{\\kern-3mu}'); diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-mac-msie.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-mac-msie.js new file mode 100644 index 0000000..97bd15e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-mac-msie.js @@ -0,0 +1,200 @@ +/* + * jsMath-fallback-mac-msie.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file makes changes needed by Internet Explorer on the Mac + * for when the TeX fonts are not available. + * + * --------------------------------------------------------------------- + * + * Copyright 2004-2006 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +/******************************************************************** + * + * Fix the default non-TeX-font characters to work with MSIE + * + */ + +jsMath.Update.TeXfonts({ + cmr10: { + '0': {c: 'G', tclass: 'greek'}, + '1': {c: 'D', tclass: 'greek'}, + '2': {c: 'Q', tclass: 'greek'}, + '3': {c: 'L', tclass: 'greek'}, + '4': {c: 'X', tclass: 'greek'}, + '5': {c: 'P', tclass: 'greek'}, + '6': {c: 'S', tclass: 'greek'}, + '7': {c: '¡', tclass: 'greek'}, + '8': {c: 'F', tclass: 'greek'}, + '9': {c: 'Y', tclass: 'greek'}, + '10': {c: 'W', tclass: 'greek'}, + '22': {c: '`', tclass: 'symbol3'} + }, + + cmti10: { + '0': {c: 'G', tclass: 'igreek'}, + '1': {c: 'D', tclass: 'igreek'}, + '2': {c: 'Q', tclass: 'igreek'}, + '3': {c: 'L', tclass: 'igreek'}, + '4': {c: 'X', tclass: 'igreek'}, + '5': {c: 'P', tclass: 'igreek'}, + '6': {c: 'S', tclass: 'igreek'}, + '7': {c: '¡', tclass: 'igreek'}, + '8': {c: 'F', tclass: 'igreek'}, + '9': {c: 'Y', tclass: 'igreek'}, + '10': {c: 'W', tclass: 'igreek'}, + '22': {c: '`', tclass: 'symbol3'} + }, + + cmbx10: { + '0': {c: 'G', tclass: 'bgreek'}, + '1': {c: 'D', tclass: 'bgreek'}, + '2': {c: 'Q', tclass: 'bgreek'}, + '3': {c: 'L', tclass: 'bgreek'}, + '4': {c: 'X', tclass: 'bgreek'}, + '5': {c: 'P', tclass: 'bgreek'}, + '6': {c: 'S', tclass: 'bgreek'}, + '7': {c: '¡', tclass: 'bgreek'}, + '8': {c: 'F', tclass: 'bgreek'}, + '9': {c: 'Y', tclass: 'bgreek'}, + '10': {c: 'W', tclass: 'bgreek'}, + '22': {c: '`', tclass: 'symbol3'} + }, + cmmi10: { + '0': {c: 'G', tclass: 'igreek'}, + '1': {c: 'D', tclass: 'igreek'}, + '2': {c: 'Q', tclass: 'igreek'}, + '3': {c: 'L', tclass: 'igreek'}, + '4': {c: 'X', tclass: 'igreek'}, + '5': {c: 'P', tclass: 'igreek'}, + '6': {c: 'S', tclass: 'igreek'}, + '7': {c: '¡', tclass: 'igreek'}, + '8': {c: 'F', tclass: 'igreek'}, + '9': {c: 'Y', tclass: 'igreek'}, + '10': {c: 'W', tclass: 'igreek'}, + '11': {c: 'a', tclass: 'greek'}, + '12': {c: 'b', tclass: 'greek'}, + '13': {c: 'g', tclass: 'greek'}, + '14': {c: 'd', tclass: 'greek'}, + '15': {c: 'e', tclass: 'greek'}, + '16': {c: 'z', tclass: 'greek'}, + '17': {c: 'h', tclass: 'greek'}, + '18': {c: 'q', tclass: 'greek'}, + '19': {c: 'i', tclass: 'greek'}, + '20': {c: 'k', tclass: 'greek'}, + '21': {c: 'l', tclass: 'greek'}, + '22': {c: 'm', tclass: 'greek'}, + '23': {c: 'n', tclass: 'greek'}, + '24': {c: 'x', tclass: 'greek'}, + '25': {c: 'p', tclass: 'greek'}, + '26': {c: 'r', tclass: 'greek'}, + '27': {c: 's', tclass: 'greek'}, + '28': {c: 't', tclass: 'greek'}, + '29': {c: 'u', tclass: 'greek'}, + '30': {c: 'f', tclass: 'greek'}, + '31': {c: 'c', tclass: 'greek'}, + '32': {c: 'y', tclass: 'greek'}, + '33': {c: 'w', tclass: 'greek'}, +// '41': // leftharpoondown +// '43': // rightharpoondown +// '44': // hook left +// '45': // hook right +// '92': // natural + '94': {c: ''}, + '95': {c: ''} +// '127': // half-circle down accent? + }, + + cmsy10: { + '0': {c: '–', tclass: 'normal'}, + '11': {c: '/', tclass: 'normal'}, + '16': {c: '', tclass: 'normal'}, + '48': {c: ''}, + '93': {c: '∪+'}, + '96': {c: '|', tclass: 'normal'}, + '104': {c: ''}, + '105': {c: ''}, + '109': {c: '⇑'}, + '110': {c: '\\', d:0, tclass: 'normal'} +// '111': // wr +//, '113': // amalg +// '116': // sqcup +// '117': // sqcap +// '118': // sqsubseteq +// '119': // sqsupseteq + }, + + cmex10: { + '10': {c: ''}, + '11': {c: ''}, + '14': {c: '/'}, '15': {c: '\\'}, + '28': {c: ''}, + '29': {c: ''}, + '30': {c: '/'}, '31': {c: '\\'}, + '42': {c: ''}, + '43': {c: ''}, + '44': {c: '/'}, '45': {c: '\\'}, + '46': {c: '/'}, '47': {c: '\\'}, + '68': {c: ''}, + '69': {c: ''}, +// '70': // sqcup +// '71': // big sqcup + '72': {ic: 0}, '73': {ic: 0}, + '82': {tclass: 'bigop1cx', ic: .15}, '90': {tclass: 'bigop2cx', ic:.6}, + '85': {c: '∪+'}, + '93': {c: '∪+'}, +// '96': // coprod +// '97': // big coprod + '98': {c: '︿', h: 0.722, w: .58, tclass: 'wide1'}, + '99': {c: '︿', h: 0.722, w: .58, tclass: 'wide2'}, + '100': {c: '︿', h: 0.722, w: .58, tclass: 'wide3'}, + '101': {c: '~', h: 0.722, w: .42, tclass: 'wide1a'}, + '102': {c: '~', h: 0.8, w: .73, tclass: 'wide2a'}, + '103': {c: '~', h: 0.8, w: 1.1, tclass: 'wide3a'} + } + +}); + +jsMath.Setup.Styles({ + '.typeset .arrow1': "font-family: Osaka; position: relative; top: .125em; margin: -1px", + '.typeset .arrow2': "font-family: Osaka; position: relative; top: .1em; margin:-1px", + '.typeset .bigop1': "font-family: Symbol; font-size: 110%; position:relative; top: .8em; margin:-.05em", + '.typeset .bigop1b': "font-family: Symbol; font-size: 140%; position: relative; top: .8em; margin:-.1em", + '.typeset .bigop1c': "font-family: Osaka; font-size: 125%; position:relative; top: .85em; margin:-.3em", + '.typeset .bigop1cx': "font-family: 'Apple Chancery'; font-size: 125%; position:relative; top: .7em; margin:-.1em", + '.typeset .bigop2': "font-family: Symbol; font-size: 175%; position:relative; top: .8em; margin:-.07em", + '.typeset .bigop2a': "font-family: Baskerville; font-size: 175%; position: relative; top: .65em", + '.typeset .bigop2b': "font-family: Symbol; font-size: 175%; position: relative; top: .8em; margin:-.07em", + '.typeset .bigop2c': "font-family: Osaka; font-size: 230%; position:relative; top: .85em; margin:-.35em", + '.typeset .bigop2cx': "font-family: 'Apple Chancery'; font-size: 250%; position:relative; top: .6em; margin-left:-.1em; margin-right:-.2em", + '.typeset .delim1b': "font-family: Times; font-size: 150%; position:relative; top:.8em", + '.typeset .delim2b': "font-family: Times; font-size: 210%; position:relative; top:.75em;", + '.typeset .delim3b': "font-family: Times; font-size: 300%; position:relative; top:.7em;", + '.typeset .delim4b': "font-family: Times; font-size: 400%; position:relative; top:.65em;", + '.typeset .symbol3': "font-family: Symbol", + '.typeset .wide1': "font-size: 50%; position: relative; top:-1.1em", + '.typeset .wide2': "font-size: 80%; position: relative; top:-.7em", + '.typeset .wide3': "font-size: 125%; position: relative; top:-.5em", + '.typeset .wide1a': "font-size: 75%; position: relative; top:-.5em", + '.typeset .wide2a': "font-size: 133%; position: relative; top: -.15em", + '.typeset .wide3a': "font-size: 200%; position: relative; top: -.05em", + '.typeset .greek': "font-family: Symbol", + '.typeset .igreek': "font-family: Symbol; font-style:italic", + '.typeset .bgreek': "font-family: Symbol; font-weight:bold" +}); diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-mac.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-mac.js new file mode 100644 index 0000000..e9e1831 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-mac.js @@ -0,0 +1,29 @@ +/* + * jsMath-fallback-mac.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file makes changes needed for when the TeX fonts are not available + * with a browser on the Mac. + * + * --------------------------------------------------------------------- + * + * Copyright 2004-2006 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +jsMath.Script.Uncompress([ + ['jsMath.Add(jsMath.TeX,{cmr10',':[{c:"Γ",','tclass:"greek"},{c:"&','Delta;",',2,'Theta;",',2,'Lambda;",',2,'Xi;",',2,'Pi;",',2,'Sigma;",',2,'Upsilon;",',2,'Phi;",',2,'Psi;",',2,'Omega;",','tclass:"','greek','"},{c:"','ff','",ic:0.0778,krn:{"39":0.0778,"63":0.0778,"33":0.0778,"41":0.0778,"93":0.0778},lig:{"105":','14,"108":15},','tclass:"normal"},{c',':"fi",',28,':"fl",',28,':"ffi",',28,':"ffl",',28,':"ı',';",a:0,',28,':"j",d:0.2,',28,':"`",',22,'accent','"},{c:"&#','xB4;",',22,44,45,'x2C7;",',22,44,45,'x2D8;",',22,44,'"},{c:"ˉ',';",',22,44,45,'x2DA;",',22,44,45,'x0327;",',28,':"ß",',28,':"æ',38,28,':"œ',38,28,':"ø",',28,':"Æ",',28,':"Œ",',28,':"Ø",',28,':"?",krn:{"108":-0.278,"76":-0.319},',28,':"!",lig:{"96":60},',28,':"”",',28,':"#",',28,':"$",',28,':"%",',28,':"&",',28,':"’",krn:{"63":0.111,"33":0.','111},','lig:{"39":34},',28,':"(",','d:0.2,',28,':")",',105,28,':"*",',28,':"+",','a:0.1,',28,':",",a:-','0.3,d:0.2,','w:0.278,',28,':"-",a:0,lig:{"45":123},',28,':".",a:-0.','25,',28,':"/",',28,':"0",',28,':"1",',28,':"2",',28,':"3",',28,':"4",',28,':"5",',28,':"6",',28,':"7",',28,':"8",',28,':"9",',28,':":",',28,':";",',28,':"¡",',28,':"=",','a:0,d:-0.','1,',28,':"¿",',28,':"?",lig:{"96":62},',28,':"@",',28,':"A','",krn:{"','116','":-0.0278,"','67',165,'79',165,'71',165,'85',165,'81',165,'84','":-0.0833,"','89',177,'86','":-0.111',',"87":-0.',101,28,':"B",',28,':"C",',28,':"D',163,'88',165,'87',165,'65',165,'86',165,'89','":-0.0278','},',28,':"E",',28,':"F',163,'111',177,'101',177,'117','":-0.0833,"114":-0.0833,"97":-0.0833,"65":-0.','111,"79',165,'67',165,'71',165,'81',200,'},',28,':"G",',28,':"H",',28,':"I',163,'73":0.','0278','},',28,':"J",',28,':"K',163,'79',165,'67',165,'71',165,'81',200,'},',28,':"L',163,'84',177,'89',177,'86',181,182,101,28,':"M",',28,':"N",',28,':"O',163,'88',165,'87',165,'65',165,'86',165,'89',200,'},',28,':"P',163,'65',177,'111',165,'101',165,'97',165,'46',177,'44":-0.0833},',28,':"Q",','d:0.1,',28,':"R',163,'116',165,'67',165,'79',165,'71',165,'85',165,'81',165,'84',177,'89',177,'86',181,182,101,28,':"S",',28,':"T',163,'121',165,'101',177,'111',212,'0833,"117":-0.0833','},',28,':"U",',28,':"V",','ic:0.0139,krn:{"','111',177,'101',177,'117',212,'111,"79',165,'67',165,'71',165,'81',200,'},',28,':"W",',332,'111',177,'101',177,'117',212,'111,"79',165,'67',165,'71',165,'81',200,'},',28,':"X',163,'79',165,'67',165,'71',165,'81',200,'},',28,':"Y",ic:0.025,','krn:{"101',177,'111',212,326,'},',28,':"Z",',28,':"[",',291,28,':"“",',28,':"]",',291,28,':"ˆ",',22,44,45,'x2D9;",',22,44,45,'x2018;",lig:{"96":92},',28,':"a','",a:0,krn:{"','118',165,'106":0.','0556,"121',165,'119',200,'},',28,':"b',163,'101','":0.0278,"','111',421,'120',165,'100',421,'99',421,'113',421,'118',165,411,'0556,"121',165,'119',200,'},',28,':"c',408,'104',165,'107',200,'},',28,':"d",',28,':"e",a:0,',28,':"f',26,'12,"102":11,"108":13},',28,':"g",','a:0,d:0.2,ic:0.','0139,krn:{"',411,230,'},',28,':"h',163,'116',165,'117',165,'98',165,'121',165,'118',165,'119',200,'},',28,':"i",',28,40,28,':"k',163,'97','":-0.0556,"','101',165,'97',165,'111',165,'99',200,'},',28,':"l",',28,':"m',408,'116',165,'117',165,'98',165,'121',165,'118',165,'119',200,'},',28,':"n',408,'116',165,'117',165,'98',165,'121',165,'118',165,'119',200,'},',28,':"o',408,'101',421,'111',421,'120',165,'100',421,'99',421,'113',421,'118',165,411,'0556,"121',165,'119',200,'},',28,':"p",a:0,',105,380,421,'111',421,'120',165,'100',421,'99',421,'113',421,'118',165,411,'0556,"121',165,'119',200,'},',28,':"q",a:0,',105,28,':"','r",a:0,',28,':"s",a:0,',28,':"t',163,'121',165,'119',200,'},',28,':"u',408,'119',200,'},',28,':"v",a:0,',332,'97',487,'101',165,'97',165,'111',165,'99',200,'},',28,':"w",a:0,',332,'101',165,'97',165,'111',165,'99',200,'},',28,':"x",a:0,',28,':"y",',458,459,'111',165,'101',165,'97',165,'46',177,'44":-0.0833},',28,':"z",a:0,',28,':"–',';",a:0.1,','ic:0.0278,','lig:{"45":124},',28,':"—',644,645,28,':"˝",',22,44,45,'x2DC;",',22,44,45,'xA8;",',22,44,'"}],cmmi10',1,'ic:0.139',',krn:{"61":-0.0556,"59":-0.111,"58":-0.111,"127":0.','0833},',22,'igreek"},{c:"&',3,'krn:{"127":0.','167},',22,669,5,'ic:0.',230,',krn:{"127":0.','0833},',22,669,7,671,'167},',22,669,9,'ic:0.0757',678,'0833},',22,669,11,'ic:0.0812,krn:{"61',487,'59":-0.0556,"58":-0.0556,"127":0.','0556},',22,669,13,'ic:0.0576',678,'0833},',22,669,15,'ic:0.139',666,'0556},',22,669,17,671,'0833},',22,669,19,'ic:0.11,krn:{"61',487,696,'0556},',22,669,21,'ic:0.0502',678,'0833},',22,669,'alpha',';",a:0,ic:0.','0037',678,230,'},',2,'beta;",','d:0.2,ic:0.','0528',678,'0833},',2,'gamma;",',458,'0556,',2,'delta;",ic:0.0378,krn:{"',696,'0556},',2,'epsilon;",a:0',678,'0556},',22,'lucida"},{c:"ζ",',738,'0738',678,'0833},',2,'eta;",',458,'0359',678,'0556},',2,'theta;",ic:0.',230,678,'0833},',2,'iota;",a:0',678,'0556},',2,'kappa',38,2,'lambda;",',2,'mu',38,'d:0.2',678,230,'},',2,'nu',731,'0637,krn:{"',696,230,'},',2,'xi;",',738,'046',678,101,2,'pi',731,'0359,',2,'rho',38,'d:0.2',678,'0833},',2,'sigma',731,803,'krn:{"59',487,'58":-0.0556','},',2,'tau',731,'113,krn:{"',696,230,'},',2,'upsilon',731,'0359',678,230,'},',2,'phi',644,'d:0.2',678,'0833},',2,'chi',38,'d:0.2',678,'0556},',2,'psi',644,738,'0359',678,101,2,'omega',731,803,2,'epsilon;",a:0',678,'0833},',22,'greek',45,'x3D1;",',671,'0833},',28,':"ϖ',731,230,',',28,':"ϱ',38,'d:0.2',678,'0833},',28,':"ς",',458,'0799',678,'0833},',28,':"ϕ',644,'d:0.2',678,'0833},',28,':"↼",',153,'2,',22,'harpoon',45,'x21BD;",',153,'1,',22,'harpoon',45,'x21C0;",',153,'2,',22,'harpoon',45,'x21C1;",',153,'1,',22,'harpoon',57,'font-size',': 133%; ',58,':.1em; margin:-.2em; left:-.05em\\">&#','x02D3',60,113,22,'lucida',57,913,914,58,916,'x02D2',60,113,22,'lucida',57,913,':50%\\">&#','x25B7',60,22,'symbol',57,913,934,'x25C1',60,22,938,24,'0",',28,':"1",',28,':"2",',28,':"3",',28,':"4",',28,':"5",',28,':"6",',28,':"7",',28,':"8",',28,':"9",',28,121,'3,',28,':",",a:-',116,28,':"<',644,28,':"/",',291,'krn:{"1',487,'65',487,'77',487,'78',487,'89":0.0556,"90":-0.0556},',28,':">',644,28,976,913,934,'x2605',60,'a:0,','tclass:"symbol"},{c:"&#','x2202;",ic:0.0556',678,'0833},',28,':"A",',671,'139','},tclass:"italic"},{c:"','B",ic:0.0502',678,'0833',1010,'C",ic:0.0715,krn:{"61',165,696,'0833',1010,'D",ic:0.',230,678,'0556',1010,'E",ic:0.0576',678,'0833',1010,'F",ic:0.139',666,'0833',1010,'G",',671,'0833',1010,'H",ic:0.0812,krn:{"61',487,696,'0556',1010,'I",ic:0.0785',678,'111',1010,'J",ic:0.0962',666,'167',1010,'K",ic:0.0715,krn:{"61',487,696,'0556',1010,'L",',671,230,1010,'M','",ic:0.109,krn:{"','61',487,696,'0833',1010,'N',1060,'61',177,'61',165,696,'0833',1010,'O",ic:0.',230,678,'0833',1010,'P",ic:0.139',666,'0833',1010,'Q",d:0.2',678,'0833',1010,'R",ic:0.00773',678,'0833',1010,'S",ic:0.0576,krn:{"61',487,696,'0833',1010,'T','",ic:0.139,krn:{"','61',165,696,'0833',1010,'U',1060,'59',181,',"58',181,',"61',487,'127":0.',230,1010,'V",ic:0.222,krn:{"59','":-0.167,"','58',1116,'61',181,1010,'W',1098,'59',1116,'58',1116,'61',181,1010,'X",ic:0.0785,krn:{"61',177,'61',165,696,'0833',1010,'Y",ic:0.222,krn:{"59',1116,'58',1116,'61',181,1010,'Z",ic:0.0715,krn:{"61',487,696,'0833},',22,'italic',45,'x266D;",',22,'symbol2',45,'x266E;",',22,'symbol2',45,'x266F;",',22,'symbol2',57,'position: relative; top',':.5em\\">⌣',60,153,'1,',28,976,1164,':-.3em\\">⌢',60,153,'1,',28,':"ℓ",',671,101,22,938,24,'a",a:0,',22,'italic"},{c:"','b",',22,1185,'c",a:0',678,'0556',1010,'d',163,'89":0.0556,"90',487,'106',181,',"102',1116,1112,'167',1010,'e",a:0',678,'0556',1010,'f",',738,'108,krn:{"',696,'167',1010,'g",',458,'0359',678,230,1010,'h',163,'127',200,1010,'i",',22,1185,'j",',738,'0572,krn:{"59',487,816,1010,'k",ic:0.0315,',22,1185,'l",ic:0.0197',678,'0833',1010,'m",a:0,',22,1185,'n",a:0,',22,1185,'o",a:0',678,'0556',1010,'p",a:0,d:0.2',678,'0833',1010,'q",',458,'0359',678,'0833',1010,582,645,'krn:{"',696,'0556',1010,'s",a:0',678,'0556',1010,'t",',671,'0833',1010,'u",a:0',678,230,1010,'v",a:0,ic:0.0359',678,230,1010,'w",a:0,ic:0.0269',678,'0833',1010,'x",a:0',678,230,1010,'y",',458,'0359',678,'0556',1010,'z",a:0,ic:0.044',678,'0556},',22,'italic',45,'x131;",a:0',678,230,1010,'j",d:0.2',678,'0833},',22,'italic',45,'x2118',38,'d:0.2',678,101,28,976,'position:relative; left: .4em; top: -.8em; ',913,': 50%\\">→',60,'ic:0.154,',1002,'x0311;",ic:0.399,',22,'normal"}],cmsy10:[{c:"−',644,1002,'xB7;",',153,'2,',1002,'xD7',38,22,938,57,58,':.3em\\">*',60,'a:0,',1002,'xF7',38,1002,'x25CA;",',22,'lucida',45,'xB1',644,1002,'x2213;",',1002,'x2295;",',1002,'x2296;",',1002,'x2297;",',1002,'x2298;",',1002,'x2299;",',22,'symbol3',45,'x25EF;",',22,938,57,58,':.25em;\\">°',60,153,'1,',1002,'x2022;",',153,'2,',1002,'x224D',644,1002,'x2261',644,1002,'x2286;",',1002,'x2287;",',1002,'x2264;",',1002,'x2265;",',1002,'x227C;",',1002,'x227D;",',22,938,'"},{c:"~",',153,'2,',28,':"≈',644,'d:-0.1,',1002,'x2282;",',1002,'x2283;",',1002,'x226A;",',1002,'x226B;",',1002,'x227A;",',1002,'x227B;",',1002,'x2190;",',153,'15,',22,'arrow1',45,'x2192;",',153,'15,',22,'arrow1',45,'x2191',';",h:1,',22,'arrow1a',45,'x2193',1435,22,'arrow1a',45,'x2194',38,22,'arrow1',45,'x2197',1435,22,'arrows',45,'x2198',1435,22,'arrows',45,'x2243',644,1002,'x21D0',644,22,'arrow2',45,'x21D2',644,22,'arrow2',45,'x21D1;",h:0.9,',291,22,'arrow2a',45,'x21D3;",h:0.9,',291,22,'arrow2a',45,'x21D4',644,22,'arrow2',45,'x2196',1435,22,'arrows',45,'x2199',1435,22,'arrows',45,'x221D',644,22,938,57,913,914,'margin-right',': -.1em; ',1164,':.4em\\">′',60,'a:0,',22,'lucida',45,'x221E',644,1002,'x2208;",',1002,'x220B;",',1002,'x25B3;",',1002,'x25BD;",',22,938,'"},{c:"/",',22,938,57,913,':50%; ',58,':-.3em; ',1504,':-.2em\\">|&#','x2216',60,'a:0.3,',291,22,'lucida',57,913,': 75%; margin:-.3em\\">≀',60,22,938,57,58,': .86em\\">√',60,'h:0.04,d:0.9,',22,'lucida',45,'x2210;",a:0.4,',1002,'x2207;",',1002,'x222B',1435,291,'ic:0.111,',22,'root',45,'x2294;",',1002,'x2293;",',1002,'x2291;",',1002,'x2292;",',1002,'xA7;",',291,28,':"†",',291,28,':"‡",',291,28,':"¶",a:0.3,',291,22,'lucida',45,'x2663;",',1002,'x2666;",',1002,'x2665;",',1002,'x2660;",',22,938,'"}],cmex10:[{c',104,'h:0.04,d:1.16,n:','16,',22,'delim1"},{c',107,1828,'17,',22,1831,389,1828,'104,',22,1831,394,1828,'105,',22,'delim1',45,1718,'",',1828,'106,',22,'delim1',45,'xF8FB',';",h:0.04,d:','1.16,n:','107,',22,'delim1',45,'xF8EE',1856,1857,'108,',22,'delim1',45,'xF8F9',1856,1857,'109,',22,1831,1731,1828,'110,',22,1831,1734,1828,'111,',22,'delim1',45,'x3008',1856,1857,'68,',22,'delim1c',45,'x3009',1856,1857,'69,',22,'delim1c"},{c',1743,'h:0.7,d:0.15,delim:{','rep:12},',22,'vertical1',1747,1900,'rep:13},',22,'vertical1',45,'x2215',1856,1857,'46,',22,'delim1b',45,1764,1856,1857,'47,',22,'delim1b"},{c',104,'h:0.04,d:1.76,n:','18,',22,'delim2"},{c',107,1924,'19,',22,1927,104,'h:0.04,d:2.36,n:','32,',22,'delim3"},{c',107,1934,'33,',22,1937,389,1934,'34,',22,1937,394,1934,'35,',22,'delim3',45,1718,1856,'2.36,n:','36,',22,'delim3',45,'xF8FB',1856,1956,'37,',22,'delim3',45,'xF8EE',1856,1956,'38,',22,'delim3',45,'xF8F9',1856,1956,'39,',22,'delim3',57,'margin: -.1em','\\">{}{}{",',138,'26,',6,141,'"},{c:"<',172,173,'\\">}
",',138,'27,',6,141,'"},{c:"",h:0.','04,d:1.16,n:113,',6,'root',187,'190',189,'925em',191,'04,d:1.76,n:114,',6,194,187,'250',189,'925em',191,'06,d:2.36,n:115,',6,194,187,'320',189,'92em',191,'08,d:2.96,n:116,',6,194,187,'400',189,'92em',191,'1,d:3.75,n:117,',6,194,187,'500',189,'9em',191,'12,d:4.5,n:118,',6,194,187,'625',189,'9em',191,'14,d:5.7,',6,194,'"},{c:"||",h:0.65,d:0.15',',delim:{top:126,','bot:127,rep:119},',6,'vertical2',2,'x25B5;",h:0.','4,delim:{top:120,rep:63},',6,'arrow1b',2,'x25BF;",h:0.','38,delim:{bot:121,rep:63},',6,252,187,'67',189,'35em','; margin-left:-.','5em\\">╭',';",','h:0.1,',6,'symbol',187,'67',189,'35em; margin-right:-.5em\\">&#','x256E',264,265,6,267,187,'67',189,'35em',262,'5em\\">╰',264,265,6,267,187,'67',189,271,'x256F',264,265,6,267,2,249,'5',244,'rep:119},',6,'arrow2b',2,254,'6,d:-0.1,delim:{bot:127,rep:119},',6,302,'"}],cmti10',':[{c:"Γ",',11,'133,',6,'igreek"},{c:"&','Delta;",',6,313,'Theta;",','ic:0.094,',6,313,'Lambda;",',6,313,'Xi;",',11,'153,',6,313,'Pi;",',11,'164,',6,313,'Sigma;",',11,'12,',6,313,'Upsilon;",',11,'111,',6,313,'Phi;",',11,'0599,',6,313,'Psi;",',11,341,6,313,'Omega;",','ic:0.103,',6,'igreek','"},{c:"ff','",ic:0.212,krn:{"39":0.104,"63":0.104,"33":0.104,"41":0.104,"93":0.104},lig:{"105":','14,"108":15},','tclass:"italic"},{c',':"fi','",ic:0.103,',361,':"fl',363,361,':"ffi',363,361,':"ffl',363,361,':"ı",a:0,',11,'0767,',361,':"j",d:0.2,',11,'0374,',361,':"`",',6,'iaccent',2,'xB4;",',11,'0969,',6,384,2,'x2C7;",',11,'083,',6,384,2,'x2D8;",',11,'108,',6,384,2,'x2C9;",',355,6,384,2,'x2DA;",',6,384,'"},{c:"?",','d:0.17,w:0.46,',361,':"ß",',11,'105,',361,':"æ",a:0,','ic:0.0751,',361,':"œ",a:0,',420,361,':"ø",',11,'0919,',361,':"Æ",',11,'12,',361,':"Œ",',11,'12,',361,':"Ø",',318,361,':"?",krn:{"108":-0.','256,"76":-0.321},',361,':"!",','ic:0.124,lig:{"96":','60},',361,':"”",',11,'0696,',361,':"#",',11,'0662,',361,':"$",',361,':"%",',11,'136,',361,':"&",',11,'0969,',361,':"’",',11,'124,','krn:{"63":0.','102,"33":0.102},lig:{"39":34},',361,':"(",d:0.2,',11,'162,',361,':")",d:0.2,',11,'0369,',361,':"*",',11,'149,',361,':"+",a:0.1,',11,'0369,',361,':",",a:-0.3,d:0.2,w:0.278,',361,':"-",a:0,',11,'0283',',lig:{"45":','123},',361,':".",a:-0.25,',361,':"/",',11,'162,',361,':"0",',11,'136,',361,':"1",',11,'136,',361,':"2",',11,'136,',361,':"3",',11,'136,',361,':"4",',11,'136,',361,':"5",',11,'136,',361,':"6",',11,'136,',361,':"7",',11,'136,',361,':"8",',11,'136,',361,':"9",',11,'136,',361,':":",',11,'0582,',361,':";",',11,'0582,',361,':"¡",',11,'0756,',361,':"=",a:0,d:-0.1,',11,'0662,',361,':"¿",',361,':"?",','ic:0.122,','lig:{"96":','62},',361,':"@",',11,'096,',361,':"A",','krn:{"110":-0.0256,"108":-0.0256,"114":-0.0256,"117":-0.0256,"109":-0.0256,"116":-0.0256,"105":-0.0256,"67":-0.0256,"79":-0.0256,"71":-0.0256,"104":-0.0256,"98":-0.0256,"85":-0.0256,"107":-0.0256,"118":-0.0256,"119":-0.0256,"81":-','0.0256,"84','":-0.0767,"','89',571,'86','":-0.102,"','87',575,'101','":-0.0511,"','97',579,'111',579,'100',579,'99',579,'103',579,'113','":-0.0511','},',361,':"B',363,361,':"C",','ic:0.145,',361,':"D",',318,'krn:{"88','":-0.0256,"','87',603,'65',603,'86',603,'89":-0.','0256},',361,':"E",',11,'12,',361,':"F','",ic:0.133,krn:{"','111',571,'101',571,'117','":-0.0767,"114":-0.0767,"97":-0.0767,"','65',575,'79',603,'67',603,'71',603,'81":-0.0256','},',361,':"G",',11,'0872,',361,':"H",',11,'164,',361,':"I",',11,'158,',361,':"J",',11,'14,',361,':"K",',598,'krn:{"79',603,'67',603,'71',603,633,'},',361,':"L",krn:{"84',571,'89',571,'86',575,'87',575,'101',579,'97',579,'111',579,'100',579,'99',579,'103',579,'113',591,'},',361,':"M",',11,'164,',361,':"N",',11,'164,',361,':"O",',318,'krn:{"88',603,'87',603,'65',603,'86',603,610,'0256},',361,':"P',363,'krn:{"65":-0.0767},',361,':"Q",d:0.1,',318,361,':"R",',11,'0387,',569,'0.0256,"84',571,'89',571,'86',575,'87',575,'101',579,'97',579,'111',579,'100',579,'99',579,'103',579,'113',591,'},',361,':"S",',11,'12,',361,':"T',618,'121',571,'101',571,'111',624,'117',571,'65":-0.0767},',361,':"U",',11,'164,',361,':"V",ic:0.','184,krn:{"','111',571,'101',571,'117',624,'65',575,'79',603,'67',603,'71',603,633,'},',361,':"W",ic:0.',764,'65":-0.0767},',361,':"X",',11,'158,krn:{"79',603,'67',603,'71',603,633,'},',361,':"Y",',11,'194',',krn:{"101',571,'111',624,'117',571,'65":-0.0767},',361,':"Z",',598,361,':"[",d:0.1,',11,'188,',361,':"“",',11,'169,',361,':"]",d:0.1,',11,'105,',361,':"ˆ",',11,'0665,',6,384,2,'x2D9;",',11,'118,',6,384,2,'x2018;",',444,'92},',361,':"a','",a:0,ic:0.',376,361,':"b",',11,'0631',800,579,'97',579,'111',579,'100',579,'99',579,'103',579,'113',591,'},',361,':"c',840,'0565',800,579,'97',579,'111',579,'100',579,'99',579,'103',579,'113',591,'},',361,':"d',363,'krn:{"108":','0.0511},',361,':"e',840,'0751',800,579,'97',579,'111',579,'100',579,'99',579,'103',579,'113',591,'},',361,':"f',359,'12,"102":11,"108":13},',361,':"g','",a:0,d:0.2,ic:0.','0885,',361,':"h",',11,376,361,':"i",',11,'102,',361,378,598,361,':"k",',11,400,361,':"l',363,883,'0.0511},',361,':"m',840,376,361,':"n',840,376,'krn:{"39":-0.102},',361,':"o',840,'0631',800,579,'97',579,'111',579,'100',579,'99',579,'103',579,'113',591,'},',361,':"p',910,'0631',800,579,'97',579,'111',579,'100',579,'99',579,'103',579,'113',591,'},',361,':"q',910,'0885,',361,':"r',840,'108',800,579,'97',579,'111',579,'100',579,'99',579,'103',579,'113',591,'},',361,':"s',840,'0821,',361,':"t",',11,'0949,',361,':"u',840,376,361,':"v',840,400,361,':"w',840,400,883,'0.0511},',361,':"x',840,'12,',361,':"y',910,'0885,',361,':"z',840,'123,',361,':"–",a:0.1,ic:0.','0921',492,'124},',361,':"—",a:0.1,ic:0.','0921,',361,':"˝",',560,6,384,2,'x2DC;",',11,'116,',6,384,2,'xA8;",',6,384,'"}],cmbx10',309,6,'bgreek"},{c:"&','Delta;",',6,1062,317,6,1062,'Lambda;",',6,1062,324,6,1062,329,6,1062,334,6,1062,339,6,1062,344,6,1062,349,6,1062,354,6,'bgreek','"},{c:"ff','",ic:0.0778,krn:{"39":0.0778,"63":0.0778,"33":0.0778,"41":0.0778,"93":0.0778},lig:{"105":','14,"108":15},','tclass:"bold"},{c',':"fi",',1096,':"fl",',1096,':"ffi",',1096,':"ffl",',1096,374,1096,378,1096,':"`",',6,'baccent',2,386,6,1111,2,392,6,1111,2,398,6,1111,2,404,6,1111,2,'x2DA;",',6,1111,412,1096,415,1096,419,1096,422,1096,425,1096,429,1096,433,1096,437,1096,440,'278,"76":-0.319},',1096,443,561,'60},',1096,447,1096,451,1096,':"$",',1096,457,1096,461,1096,465,468,'111,"33":0.111},lig:{"39":34},',1096,471,1096,475,1096,479,1096,483,1096,':",",a:-0.3,d:0.2,w:0.278,',1096,':"-",a:0',492,'123},',1096,':".",a:-0.25,',1096,497,1096,501,1096,505,1096,509,1096,513,1096,517,1096,521,1096,525,1096,529,1096,533,1096,537,1096,541,1096,545,1096,549,1096,553,1096,':"¿",',1096,559,561,'62},',1096,564,1096,':"A",krn:{"116','":-0.0278,"','67',1224,'79',1224,'71',1224,'85',1224,'81',1224,'84','":-0.0833,"','89',1236,'86":-0.','111,"87":-0.111},',1096,':"B",',1096,597,1096,':"D",krn:{"88',1224,'87',1224,'65',1224,'86',1224,610,'0278},',1096,613,1096,':"F",krn:{"111',1236,'101',1236,'117','":-0.0833,"114":-0.0833,"97":-0.0833,"65":-0.','111,"79',1224,'67',1224,'71',1224,'81":-0.0278','},',1096,636,1096,640,1096,':"I",krn:{"73":0.0278},',1096,648,1096,':"K",krn:{"79',1224,'67',1224,'71',1224,1271,'},',1096,':"L",krn:{"84',1236,'89',1236,1239,'111,"87":-0.111},',1096,687,1096,691,1096,':"O",krn:{"88',1224,'87',1224,'65',1224,'86',1224,610,'0278},',1096,':"P",krn:{"65',1236,'111',1224,'101',1224,'97',1224,'46',1236,'44":-0.0833},',1096,712,1096,':"R",krn:{"116',1224,'67',1224,'79',1224,'71',1224,'85',1224,'81',1224,'84',1236,'89',1236,1239,'111,"87":-0.111},',1096,743,1096,':"T",krn:{"121',1224,'101',1236,'111',1264,'0833,"117":-0.0833','},',1096,759,1096,763,'0139,krn:{"','111',1236,'101',1236,'117',1264,'111,"79',1224,'67',1224,'71',1224,1271,'},',1096,782,1360,'111',1236,'101',1236,'117',1264,'111,"79',1224,'67',1224,'71',1224,1271,'},',1096,':"X",krn:{"79',1224,'67',1224,'71',1224,1271,'},',1096,':"Y",',11,'025',800,1236,'111',1264,1354,'},',1096,808,1096,811,1096,815,1096,819,1096,823,6,1111,2,829,6,1111,2,835,561,'92},',1096,':"a','",a:0,krn:{"','118',1224,'106":0.','0556,"121',1224,'119":-0.','0278},',1096,':"b",krn:{"101','":0.0278,"','111',1443,'120',1224,'100',1443,'99',1443,'113',1443,'118',1224,1436,'0556,"121',1224,1439,'0278},',1096,':"c',1433,'104',1224,'107":-0.0278},',1096,':"d",',1096,':"e",a:0,',1096,':"f',1094,'12,"102":11,"108":13},',1096,':"g',910,1360,1436,'0278},',1096,':"h",krn:{"116',1224,'117',1224,'98',1224,'121',1224,'118',1224,1439,'0278},',1096,917,1096,378,1096,':"k",krn:{"97":-0.0556,"101',1224,'97',1224,'111',1224,'99":-0.','0278},',1096,':"l",',1096,':"m',1433,'116',1224,'117',1224,'98',1224,'121',1224,'118',1224,1439,'0278},',1096,':"n',1433,'116',1224,'117',1224,'98',1224,'121',1224,'118',1224,1439,'0278},',1096,':"o",a:0',800,1443,'111',1443,'120',1224,'100',1443,'99',1443,'113',1443,'118',1224,1436,'0556,"121',1224,1439,'0278},',1096,':"p",a:0,d:0.2',800,1443,'111',1443,'120',1224,'100',1443,'99',1443,'113',1443,'118',1224,1436,'0556,"121',1224,1439,'0278},',1096,':"q",a:0,d:0.2,',1096,':"r",a:0,',1096,':"s",a:0,',1096,':"t",krn:{"121',1224,1439,'0278},',1096,':"u',1433,1439,'0278},',1096,':"v',840,1360,'97":-0.0556,"101',1224,'97',1224,'111',1224,1505,'0278},',1096,':"w',840,'0139',800,1224,'97',1224,'111',1224,1505,'0278},',1096,':"x",a:0,',1096,':"y',910,1360,'111',1224,'101',1224,'97',1224,'46',1236,'44":-0.0833},',1096,':"z",a:0,',1096,1037,'0278',492,'124},',1096,1042,'0278,',1096,1045,6,1111,2,1050,6,1111,2,'xA8;",',6,1111,'"}]});','jsMath.Setup.Styles({".typeset .','cmr10','":"font-family: ','serif','",".typeset .','italic":"font-style: italic',1663,'bold":"font-weight: bold',1663,'lucida":"font-family: \'Lucida Grande','\'",".typeset .','asymbol','":"font-family: \'Apple ','Symbols\'; ','font-size: ','115','%",".typeset .','cal',1671,'Chancery',1669,'arrows','":"font-family: \'Hiragino Mincho Pro',1669,'arrow1',1681,'\'; ','position: relative; top',': .075em; margin: -1px',1663,'arrow1a',1681,'\'; margin:-.','3em',1663,252,1661,'AppleGothic','; ',1673,'50',1675,'arrow2',1661,'Symbol','; ',1673,'140%; ',1686,': .','1em; margin:-1px',1663,'arrow2a',1661,1703,1663,302,1661,1696,'; ',1673,'67',1675,'harpoon',1661,1696,'; ',1673,'90',1675,267,1681,1669,'symbol2',1681,1691,'2em',1663,'symbol3',1661,1696,1663,'delim1',1661,'Times; ',1673,'133',189,'75em',1663,'delim1b',1681,'\'; ',1673,'133',189,'8em; ',173,1663,'delim1c',1661,1703,'; ',1673,'120',189,'8em',';",".typeset .',141,1661,'Baskerville','; ',1673,'180',189,1747,1663,'delim2b',1681,'\'; ',1673,'190',189,'8em; ',173,1663,'delim2c',1661,1703,'; ',1673,'167',189,'8em',1766,'delim3',1661,1769,'; ',1673,'250',189,'725em',1663,'delim3b',1681,'\'; ',1673,'250',189,'8em; ',173,1663,'delim3c',1661,267,'; ',1673,'240',189,'775em',1766,'delim4',1661,1769,'; ',1673,'325',189,'7em',1663,'delim4b',1681,'\'; ',1673,'325',189,'8em; ',173,1663,'delim4c',1661,1703,'; ',1673,'300',189,'8em',1766,'vertical',1661,'Copperplate',1663,'vertical1',1661,1850,'; ',1673,'85%; margin: .','15em',1766,247,1661,1850,'; ',1673,1857,'17em',1766,'greek',1661,1662,1663,357,1661,1662,'; font-style:italic',1663,1092,1661,1662,'; font-weight:bold',1663,38,1681,'\'; ',1673,'133%; ',1686,': .85em','; margin:-.','05em',1663,1,1661,1769,'; ',1673,'100%; ',1686,': .775em',1766,20,1681,'\'; ',1673,'160%; ',1686,': .7em','; margin:-.1em',1663,14,1661,'Apple Symbols','; ',1673,'125%; ',1686,': .',1747,1908,1766,87,1681,'\'; ',1673,'200%; ',1686,': .8em',1889,'07em',1663,50,1661,1769,'; ',1673,'175%; ',1686,1907,1766,69,1681,'\'; ',1673,'270%; ',1686,': .62em',1908,1663,63,1671,'Symbols\'; ',1673,'250%; ',1686,1907,1889,'17em',1766,111,'":"',1673,'67%; ',1686,':-.8em',1663,116,'":"',1673,'110%; ',1686,':-.5em',1663,121,'":"',1673,'175%; ',1686,':-.32em',1663,127,'":"',1673,'75%; ',1686,1971,1663,132,'":"',1673,'133%; ',1686,': -.15em',1663,'wide3a":"',1673,'200%; ',1686,': -.05em',1663,194,1661,1769,1766,'accent":"',1686,': .02em',1663,384,'":"',1686,2006,'; font-style:italic',1663,1111,'":"',1686,2006,1880,'"});jsMath.noAppleSymbols=(jsMath.BBoxFor("∣").w==jsMath.BBoxFor("<',172,'font-family: ',1912,'\\">∣").w);','if(jsMath.noAppleSymbols){jsMath.Update.TeXfonts({cmsy10:{"','16":{c:"<','span style=\\"position:relative',';top:.','25em; ',1673,'67%\\">⌣<',2026,';top:-.15em;font-size:67%;','margin-left:-','1em\\">⌢',264,6,'normal"},"','22','":{c:"&#','x227A;<',2026,2027,'3em; ',2033,'1em\\">&','mdash',264,6,2037,'23',2039,'x227B;<',2026,2027,2043,2033,2045,'mdash',264,6,2037,'91','":{c:"∪',';"},"92',2039,22,';"},"93',2063,';<',172,1673,'50%; ',2033,'1.1em; ',1686,':-.3em; margin-right:.4em\\">+"},"94',2039,34,';"},"95',2039,40,';"},"96":{c:"|<',2026,'; top:-.15em',262,2045,'ndash',264,6,2037,'109',2039,'x21D1;<',2026,'; top:.','1em',262,'6em\\">⇓',264,'h:0.9,d:0.2,',6,1711,'"}},cmex10:{"85',2063,';<',172,1673,'50%; ',2033,'1.1em; ',1686,2076,'>"},"93',2063,';<',172,1673,'50%; ',2033,'1.1em; ',1686,2076,'>"}}});jsMath.Macro("rightleftharpoons","\\\\unicode{x21CC}");}else{',1659,'harpoon',1661,1912,'; ',1673,'125%"});}','if(jsMath.browser=="','OmniWeb"){jsMath.Update.TeXfonts({cmsy10:{"55":{c:"<',172,1673,'75%; ','position:relative','; left:.3em',2085,262,'3em\\">˫"},"104":{c:"<',2026,2096,'2em',262,'55em\\">〈"},"105":{c:"<',2026,2096,'2em','; margin-right',':-.55em\\">〉"}}});',1659,'arrow2',1661,1703,'; ',1673,'100%; ',1686,': -.',1709,'"});',2024,'22',2039,'x227A;<',2026,2027,'25em',262,'8em',2150,':.2em\\">&ndash',264,6,2037,'23',2039,'x227B;<',2026,2027,'25em',262,'7em',2150,':.',2045,'ndash',264,6,2037,'96":{c:"<',172,'font-size:80%; ',2137,2085,'\\">|<',2026,'; top:-.1em',262,2045,'ndash',264,6,'normal"}}});}}',2132,'Opera"){',1659,14,'":"margin:0pt .12em 0pt 0pt',1766,63,2210,';"});}',2132,'Mozilla','"){jsMath.Setup.Script("jsMath-fallback-mac-','mozilla.js");}',2132,'MSIE',2217,'msie.js");}jsMath.Macro("not","\\\\mathrel{\\\\rlap{\\\\kern 4mu/}}");jsMath.Box.defaultH=0.8;'] +]); diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-pc.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-pc.js new file mode 100644 index 0000000..dfe675e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-pc.js @@ -0,0 +1,29 @@ +/* + * jsMath-fallback-pc.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file makes changes needed for when the TeX fonts are not available + * with a browser on the PC. + * + * --------------------------------------------------------------------- + * + * Copyright 2004-2006 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +jsMath.Script.Uncompress([ + ['jsMath.Add(jsMath.TeX,{cmr10',':[{c:"Γ",','tclass:"greek"},{c:"&','Delta;",',2,'Theta;",',2,'Lambda;",',2,'Xi;",',2,'Pi;",',2,'Sigma;",',2,'Upsilon;",',2,'Phi;",',2,'Psi;",',2,'Omega;",','tclass:"','greek','"},{c',':"ff','",ic:0.0778,krn:{"39":0.0778,"63":0.0778,"33":0.0778,"41":0.0778,"93":0.0778},lig:{"105":','14,"108":15},','tclass:"normal"},{c',':"fi",',28,':"fl",',28,':"ffi",',28,':"ffl",',28,':"ı',';",a:0,',28,':"j",','d:0.2,',28,':"ˋ",',22,'accent','"},{c:"&#','x2CA;",',22,45,46,'x2C7;",',22,45,46,'x2D8;",',22,45,46,'x2C9;",',22,45,46,'x2DA;",',22,45,46,'x0327;",',28,':"ß",',28,':"æ',38,28,':"œ',38,28,':"ø",',28,':"Æ",',28,':"Œ",',28,':"Ø",',28,':"?",krn:{"108":-0.278,"76":-0.319},',28,':"!",lig:{"96":60},',28,':"”",',28,':"#",',28,':"$",',28,':"%",',28,':"&",',28,':"’",krn:{"63":0.111,"33":0.','111},','lig:{"39":34},',28,':"(",',41,28,':")",',41,28,':"*",',28,':"+",a:0.1,',28,':",",a:-','0.3,d:0.2,','w:0.278,',28,':"-",a:0,lig:{"45":123},',28,':".",a:-0.','25,',28,':"/",',28,':"0",',28,':"1",',28,':"2",',28,':"3",',28,':"4",',28,':"5",',28,':"6",',28,':"7",',28,':"8",',28,':"9",',28,':":",',28,':";",',28,':"¡",',28,':"=",a:0,d:-0.1,',28,':"¿",',28,':"?",lig:{"96":62},',28,':"@",',28,':"A','",krn:{"','116','":-0.0278,"','67',161,'79',161,'71',161,'85',161,'81',161,'84','":-0.0833,"','89',173,'86','":-0.111',',"87":-0.',100,28,':"B",',28,':"C",',28,':"D',159,'88',161,'87',161,'65',161,'86',161,'89','":-0.0278','},',28,':"E",',28,':"F',159,'111',173,'101',173,'117','":-0.0833,"114":-0.0833,"97":-0.0833,"65":-0.','111,"79',161,'67',161,'71',161,'81',196,'},',28,':"G",',28,':"H",',28,':"I',159,'73":0.','0278','},',28,':"J",',28,':"K',159,'79',161,'67',161,'71',161,'81',196,'},',28,':"L',159,'84',173,'89',173,'86',177,178,100,28,':"M",',28,':"N",',28,':"O',159,'88',161,'87',161,'65',161,'86',161,'89',196,'},',28,':"P',159,'65',173,'111',161,'101',161,'97',161,'46',173,'44":-0.0833},',28,':"Q",',41,28,':"R',159,'116',161,'67',161,'79',161,'71',161,'85',161,'81',161,'84',173,'89',173,'86',177,178,100,28,':"S",',28,':"T',159,'121',161,'101',173,'111',208,'0833,"117":-0.0833','},',28,':"U",',28,':"V",','ic:0.0139,krn:{"','111',173,'101',173,'117',208,'111,"79',161,'67',161,'71',161,'81',196,'},',28,':"W",',328,'111',173,'101',173,'117',208,'111,"79',161,'67',161,'71',161,'81',196,'},',28,':"X',159,'79',161,'67',161,'71',161,'81',196,'},',28,':"Y",ic:0.025,','krn:{"101',173,'111',208,322,'},',28,':"Z",',28,':"[",','d:0.1,',28,':"“",',28,':"]",',386,28,':"ˆ",',22,45,46,'x2D9;",',22,45,46,'x2018;",lig:{"96":92},',28,':"a','",a:0,krn:{"','118',161,'106":0.','0556,"121',161,'119',196,'},',28,':"b',159,'101','":0.0278,"','111',417,'120',161,'100',417,'99',417,'113',417,'118',161,407,'0556,"121',161,'119',196,'},',28,':"c',404,'104',161,'107',196,'},',28,':"d",',28,':"e",a:0,',28,':"f',26,'12,"102":11,"108":13},',28,':"g",','a:0,d:0.2,ic:0.','0139,krn:{"',407,226,'},',28,':"h',159,'116',161,'117',161,'98',161,'121',161,'118',161,'119',196,'},',28,':"i",',28,':"j",',41,28,':"k',159,'97','":-0.0556,"','101',161,'97',161,'111',161,'99',196,'},',28,':"l",',28,':"m',404,'116',161,'117',161,'98',161,'121',161,'118',161,'119',196,'},',28,':"n',404,'116',161,'117',161,'98',161,'121',161,'118',161,'119',196,'},',28,':"o',404,'101',417,'111',417,'120',161,'100',417,'99',417,'113',417,'118',161,407,'0556,"121',161,'119',196,'},',28,':"p",a:0,',41,376,417,'111',417,'120',161,'100',417,'99',417,'113',417,'118',161,407,'0556,"121',161,'119',196,'},',28,':"q",a:0,',41,28,':"','r",a:0,',28,':"s",a:0,',28,':"t',159,'121',161,'119',196,'},',28,':"u',404,'119',196,'},',28,':"v",a:0,',328,'97',484,'101',161,'97',161,'111',161,'99',196,'},',28,':"w",a:0,',328,'101',161,'97',161,'111',161,'99',196,'},',28,':"x",a:0,',28,':"y",',454,455,'111',161,'101',161,'97',161,'46',173,'44":-0.0833},',28,':"z",a:0,',28,':"–',';",a:0.1,','ic:0.0278,','lig:{"45":124},',28,':"—',641,642,28,':"˝",',22,45,46,'x2DC;",',22,45,46,'xA8;",',22,45,'"}],cmmi10',1,'ic:0.139',',krn:{"61":-0.0556,"59":-0.111,"58":-0.111,"127":0.','0833},',22,'igreek"},{c:"&',3,'krn:{"127":0.','167},',22,666,5,'ic:0.',226,',krn:{"127":0.','0833},',22,666,7,668,'167},',22,666,9,'ic:0.0757',675,'0833},',22,666,11,'ic:0.0812,krn:{"61',484,'59":-0.0556,"58":-0.0556,"127":0.','0556},',22,666,13,'ic:0.0576',675,'0833},',22,666,15,'ic:0.139',663,'0556},',22,666,17,668,'0833},',22,666,19,'ic:0.11,krn:{"61',484,693,'0556},',22,666,21,'ic:0.0502',675,'0833},',22,666,'alpha',';",a:0,ic:0.','0037',675,226,'},',2,'beta;",','d:0.2,ic:0.','0528',675,'0833},',2,'gamma;",',454,'0556,',2,'delta;",ic:0.0378,krn:{"',693,'0556},',2,'epsilon;",a:0',675,'0556},',22,'lucida',24,':"ζ",',735,'0738',675,'0833},',2,'eta;",',454,'0359',675,'0556},',2,'theta;",ic:0.',226,675,'0833},',2,'iota;",a:0',675,'0556},',2,'kappa',38,2,'lambda;",',2,'mu',38,'d:0.2',675,226,'},',2,'nu',728,'0637,krn:{"',693,226,'},',2,'xi;",',735,'046',675,100,2,'pi',728,'0359,',2,'rho',38,'d:0.2',675,'0833},',2,'sigma',728,802,'krn:{"59',484,'58":-0.0556','},',2,'tau',728,'113,krn:{"',693,226,'},',2,'upsilon',728,'0359',675,226,'},',2,'phi',641,'d:0.2',675,'0833},',2,'chi',38,'d:0.2',675,'0556},',2,'psi',641,735,'0359',675,100,2,'omega',728,802,2,'epsilon;",a:0',675,'0833},',22,'greek',46,'x3D1;",',668,'0833},',22,'lucida',46,'x3D6',728,226,',',22,'lucida',46,'x3F1',38,'d:0.2',675,'0833},',22,'lucida',46,'x3C2;",',454,'0799',675,'0833},',22,'lucida',46,'x3D5',641,'d:0.2',675,'0833},',22,'lucida',46,'x21BC',';",a:0,d:-0.','2,',22,'arrows',46,'x21BD',899,'1,',22,'arrows',46,'x21C0',899,'2,',22,'arrows',46,'x21C1',899,'1,',22,'arrows',24,':\'&#','x02D3',';\',a:0','.1,',22,'symbol"},{c',922,923,'x02D2',925,'.1,','tclass:"symbol"},{c:"&#','x25B9;",',934,'x25C3;",',22,928,':"0",',28,':"1",',28,':"2",',28,':"3",',28,':"4",',28,':"5",',28,':"6",',28,':"7",',28,':"8",',28,':"9",',28,119,'3,',28,':",",a:-',114,28,':"<',641,28,':\'/\',',386,'krn:{"1',484,'65',484,'77',484,'78',484,'89":0.0556,"90":-0.0556},',28,':">',641,28,':"⋆',38,22,'arial',46,'x2202;",ic:0.0556',675,'0833},',28,':"A",',668,'139','},tclass:"italic"},{c:"','B",ic:0.0502',675,'0833',1000,'C",ic:0.0715,krn:{"61',161,693,'0833',1000,'D",ic:0.',226,675,'0556',1000,'E",ic:0.0576',675,'0833',1000,'F",ic:0.139',663,'0833',1000,'G",',668,'0833',1000,'H",ic:0.0812,krn:{"61',484,693,'0556',1000,'I",ic:0.0785',675,'111',1000,'J",ic:0.0962',663,'167',1000,'K",ic:0.0715,krn:{"61',484,693,'0556',1000,'L",',668,226,1000,'M','",ic:0.109,krn:{"','61',484,693,'0833',1000,'N',1050,'61',173,'61',161,693,'0833',1000,'O",ic:0.',226,675,'0833',1000,'P",ic:0.139',663,'0833',1000,'Q",d:0.2',675,'0833',1000,'R",ic:0.00773',675,'0833',1000,'S",ic:0.0576,krn:{"61',484,693,'0833',1000,'T','",ic:0.139,krn:{"','61',161,693,'0833',1000,'U',1050,'59',177,',"58',177,',"61',484,'127":0.',226,1000,'V",ic:0.222,krn:{"59','":-0.167,"','58',1106,'61',177,1000,'W',1088,'59',1106,'58',1106,'61',177,1000,'X",ic:0.0785,krn:{"61',173,'61',161,693,'0833',1000,'Y",ic:0.222,krn:{"59',1106,'58',1106,'61',177,1000,'Z",ic:0.0715,krn:{"61',484,693,'0833},',22,'italic',46,'x266D;",',934,'x266E;",',934,'x266F;",',22,928,':\'&#','x203F',925,',d:-0.1,',22,991,'"},{c:\'−',925,'.1,',934,'xB7',899,'2,',28,':"×',38,28,922,'top:.3em">*',925,',',28,':"÷',38,28,':"◊",',934,'xB1',641,28,':"∓",',934,'x2295;",',934,'x2296;",',934,'x2297;",',934,'x2298;",',934,'x2299;",',934,'x25EF;",',22,991,46,'x2218',899,'1,',22,'symbol2',46,'x2022',899,'2,',934,'x224D',641,22,'symbol2',46,'x2261',641,22,'symbol2',46,'x2286;",',934,'x2287;",',934,'x2264;",',934,'x2265;",',934,'x227C;",',934,'x227D;",',22,928,':"~",a:0,d:-0.2,',28,':"≈',641,'d:-0.1,',934,'x2282;",',934,'x2283;",',934,'x226A;",',934,'x226B;",',934,'x227A;",',934,'x227B;",',934,'x2190;",a:-0.1,',22,'arrow1',46,'x2192;",a:-0.1,',22,'arrow1',46,'x2191',';",a:0.2,d:0',',',22,'arrow1a',46,'x2193',1419,',',22,'arrow1a',46,'x2194;",a:-0.1,',22,'arrow1',46,'x2197',641,22,'arrows',46,'x2198',641,22,'arrows',46,'x2243',641,22,'symbol2',46,'x21D0;",a:-0.1,',22,'arrow2',46,'x21D2;",a:-0.1,',22,'arrow2',46,'x21D1',1419,'.1,',22,'arrow1a',46,'x21D3',1419,'.1,',22,'arrow1a',46,'x21D4;",a:-0.1,',22,'arrow2',46,'x2196',641,22,'arrows',46,'x2199',641,22,'arrows',46,'x221D',641,28,969,': 133%; margin-right: -.1em; ',1150,':.4em">′',925,',',22,'lucida',46,'x221E',641,934,'x2208;",',934,'x220B;",',22,928,969,': 150',971,'2em">&#','x25B3;/{}{}{}|{\',',33,'26,',3,240,270,'position:relative',274,'1em; left:-.05em">}\',',33,'27,',3,240,270,'font-size: ','150%; ','position:relative; top:.','8em','">√\',h:0.','04,d:1.16,n:113,',3,'root',270,289,'220%; ',291,'8em">√\',',33,'114,',3,296,270,289,'310%; ',291,'8em',274,'01em',293,'06,d:2.36,n:115,',3,296,270,289,'400%; ',291,'8em',274,'025em',293,'08,d:2.96,n:116,',3,296,270,289,'490%; ',291,'8em',274,'03em',293,'1,d:3.75,n:117,',3,296,270,289,'580%; ',291,'775em',274,'04em',293,'12,d:4.5,n:118,',3,296,270,289,'750%; ',291,343,';','margin-right',':-.04em',293,'14,d:5.7,',3,296,270,'margin-left',':.02em">||\',h:0.8,d:',0,1,'126,bot:127,rep:119},',3,'normal',5,'x2191',';",h:0.7,d:0,delim:{',1,'120,rep:63},',3,'arrow1a',5,'x2193;",h:0.65,d:',0,'bot:121,rep:63},',3,381,270,363,273,'">◜',';\',h:0.','05,',3,'symbol',270,363,':-.3em">◝',397,'05,',3,400,270,363,273,'">◟',397,'05,',3,400,270,363,':-.3em">◞',397,'05,',3,400,5,'x21D1',377,1,'126,rep:119},',3,381,5,'x21D3',377,'bot:127,rep:119},',3,381,'"}],cmti10',':[{c:"Γ",','ic:0.133,',3,'igreek"},{c:"&','Delta;",',3,455,'Theta;",','ic:0.094,',3,455,'Lambda;",',3,455,'Xi;",ic:0.153,',3,455,'Pi;",ic:0.164,',3,455,'Sigma;",','ic',':0.12,',3,455,'Upsilon;",','ic:0.111,',3,455,'Phi;",','ic:0.0599,',3,455,'Psi;",','ic:0.111,',3,455,'Omega;",','ic:0.103,',3,'igreek','"},{c:"ff','",ic:0.212,krn:{"39":0.104,"63":0.104,"33":0.104,"41":0.104,"93":0.104},lig:{"105":','14,"108":15},','tclass:"italic"},{c',':"fi','",ic:0.103,',496,':"fl',498,496,':"ffi',498,496,':"ffl',498,496,':"ı",a:0,','ic:0.','0767,',496,':"j",d:0.2,','ic:0.0374,',496,':"ˋ",',3,'iaccent',5,'x2CA;",','ic:0.0969,',3,518,5,'x2C7;",','ic:0.083,',3,518,5,'x2D8;",','ic:0.108,',3,518,5,'x2C9;",',490,3,518,5,'x2DA;",',3,518,'"},{c:"?",','d:0.17,w:0.46,',496,':"ß",','ic:0.105,',496,':"æ",a:0,','ic:0.0751,',496,':"œ",a:0,',550,496,':"ø",','ic:0.0919,',496,':"Æ",','ic',474,496,':"Œ",','ic',474,496,':"Ø",',460,496,':"?",krn:{"108":-0.','256,"76":-0.321},',496,':"!",','ic:0.124,lig:{"96":','60},',496,':"”",','ic:0.0696,',496,':"#",ic:0.0662,',496,':"$",',496,':"%",ic:0.136,',496,':"&",','ic:0.0969,',496,':"’",','ic:0.124,','krn:{"63":0.','102,"33":0.102},lig:{"39":34},',496,':"(",d:0.2,','ic:0.162,',496,':")",d:0.2,','ic:0.0369,',496,':"*",ic:0.149,',496,':"+",a:0.1,','ic:0.0369,',496,':",",a:-0.3,d:0.2,w:0.278,',496,':"-",a:0,ic:0.0283',',lig:{"45":','123},',496,':".",a:-0.25,',496,':"/",ic:0.162,',496,':"0",ic:0.136,',496,':"1",ic:0.136,',496,':"2",ic:0.136,',496,':"3",ic:0.136,',496,':"4",ic:0.136,',496,':"5",ic:0.136,',496,':"6",ic:0.136,',496,':"7",ic:0.136,',496,':"8",ic:0.136,',496,':"9",ic:0.136,',496,':":",ic:0.0582,',496,':";",ic:0.0582,',496,':"¡",','ic:0.0756,',496,':"=",a:0,d:-0.1,','ic:0.0662,',496,':"¿",',496,':"?",','ic:0.122,','lig:{"96":','62},',496,':"@",ic:0.096,',496,':"A",','krn:{"110":-0.0256,"108":-0.0256,"114":-0.0256,"117":-0.0256,"109":-0.0256,"116":-0.0256,"105":-0.0256,"67":-0.0256,"79":-0.0256,"71":-0.0256,"104":-0.0256,"98":-0.0256,"85":-0.0256,"107":-0.0256,"118":-0.0256,"119":-0.0256,"81":-','0.0256,"84','":-0.0767,"','89',656,'86','":-0.102,"','87',660,'101','":-0.0511,"','97',664,'111',664,'100',664,'99',664,'103',664,'113','":-0.0511','},',496,':"B',498,496,':"C",','ic:0.145,',496,':"D",',460,'krn:{"88','":-0.0256,"','87',688,'65',688,'86',688,'89":-0.','0256},',496,':"E",ic',474,496,':"F','",ic:0.133,krn:{"','111',656,'101',656,'117','":-0.0767,"114":-0.0767,"97":-0.0767,"','65',660,'79',688,'67',688,'71',688,'81":-0.0256','},',496,':"G",ic:0.0872,',496,':"H",ic:0.164,',496,':"I",ic:0.158,',496,':"J",ic:0.14,',496,':"K",',683,'krn:{"79',688,'67',688,'71',688,717,'},',496,':"L",krn:{"84',656,'89',656,'86',660,'87',660,'101',664,'97',664,'111',664,'100',664,'99',664,'103',664,'113',676,'},',496,':"M",ic:0.164,',496,':"N",ic:0.164,',496,':"O",',460,'krn:{"88',688,'87',688,'65',688,'86',688,695,'0256},',496,':"P',498,'krn:{"65":-0.0767},',496,':"Q",d:0.2,',460,496,':"R",ic:0.0387,',654,'0.0256,"84',656,'89',656,'86',660,'87',660,'101',664,'97',664,'111',664,'100',664,'99',664,'103',664,'113',676,'},',496,':"S",ic',474,496,':"T',702,'121',656,'101',656,'111',708,'117',656,'65":-0.0767},',496,':"U",ic:0.164,',496,':"V",ic:0.','184,krn:{"','111',656,'101',656,'117',708,'65',660,'79',688,'67',688,'71',688,717,'},',496,':"W",ic:0.',831,'65":-0.0767},',496,':"X",ic:0.158,krn:{"79',688,'67',688,'71',688,717,'},',496,':"Y",ic:0.','194',',krn:{"101',656,'111',708,'117',656,'65":-0.0767},',496,':"Z",',683,496,':"[",d:0.1,','ic:0.188,',496,':"“",','ic:0.169,',496,':"]",d:0.1,','ic:0.105,',496,':"ˆ",','ic:0.0665,',3,518,5,'x2D9;",','ic:0.118,',3,518,5,'x2018;",',573,'92},',496,':"a','",a:0,ic:0.',511,496,':"b",ic:0.0631',864,664,'97',664,'111',664,'100',664,'99',664,'103',664,'113',676,'},',496,':"c',899,'0565',864,664,'97',664,'111',664,'100',664,'99',664,'103',664,'113',676,'},',496,':"d',498,'krn:{"108":','0.0511},',496,':"e',899,'0751',864,664,'97',664,'111',664,'100',664,'99',664,'103',664,'113',676,'},',496,':"f',494,'12,"102":11,"108":13},',496,':"g','",a:0,d:0.2,ic:0.','0885,',496,':"h",ic:0.',511,496,':"i",ic:0.102,',496,513,683,496,':"k",',531,496,':"l',498,940,'0.0511},',496,':"m',899,511,496,':"n',899,511,'krn:{"39":-0.102},',496,':"o',899,'0631',864,664,'97',664,'111',664,'100',664,'99',664,'103',664,'113',676,'},',496,':"p',967,'0631',864,664,'97',664,'111',664,'100',664,'99',664,'103',664,'113',676,'},',496,':"q',967,'0885,',496,':"r',899,'108',864,664,'97',664,'111',664,'100',664,'99',664,'103',664,'113',676,'},',496,':"s',899,'0821,',496,':"t",ic:0.0949,',496,':"u',899,511,496,':"v',899,'108,',496,':"w',899,1068,940,'0.0511},',496,':"x',899,'12,',496,':"y',967,'0885,',496,':"z',899,'123,',496,':"–",a:0.1,ic:0.','0921',607,'124},',496,':"—",a:0.1,ic:0.','0921,',496,':"˝",',647,3,518,5,'x2DC;",','ic:0.116,',3,518,5,'xA8;",',3,518,'"}],cmbx10',452,3,'bgreek"},{c:"&','Delta;",',3,1112,459,3,1112,'Lambda;",',3,1112,'Xi;",',3,1112,'Pi;",',3,1112,472,3,1112,477,3,1112,481,3,1112,485,3,1112,489,3,'bgreek','"},{c:"ff','",ic:0.0778,krn:{"39":0.0778,"63":0.0778,"33":0.0778,"41":0.0778,"93":0.0778},lig:{"105":','14,"108":15},','tclass:"bold"},{c',':"fi",',1146,':"fl",',1146,':"ffi",',1146,':"ffl",',1146,509,1146,513,1146,':"ˋ",',3,'baccent',5,520,3,1161,5,525,3,1161,5,530,3,1161,5,535,3,1161,5,'x2DA;",',3,1161,543,1146,546,1146,549,1146,552,1146,555,1146,558,1146,562,1146,566,1146,569,'278,"76":-0.319},',1146,572,648,'60},',1146,576,1146,':"#",',1146,':"$",',1146,':"%",',1146,585,1146,588,590,'111,"33":0.111},lig:{"39":34},',1146,593,1146,596,1146,':"*",',1146,601,1146,':",",a:-0.3,d:0.2,w:0.278,',1146,':"-",a:0',607,'123},',1146,':".",a:-0.25,',1146,':"/",',1146,':"0",',1146,':"1",',1146,':"2",',1146,':"3",',1146,':"4",',1146,':"5",',1146,':"6",',1146,':"7",',1146,':"8",',1146,':"9",',1146,':":",',1146,':";",',1146,638,1146,641,1146,':"¿",',1146,646,648,'62},',1146,':"@",',1146,':"A",krn:{"116','":-0.0278,"','67',1274,'79',1274,'71',1274,'85',1274,'81',1274,'84','":-0.0833,"','89',1286,'86":-0.','111,"87":-0.111},',1146,':"B",',1146,682,1146,':"D",krn:{"88',1274,'87',1274,'65',1274,'86',1274,695,'0278},',1146,':"E",',1146,':"F",krn:{"111',1286,'101',1286,'117','":-0.0833,"114":-0.0833,"97":-0.0833,"65":-0.','111,"79',1274,'67',1274,'71',1274,'81":-0.0278','},',1146,':"G",',1146,':"H",',1146,':"I",krn:{"73":0.0278},',1146,':"J",',1146,':"K",krn:{"79',1274,'67',1274,'71',1274,1321,'},',1146,':"L",krn:{"84',1286,'89',1286,1289,'111,"87":-0.111},',1146,':"M",',1146,':"N",',1146,':"O",krn:{"88',1274,'87',1274,'65',1274,'86',1274,695,'0278},',1146,':"P",krn:{"65',1286,'111',1274,'101',1274,'97',1274,'46',1286,'44":-0.0833},',1146,784,1146,':"R",krn:{"116',1274,'67',1274,'79',1274,'71',1274,'85',1274,'81',1274,'84',1286,'89',1286,1289,'111,"87":-0.111},',1146,':"S",',1146,':"T",krn:{"121',1274,'101',1286,'111',1314,'0833,"117":-0.0833','},',1146,':"U",',1146,830,'0139,krn:{"','111',1286,'101',1286,'117',1314,'111,"79',1274,'67',1274,'71',1274,1321,'},',1146,849,1410,'111',1286,'101',1286,'117',1314,'111,"79',1274,'67',1274,'71',1274,1321,'},',1146,':"X",krn:{"79',1274,'67',1274,'71',1274,1321,'},',1146,862,'025',864,1286,'111',1314,1404,'},',1146,872,1146,875,1146,878,1146,881,1146,884,3,1161,5,889,3,1161,5,894,648,'92},',1146,':"a','",a:0,krn:{"','118',1274,'106":0.','0556,"121',1274,'119":-0.','0278},',1146,':"b",krn:{"101','":0.0278,"','111',1492,'120',1274,'100',1492,'99',1492,'113',1492,'118',1274,1485,'0556,"121',1274,1488,'0278},',1146,':"c',1482,'104',1274,'107":-0.0278},',1146,':"d",',1146,':"e",a:0,',1146,':"f',1144,'12,"102":11,"108":13},',1146,':"g',967,1410,1485,'0278},',1146,':"h",krn:{"116',1274,'117',1274,'98',1274,'121',1274,'118',1274,1488,'0278},',1146,':"i",',1146,513,1146,':"k",krn:{"97":-0.0556,"101',1274,'97',1274,'111',1274,'99":-0.','0278},',1146,':"l",',1146,':"m',1482,'116',1274,'117',1274,'98',1274,'121',1274,'118',1274,1488,'0278},',1146,':"n',1482,'116',1274,'117',1274,'98',1274,'121',1274,'118',1274,1488,'0278},',1146,':"o",a:0',864,1492,'111',1492,'120',1274,'100',1492,'99',1492,'113',1492,'118',1274,1485,'0556,"121',1274,1488,'0278},',1146,':"p",a:0,d:0.2',864,1492,'111',1492,'120',1274,'100',1492,'99',1492,'113',1492,'118',1274,1485,'0556,"121',1274,1488,'0278},',1146,':"q",a:0,d:0.2,',1146,':"r",a:0,',1146,':"s",a:0,',1146,':"t",krn:{"121',1274,1488,'0278},',1146,':"u',1482,1488,'0278},',1146,':"v',899,1410,'97":-0.0556,"101',1274,'97',1274,'111',1274,1554,'0278},',1146,':"w',899,'0139',864,1274,'97',1274,'111',1274,1554,'0278},',1146,':"x",a:0,',1146,':"y',967,1410,'111',1274,'101',1274,'97',1274,'46',1286,'44":-0.0833},',1146,':"z",a:0,',1146,1088,'0278',607,'124},',1146,1093,'0278,',1146,1096,3,1161,5,1101,3,1161,5,'xA8;",',3,1161,'"}]});','jsMath.Setup.Styles({".typeset .','cmr10','":"font-family',': serif','",".typeset .','italic":"font-style: italic',1712,'bold":"font-weight: bold',1712,'lucida',1710,': \'lucida sans unicode','\'",".typeset .','arial','":"font-family: \'Arial unicode MS',1720,'cal',1710,': \'Script MT\', \'Script MT Bold\', cursive',1712,'arrows',1722,1720,'arrow1',1722,1720,381,1722,'\'; ',291,'05em;left:-.',419,274,419,1712,'arrow2',1722,'\'; ',271,'top',273,';",".typeset .','arrow3',1722,'\'; margin:.1em',1712,400,1722,1720,'symbol2',1722,1720,'delim1','":"font-family: \'Times New Roman\'; font-','size: ','133%; ',291,'7em',1712,'delim1a','":"font-family: \'Lucida sans unicode\'; font-size: ','133%; ',291,'8em',1712,'delim1b',1722,'\'; font-size: ','133%; ',291,'8em',1712,240,1761,1762,'180%; ',291,'75em',1712,251,1768,'180%; ',291,'8em',1712,36,1722,1775,'180%; ',291,'8em',1712,'delim3',1761,1762,'250%; ',291,'725em',1712,'delim3a',1768,'250%; ',291,343,1712,'delim3b',1722,1775,'250%; ',291,'8em',1712,'delim4',1761,1762,'325%; ',291,'7em',1712,'delim4a',1768,'325%; ',291,343,1712,'delim4b',1722,1775,'325%; ',291,'8em',1712,11,1710,': Symbol; ',291,'2em',1712,'greek',1710,': \'Times New Roman',1720,492,1761,'style:italic',1712,1142,1761,'weight:bold',1712,48,1722,1775,'130','%; position: relative; top',': .7em; margin:-.05em',1712,106,1722,1775,'110',1862,': .85em',1749,124,1722,1775,'180',1862,': .6em',1712,60,1722,1775,'85',1862,': 1em',1712,54,1722,1775,'230',1862,1877,'; margin:-.05em',1712,154,1722,1775,'185',1862,': .75em',1712,170,1722,1775,'275',1862,': .',394,1712,64,1722,1775,'185',1862,1884,274,'1em',1712,212,'":"',289,'67',1862,':-.5em',1749,217,'":"',289,'110',1862,':-.2em',1749,222,'":"',289,'175%;",".typeset .',227,1761,1762,'75',1862,1923,1712,231,1761,1762,'133',1862,1930,1712,235,1761,1762,'200',1862,273,1712,296,1722,'\'; ',356,':-.075em',1712,'accent',1722,'\'; ',291,'05em; left:.15em',1712,518,1722,'\'; ',291,1967,'; font-','style:italic',1712,1161,1722,'\'; ',291,1967,1974,1856,'"});','if(jsMath.browser=="','Mozilla"){','jsMath.Update.TeXfonts({cmex10:{"','48":{c:""},"49":{c:""},"50":{c:""},"51":{c:""},"52":{c:""},"53":{c:""},"54":{c:""},"55":{c:""},"56":{c:""},"57":{c:""},"58":{c:""},"59":{c:""},"60":{c:""},"61":{c:""},"62":{c:""},"64":{c:""},"65":{c:""},"66":{c:""},"67":{c:""}}});',1708,'accent',1710,': Arial unicode MS; ',291,'05em; left:.05em"})}',1985,'MSIE"){jsMath.Browser.msieFontBug=1;',1987,'63":{','c:\'|\'}}})}jsMath.Macro("not","\\\\mathrel{\\\\rlap{\\\\kern 3mu/}}");jsMath.Macro("bowtie","\\\\mathrel\\\\triangleright\\\\kern-6mu\\\\mathrel\\\\triangleleft");jsMath.Box.defaultH=0.8;'] +]); \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-symbols.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-symbols.js new file mode 100644 index 0000000..8db31f4 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-symbols.js @@ -0,0 +1,28 @@ +/* + * jsMath-fallback-symbols.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file makes changes needed to use image fonts for symbols + * but standard native fonts for letters and numbers. + * + * --------------------------------------------------------------------- + * + * Copyright 2004-2006 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +jsMath.Script.Uncompress([ + ['jsMath.','Add(','jsMath.Img',',{','UpdateTeXFonts',':function(_1){for(var _2 in _1){for(var _3 in _1[_2]){',0,'TeX[_2][_3',']=_1[_2][_3];',0,7,'].tclass="i"+_2;}}}});',2,'.',4,'({cmr10',':{"33":{c:"!",lig:{"96":60}},"35":{c:"#"},"36":{c:"$"},"37":{c:"%"},"38":{c:"&"},"40":{c:"(",d:0.2},"41":{c:")",d:0.2},"42":{c',':"*",d:-0.3},"','43":{c:"+",a:0.1},"44":{c:",",a:-0.3','},"45":{c:"-",a:0',',lig:{"45":123}},"46":{c:".",a:-0.25},"47":{c',':"/"},"','48":{c:"0','"},"49":{c:"1"},"50":{c:"2"},"51":{c:"3"},"52":{c:"4"},"53":{c:"5"},"54":{c:"6"},"55":{c:"7"},"56":{c:"8"},"57":{c:"9"},"58":{c:":"},"59":{c:";"},"61":{c:"=",a:0,d:-0.1},"63":{c:"?",lig:{"96":62}},"64":{c:"@"},"65":{c:"A",krn:{"116','":-0.0278,"','67',24,'79',24,'71',24,'85',24,'81',24,'84":-0.0833,"89":-0.0833,"86":-0.111,"87":-0.111}},"','66":{c:"B','"},"','67":{c:"C',37,'68":{c:"D','",krn:{"','88',24,'87',24,'65',24,'86',24,'89','":-0.0278}},"','69":{c:"E',37,'70":{c:"F",','krn:{"111":-0.0833,"101":-0.0833,"117":-0.0833,"114":-0.0833,"97":-0.0833,"65":-0.111,"79":-0.0278,"67":-0.0278,"71":-0.0278,"81":-0.0278}},"','71":{c:"G',37,'72":{c:"H',37,'73":{c:"I',41,'73','":0.0278}},"','74":{c:"J',37,'75":{c:"K',41,'79',24,'67',24,'71',24,'81',51,'76":{c:"L",krn:{"',35,'77":{c:"M',37,'78":{c:"N',37,'79":{c:"O',41,'88',24,'87',24,'65',24,'86',24,'89',51,'80":{c:"P",','krn:{"65":-0.','0833,"111',24,'101',24,'97',24,'46":-0.0833,"44":-0.0833}},"','81":{c:"Q",d:','1},"82":{c:"R',41,'116',24,'67',24,'79',24,'71',24,'85',24,'81',24,35,'83":{c:"S',37,'84":{c:"T',41,'121',24,'101":-0.0833,"111":-0.0833,"114":-0.0833,"97":-0.0833,"65":-0.0833,"117":-0.0833}},"','85":{c:"U',37,'86":{c:"V",ic:0.','0139,',55,'87":{c:"W",ic:0.','0139,',55,'88":{c:"X",','krn:{"79',24,'67',24,'71',24,'81',51,'89":{c:"Y",ic:0.','025',',krn:{"',125,'90":{c:"Z',37,'91":{c:"[",d:0.1','},"93":{c:"]",d:0.1','},"97":{c:"a','",a:0,krn:{"','118',24,'106":0.0556,"121',24,'119',51,'98":{c:"b",','krn:{"101":0.0278,"111":0.0278,"120":-0.0278,"100":0.0278,"99":0.0278,"113":0.0278,"118":-0.0278,"106":0.0556,"121":-0.0278,"119":-0.0278}},"','99":{c:"c',152,'104',24,'107',51,'100":{c:"d',37,'101":{c:"e",a',':0},"102":{c:"f",ic:0.0778,krn:{"39":0.0778,"63":0.0778,"33":0.0778,"41":0.0778,"93":0.0778},lig:{"105":12,"102":11,"108":13}},"103":{c:"g",a:0,d:0.2,ic:0.0139,krn:{"106":0.0278}},"104":{c:"h",krn:{"116',24,'117',24,'98',24,'121',24,'118',24,'119',51,'105":{c:"i"},"106":{c:"j",d:','1},"107":{c:"k',41,'97','":-0.0556,"','101',24,'97',24,'111',24,'99',51,'108":{c:"l',37,'109":{c:"m',152,'116',24,'117',24,'98',24,'121',24,'118',24,'119',51,'110":{c:"n',152,'116',24,'117',24,'98',24,'121',24,'118',24,'119',51,'111":{c:"o",a:0,',160,'112":{c:"p",a:0,d:0.2,',160,'113":{c:"q",a:0,d:','1','},"114":{c:"r",a:0','},"','115":{c:"s",a:0','},"116":{c:"t',41,'121',24,'119',51,'117":{c:"u',152,'119',51,'118":{c:"v','",a:0,ic:0.','0139',145,'97',186,'101',24,'97',24,'111',24,'99',51,'119":{c:"w',245,'0139',145,'101',24,'97',24,'111',24,'99',51,'120":{c:"x",a:0','},"121":{c:"y','",a:0,d:0.2,ic:0.','0139',145,'111',24,'101',24,'97',24,102,'122":{c:"z",a:0','}},cmmi10:{"65":{c:"A',41,'127":0.139}},"',36,'",ic:0.','0502,','krn:{"127":0.0833}},"',38,287,'0715',145,'61',24,'59":-0.0556,"58":-0.0556,"127":0.','0833}},"','68":{c:"D',287,'0278',',krn:{"127":0.0556}},"',52,287,'0576,',289,54,'ic:0.139',',krn:{"61":-0.0556,"59":-0.111,"58":-0.111,"127":0.',297,56,'",',289,58,287,'0812',145,'61',186,296,'0556}},"','73":{c:"I",ic:0.','0785',145,'127":0.111}},"',64,287,'0962',308,'167}},"75":{c:"K',287,'0715',145,'61',186,296,320,'76":{c:"L",','krn:{"127":0.0278}},"',78,287,'109',145,'61',186,296,297,80,287,'109',145,'61":-0.0833,"61',24,296,297,'79":{c:"O',287,300,',',289,94,'ic:0.139',308,297,103,'0.2,',289,'82":{c:"R',287,'00773,',289,119,287,'0576',145,'61',186,296,297,'84":{c:"T",ic:0.','139',145,'61',24,296,297,126,287,'109',145,'59":-0.111,"58":-0.111,"61',186,'127',63,128,'222',',krn:{"59":-0.167,"58":-0.167,"61":-0.111}},"',131,'139',396,134,'ic:0.0785',145,'61":-0.0833,"61',24,296,297,143,'222',396,147,287,'0715',145,'61',186,296,297,'97":{c:"a",a:0},"98":{c:"b',37,'99":{c:"c",a:0',301,167,41,'89":0.0556,"90',186,'106":-0.111,"102":-0.167,"127":0.167}},"101":{c:"e",a:0',301,'102":{c:"f",d:','0.2,ic:0.','108',145,296,'167}},"103":{c:"g',272,'0359,',338,'104":{c:"h',41,'127',51,182,429,'0572',145,'59',186,'58":-0.',320,'107":{c:"k',287,'0315},"',195,287,'0197,',289,'109":{c:"m",a:0},"110":{c:"n",a:0},"111":{c:"o",a:0',301,227,289,'113":{c:"q',272,'0359,',289,'114":{c:"r',245,300,145,296,320,233,301,'116":{c:"t",',289,'117":{c:"u",a:0,',338,'118":{c:"v',245,'0359,',338,'119":{c:"w',245,'0269,',289,270,',',338,'121":{c:"y',272,'0359',301,'122":{c:"z',245,'044',145,'127":0.0556}}},cmsy10:{"0":{c:"−",a:0.1}},cmti10:{"33":{c:"!",lig:{"96":60}},"35":{c:"#",ic:0.0662},"37":{c:"%",ic:0.136},"38":{c:"&",ic:0.0969},"40":{c:"(",d:',429,'162},"41":{c:")",d:',429,'0369},"42":{c:"*",ic:0.149},"43":{c:"+",a:0.1,ic:0.0369},"44":{c:",",a:-0.3,d:0.2,w:0.278},"45":{c:"-",a:0,ic:0.0283',20,':"/",ic:0.162},"',22,'",ic:0.136},"','49":{c:"1',503,'50":{c:"2',503,'51":{c:"3',503,'52":{c:"4',503,'53":{c:"5',503,'54":{c:"6',503,'55":{c:"7',503,'56":{c:"8',503,'57":{c:"9',503,'58":{c:":",ic:0.0582},"59":{c:";",ic:0.0582},"61":{c:"=",a:0,d:-0.1,ic:0.0662},"63":{c:"?",ic:0.122,lig:{"96":62}},"64":{c:"@",ic:0.096},"65":{c:"A",','krn:{"110":-0.0256,"108":-0.0256,"114":-0.0256,"117":-0.0256,"109":-0.0256,"116":-0.0256,"105":-0.0256,"67":-0.0256,"79":-0.0256,"71":-0.0256,"104":-0.0256,"98":-0.0256,"85":-0.0256,"107":-0.0256,"118":-0.0256,"119":-0.0256,"81":-','0.0256,"84','":-0.0767,"','89',525,'86','":-0.102,"','87',529,'101":-0.0511,"97":-0.0511,"111":-0.0511,"100":-0.0511,"99":-0.0511,"103":-0.0511,"113":-0.0511}},"',36,'",ic:0.103','},"',38,287,'145},"','68":{c:"D','",ic:0.094,krn:{"88":-0.0256,"87":-0.0256,"65":-0.0256,"86":-0.0256,"89":-0.0256}},"',52,'",ic:0.12},"',54,'ic:0.133',145,'111',525,'101',525,'117','":-0.0767,"114":-0.0767,"97":-0.0767,"','65',529,'79":-0.0256,"67":-0.0256,"71":-0.0256,"81":-0.0256}},"',56,287,'0872},"',58,'",ic:0.164},"',321,'158},"',64,287,'14},"75":{c:"K',287,'145',145,554,76,'84',525,'89',525,'86',529,'87',529,532,78,559,80,559,'79":{c:"O',540,94,'ic:0.103',145,'65":-0.0767}},"',103,429,'094},"82":{c:"R',287,'0387,',523,'0.0256,"84',525,'89',525,'86',529,'87',529,532,119,542,379,'133',145,'121',525,'101',525,'111',551,'117',525,588,126,559,128,'184',145,'111',525,'101',525,'117',551,'65',529,554,131,'184',145,588,134,'ic:0.158',145,554,143,'194',145,'101',525,'111',551,'117',525,588,147,287,538,149,',ic:0.188',150,',ic:0.105},"97":{c:"a',245,'0767},"',159,'ic:0.0631',145,532,'99":{c:"c',245,'0565',145,532,167,534,145,'108":0.0511}},"','101":{c:"e',245,'0751',145,532,'102":{c:"f',287,'212',145,'39":0.104,"63":0.104,"33":0.104,"41":0.104,"93":0.104},lig:{"105":12,"102":11,"108":13}},"103":{c:"g',272,'0885},"','104":{c:"h',287,658,'105":{c:"i',287,'102},"106":{c:"j",d:',429,538,'107":{c:"k',287,'108},"',195,534,145,671,'109":{c:"m',245,658,'110":{c:"n',245,'0767',145,'39":-0.102}},"111":{c:"o',245,'0631',145,532,'112":{c:"p',272,'0631',145,532,'113":{c:"q',272,683,'114":{c:"r',245,'108',145,532,'115":{c:"s',245,'0821},"116":{c:"t',287,'0949},"117":{c:"u',245,658,'118":{c:"v',245,694,'119":{c:"w',245,'108',145,671,'120":{c:"x',245,'12},"121":{c:"y',272,683,'122":{c:"z',245,'123}},cmbx10',16,':"*"},"',18,',d:0.2,w:0.278},"45":{c:"-",a:0',20,':"/"},"',22,23,24,'67',24,'79',24,'71',24,'85',24,'81',24,35,36,37,38,37,'68":{c:"D',41,'88',24,'87',24,'65',24,'86',24,'89',51,52,37,54,55,56,37,58,37,'73":{c:"I',41,'73',63,64,37,'75":{c:"K',41,'79',24,'67',24,'71',24,'81',51,76,35,78,37,80,37,'79":{c:"O',41,'88',24,'87',24,'65',24,'86',24,'89',51,94,95,'0833,"111',24,'101',24,'97',24,102,103,'1},"82":{c:"R',41,'116',24,'67',24,'79',24,'71',24,'85',24,'81',24,35,119,37,'84":{c:"T',41,'121',24,125,126,37,128,'0139,',55,131,'0139,',55,134,'krn:{"79',24,'67',24,'71',24,'81',51,143,'025',145,125,147,37,149,150,'},"97":{c:"a',152,'118',24,'106":0.0556,"121',24,'119',51,159,160,'99":{c:"c',152,'104',24,'107',51,167,37,'101":{c:"e",a',170,24,'117',24,'98',24,'121',24,'118',24,'119',51,182,'1},"107":{c:"k',41,'97',186,'101',24,'97',24,'111',24,'99',51,195,37,'109":{c:"m',152,'116',24,'117',24,'98',24,'121',24,'118',24,'119',51,'110":{c:"n',152,'116',24,'117',24,'98',24,'121',24,'118',24,'119',51,225,160,227,160,229,'1',231,'},"',233,'},"116":{c:"t',41,'121',24,'119',51,'117":{c:"u',152,'119',51,'118":{c:"v',245,'0139',145,'97',186,'101',24,'97',24,'111',24,'99',51,'119":{c:"w',245,'0139',145,'101',24,'97',24,'111',24,'99',51,270,'},"121":{c:"y',272,'0139',145,'111',24,'101',24,'97',24,102,282,'}}});if(',0,'browser=="MSIE"&&',0,'platform=="mac"){','jsMath.Setup.Styles({".typeset .math":"font-style: normal",".typeset .typeset":"font-style: normal",".typeset .icmr10":"font-family: ','Times','",".typeset .icmmi10":"font-family: ',1020,'; font-style: italic",".typeset .icmbx10":"font-family: ',1020,'; font-weight: bold",".typeset .icmti10":"font-family: ',1020,'; font-style: italic"});}','else{',1019,'serif',1021,1030,1023,1030,1025,1030,1027,0,'Add(',2,',{symbols:[0,','1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,','34,39,60,62,92,94,95,96',',123,124,125,126,127',']});',2,'.SetFont',15,':',2,'.symbols',',cmmi10:[0,',1042,'33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,','91,92,93,94,95,96',1044,'],cmsy10:[',1042,1054,'65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122',1044,'],cmex10:["all"],cmti10:',2,1051,'.concat(36),cmbx10:',2,1051,'});',2,'.LoadFont("cm-fonts");'] +]); diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-unix.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-unix.js new file mode 100644 index 0000000..543c1fd --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-fallback-unix.js @@ -0,0 +1,29 @@ +/* + * jsMath-fallback-unix.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file makes changes needed for when the TeX fonts are not available + * with a browser under Unix. + * + * --------------------------------------------------------------------- + * + * Copyright 2004-2006 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +jsMath.Script.Uncompress([ + ['jsMath.Add(jsMath.TeX,{cmr10',':[{c:"Γ",','tclass:"greek"},{c:"&','Delta;",',2,'Theta;",',2,'Lambda;",',2,'Xi;",',2,'Pi;",',2,'Sigma;",',2,'Upsilon;",',2,'Phi;",',2,'Psi;",',2,'Omega;",','tclass:"','greek','"},{c',':"ff','",ic:0.0778,krn:{"39":0.0778,"63":0.0778,"33":0.0778,"41":0.0778,"93":0.0778},lig:{"105":','14,"108":15},','tclass:"normal"},{c',':"fi",',28,':"fl",',28,':"ffi",',28,':"ffl",',28,':"&#','x131',';",a:0,',28,':"j",d:0.2,',28,37,'x60;",',22,'accent','"},{c:"&#','xB4;",',22,46,47,'x2C7;",',22,46,47,'x2D8;",',22,46,24,':"ˉ',';",',22,46,47,'x2DA;",',22,46,47,'x0327;",',28,37,'xDF;",',28,37,'xE6',39,28,37,'x153',39,28,37,'xF8;",',28,37,'xC6;",',28,37,'x152;",',28,37,'xD8;",',28,':"?",krn:{"108":-0.278,"76":-0.319},',28,':"!",lig:{"96":60},',28,37,'x201D;",',28,':"#",',28,':"$",',28,':"%",',28,':"&",',28,37,'x2019;",krn:{"63":0.111,"33":0.','111},','lig:{"39":34},',28,':"(",','d:0.2,',28,':")",',117,28,':"*",',28,':"+",a',':0.1,',28,':",",a:-','0.3,d:0.2,','w:0.278,',28,':"-",a:0,lig:{"45":123},',28,':".",a:-0.','25,',28,':"/",',28,':"0",',28,':"1",',28,':"2",',28,':"3",',28,':"4",',28,':"5",',28,':"6",',28,':"7",',28,':"8",',28,':"9",',28,':":",',28,':";",',28,37,'xA1;",',28,':"=",','a:0,d:-0.','1,',28,37,'xBF;",',28,':"?",lig:{"96":62},',28,':"@",',28,':"A','",krn:{"','116','":-0.0278,"','67',179,'79',179,'71',179,'85',179,'81',179,'84','":-0.0833,"','89',191,'86','":-0.111',',"87":-0.',113,28,':"B",',28,':"C",',28,':"D',177,'88',179,'87',179,'65',179,'86',179,'89','":-0.0278','},',28,':"E",',28,':"F',177,'111',191,'101',191,'117','":-0.0833,"114":-0.0833,"97":-0.0833,"65":-0.','111,"79',179,'67',179,'71',179,'81',214,'},',28,':"G",',28,':"H",',28,':"I',177,'73":0.','0278','},',28,':"J",',28,':"K',177,'79',179,'67',179,'71',179,'81',214,'},',28,':"L',177,'84',191,'89',191,'86',195,196,113,28,':"M",',28,':"N",',28,':"O',177,'88',179,'87',179,'65',179,'86',179,'89',214,'},',28,':"P',177,'65',191,'111',179,'101',179,'97',179,'46',191,'44":-0.0833},',28,':"Q",d:1,',28,':"R',177,'116',179,'67',179,'79',179,'71',179,'85',179,'81',179,'84',191,'89',191,'86',195,196,113,28,':"S",',28,':"T',177,'121',179,'101',191,'111',226,'0833,"117":-0.0833','},',28,':"U",',28,':"V",','ic:0.0139,krn:{"','111',191,'101',191,'117',226,'111,"79',179,'67',179,'71',179,'81',214,'},',28,':"W",',345,'111',191,'101',191,'117',226,'111,"79',179,'67',179,'71',179,'81',214,'},',28,':"X',177,'79',179,'67',179,'71',179,'81',214,'},',28,':"Y",ic:0.025,','krn:{"101',191,'111',226,339,'},',28,':"Z",',28,':"[",','d',125,28,37,'x201C;",',28,':"]",','d',125,28,37,'x2C6;",',22,46,47,'x2D9;",',22,46,47,'x2018;",lig:{"96":92},',28,':"a','",a:0,krn:{"','118',179,'106":0.','0556,"121',179,'119',214,'},',28,':"b',177,'101','":0.0278,"','111',438,'120',179,'100',438,'99',438,'113',438,'118',179,428,'0556,"121',179,'119',214,'},',28,':"c',425,'104',179,'107',214,'},',28,':"d",',28,':"e",a:0,',28,':"f',26,'12,"102":11,"108":13},',28,':"g",','a:0,d:0.2,ic:0.','0139,krn:{"',428,244,'},',28,':"h',177,'116',179,'117',179,'98',179,'121',179,'118',179,'119',214,'},',28,':"i",',28,41,28,':"k',177,'97','":-0.0556,"','101',179,'97',179,'111',179,'99',214,'},',28,':"l",',28,':"m',425,'116',179,'117',179,'98',179,'121',179,'118',179,'119',214,'},',28,':"n',425,'116',179,'117',179,'98',179,'121',179,'118',179,'119',214,'},',28,':"o',425,'101',438,'111',438,'120',179,'100',438,'99',438,'113',438,'118',179,428,'0556,"121',179,'119',214,'},',28,':"p",a:0,',117,393,438,'111',438,'120',179,'100',438,'99',438,'113',438,'118',179,428,'0556,"121',179,'119',214,'},',28,':"q",a:0,',117,28,':"','r",a:0,',28,':"s",a:0,',28,':"t',177,'121',179,'119',214,'},',28,':"u',425,'119',214,'},',28,':"v",a:0,',345,'97',504,'101',179,'97',179,'111',179,'99',214,'},',28,':"w",a:0,',345,'101',179,'97',179,'111',179,'99',214,'},',28,':"x",a:0,',28,':"y",',475,476,'111',179,'101',179,'97',179,'46',191,'44":-0.0833},',28,':"z",a:0,',28,37,'x2013',';",a:0.1,','ic:0.0278,','lig:{"45":124},',28,37,'x2014',662,663,28,37,'x2DD;",',22,46,47,'x2DC;",',22,46,47,'xA8;",',22,46,'"}],cmmi10',1,'ic:0.139',',krn:{"61":-0.0556,"59":-0.111,"58":-0.111,"127":0.','0833},',22,'igreek"},{c:"&',3,'krn:{"127":0.','167},',22,689,5,'ic:0.',244,',krn:{"127":0.','0833},',22,689,7,691,'167},',22,689,9,'ic:0.0757',698,'0833},',22,689,11,'ic:0.0812,krn:{"61',504,'59":-0.0556,"58":-0.0556,"127":0.','0556},',22,689,13,'ic:0.0576',698,'0833},',22,689,15,'ic:0.139',686,'0556},',22,689,17,691,'0833},',22,689,19,'ic:0.11,krn:{"61',504,716,'0556},',22,689,21,'ic:0.0502',698,'0833},',22,689,'alpha',';",a:0,ic:0.','0037',698,244,'},',2,'beta;",','d:0.2,ic:0.','0528',698,'0833},',2,'gamma;",',475,'0556,',2,'delta;",ic:0.0378,krn:{"',716,'0556},',2,'epsilon;",a:0',698,'0556},',22,'symbol"},{c',':"ζ",',758,'0738',698,'0833},',2,'eta;",',475,'0359',698,'0556},',2,'theta;",ic:0.',244,698,'0833},',2,'iota;",a:0',698,'0556},',2,'kappa',39,2,'lambda;",',2,'mu',39,'d:0.2',698,244,'},',2,'nu',751,'0637,krn:{"',716,244,'},',2,'xi;",',758,'046',698,113,2,'pi',751,'0359,',2,'rho',39,'d:0.2',698,'0833},',2,'sigma',751,824,'krn:{"59',504,'58":-0.0556','},',2,'tau',751,'113,krn:{"',716,244,'},',2,'upsilon',751,'0359',698,244,'},',2,'phi',662,'d:0.2',698,'0833},',2,'chi',39,'d:0.2',698,'0556},',2,'psi',662,758,'0359',698,113,2,'omega',751,824,2,'epsilon;",a:0',698,'0833},',22,'greek',47,'x3D1;",',691,'0833},',28,37,'x3D6',751,244,',',28,37,'x3F1',39,'d:0.2',698,'0833},',28,37,'x3C2;",',475,'0799',698,'0833},',28,37,'x3D5',662,'d:0.2',698,'0833},',28,37,'x21BC',';",a:0,d:-0.','2,',22,'harpoon',47,'x21BD',916,'1,',22,'harpoon',47,'x21C0',916,'2,',22,'harpoon',47,'x21C1',916,'1,',22,'harpoon',24,60,'font-size: 133%; ',61,':-.1em; margin:-.2em; left:-.05em\\">&#','x02D3',63,'a',125,22,'symbol"},{c:"&#','x25B7',63,22,948,958,'x25C1',63,22,775,':"0",',28,':"1",',28,':"2",',28,':"3",',28,':"4",',28,':"5",',28,':"6",',28,':"7",',28,':"8",',28,':"9",',28,133,'3,',28,':",",a:-',128,28,':"<',662,28,136,'krn:{"1',504,'65',504,'77',504,'78',504,'89":0.0556,"90":-0.0556},',28,':">',662,28,60,958,'x2605',63,'a:0,','tclass:"symbol"},{c:"&#','x2202;",ic:0.0556',698,'0833},',28,':"A",',691,'139','},tclass:"italic"},{c:"','B",ic:0.0502',698,'0833',1024,'C",ic:0.0715,krn:{"61',179,716,'0833',1024,'D",ic:0.',244,698,'0556',1024,'E",ic:0.0576',698,'0833',1024,'F",ic:0.139',686,'0833',1024,'G",',691,'0833',1024,'H",ic:0.0812,krn:{"61',504,716,'0556',1024,'I",ic:0.0785',698,'111',1024,'J",ic:0.0962',686,'167',1024,'K",ic:0.0715,krn:{"61',504,716,'0556',1024,'L",',691,244,1024,'M','",ic:0.109,krn:{"','61',504,716,'0833',1024,'N',1074,'61',191,'61',179,716,'0833',1024,'O",ic:0.',244,698,'0833',1024,'P",ic:0.139',686,'0833',1024,'Q",d:0.2',698,'0833',1024,'R",ic:0.00773',698,'0833',1024,'S",ic:0.0576,krn:{"61',504,716,'0833',1024,'T','",ic:0.139,krn:{"','61',179,716,'0833',1024,'U',1074,'59',195,',"58',195,',"61',504,'127":0.',244,1024,'V",ic:0.222,krn:{"59','":-0.167,"','58',1130,'61',195,1024,'W',1112,'59',1130,'58',1130,'61',195,1024,'X",ic:0.0785,krn:{"61',191,'61',179,716,'0833',1024,'Y",ic:0.222,krn:{"59',1130,'58',1130,'61',195,1024,'Z",ic:0.0715,krn:{"61',504,716,'0833},',22,'italic',47,'x266D;",',22,'symbol2',47,'x266E;",',22,'symbol2',47,'x266F;",',22,'symbol2',47,'x2323',916,'1,',28,37,'x2322',916,'1,',28,37,'x2113;",',691,113,22,775,':"a",a:0,',22,'italic"},{c:"','b",',22,1195,'c",a:0',698,'0556',1024,'d',177,'89":0.0556,"90',504,'106',195,',"102',1130,1126,'167',1024,'e",a:0',698,'0556',1024,'f",',758,'108,krn:{"',716,'167',1024,'g",',475,'0359',698,244,1024,'h',177,'127',214,1024,'i",',22,1195,'j",',758,'0572,krn:{"59',504,837,1024,'k",ic:0.0315,',22,1195,'l",ic:0.0197',698,'0833',1024,'m",a:0,',22,1195,'n",a:0,',22,1195,'o",a:0',698,'0556',1024,'p",a:0,d:0.2',698,'0833',1024,'q",',475,'0359',698,'0833',1024,599,663,'krn:{"',716,'0556',1024,'s",a:0',698,'0556',1024,'t",',691,'0833',1024,'u",a:0',698,244,1024,'v",a:0,ic:0.0359',698,244,1024,'w",a:0,ic:0.0269',698,'0833',1024,'x",a:0',698,244,1024,'y",',475,'0359',698,'0556',1024,'z",a:0,ic:0.044',698,'0556},',22,'italic',47,'x131;",a:0',698,244,1024,'j",d:0.2',698,'0833},',22,'italic',47,'x2118',39,'d:0.2',698,113,28,60,'position:relative; left: .4em; top: -.8em; font-size: 50%\\">→',63,'ic:0.154,',1016,'x0311;",ic:0.399,',22,'normal"}],cmsy10:[{c',37,'x2212',662,1016,'xB7',916,'2,',1016,'xD7',39,22,948,61,':.2em\\">*',63,'a:0,',1016,'xF7',39,1016,'x25CA;",',1016,'xB1',662,1016,'x2213;",',1016,'x2295;",',1016,'x2296;",',1016,'x2297;",',1016,'x2298;",',1016,'x2299;",',1016,'x25EF;",',22,948,61,':.25em;\\">°',63,166,'1,',1016,'x2022',916,'2,',1016,'x224D',662,1016,'x2261',662,1016,'x2286;",',1016,'x2287;",',1016,'x2264;",',1016,'x2265;",',1016,'x227C;",',1016,'x227D;",',22,775,':"~",',166,'2,',28,37,'x2248',662,'d:-0.1,',1016,'x2282;",',1016,'x2283;",',1016,'x226A;",',1016,'x226B;",',1016,'x227A;",',1016,'x227B;",',1016,'x2190',916,'15,',22,'arrows"},{c:"&#','x2192',916,'15,',22,1431,'x2191',';",h:1,',22,1431,'x2193',1438,22,1431,'x2194',39,22,1431,'x2197',1438,22,1431,'x2198',1438,22,1431,'x2243',662,1016,'x21D0',662,22,1431,'x21D2',662,22,1431,'x21D1;",h:0.9,d',125,22,1431,'x21D3;",h:0.9,d',125,22,1431,'x21D4',662,22,1431,'x2196',1438,22,1431,'x2199',1438,22,1431,'x221D',662,22,948,940,'margin-right',': -.1em; position: relative; top:.4em\\">′',63,'a:0,',1016,'x221E',662,1016,'x2208;",',1016,'x220B;",',1016,'x25B3;",',1016,'x25BD;",',22,775,136,22,948,'font-size:50%; ',61,':-.3em; ',1493,':-.2em\\">|",a:0,',28,37,'x2200;",',1016,'x2203;",',1016,'xAC',916,'1,',22,'symbol1',47,'x2205;",',1016,'x211C;",',1016,'x2111;",',1016,'x22A4;",',1016,'x22A5;",',1016,'x2135;",',22,775,':"A',177,'48":0.194},',22,'cal"},{c:"','B",ic:0.0304',',krn:{"48":0.','139},',22,1547,'C",ic:0.0583',1549,'139},',22,1547,'D",ic:0.',244,1549,'0833},',22,1547,'E",ic:0.0894',1549,113,22,1547,'F",ic:0.0993',1549,113,22,1547,'G",',758,'0593',1549,113,22,1547,'H",ic:0.00965',1549,113,22,1547,'I",ic:0.0738',1549,244,'},',22,1547,'J",',758,'185',1549,'167},',22,1547,'K",ic:0.0144',1549,'0556},',22,1547,'L',177,'48":0.139},',22,1547,'M',177,'48":0.139},',22,1547,'N",ic:0.147',1549,'0833},',22,1547,'O",ic:0.',244,1549,113,22,1547,'P",ic:0.0822',1549,'0833},',22,1547,'Q",d:0.2',1549,113,22,1547,'R',177,'48":0.0833},',22,1547,'S",ic:0.075',1549,'139},',22,1547,'T",ic:0.254',1549,244,'},',22,1547,'U",ic:0.0993',1549,'0833},',22,1547,'V",ic:0.0822',1549,244,'},',22,1547,'W",ic:0.0822',1549,'0833},',22,1547,'X",ic:0.146',1549,'139},',22,1547,'Y",ic:0.0822',1549,'0833},',22,1547,'Z",ic:0.0794',1549,'139},',22,'cal',47,'x22C3;",',1016,'x22C2;",',1016,'x228E;",',1016,'x22C0;",',1016,'x22C1;",',1016,'x22A2;",',1016,'x22A3;",',22,'symbol2',47,'xF8F0;",','a:',128,28,37,'xF8FB;",','a:',128,28,37,'xF8EE;",','a:',128,28,37,'xF8F9;",','a:',128,28,':"{",',117,28,':"}",',117,28,37,'x3008;",','a:',128,28,37,'x3009;",','a:',128,28,':"|",d',125,22,'vertical"},{c',':"||",','d:0,',22,'vertical',47,'x2195',1438,'d:0.15,',22,1431,'x21D5;",a:0.2,d',125,22,1431,'x2216;",','a:0.3,d',125,28,37,'x2240;",',22,948,61,': .8em\\">√',63,'h:0.04,d:0.9,',28,37,'x2210;",a:0.4,',1016,'x2207;",',1016,'x222B',1438,'d',125,'ic:0.111,',22,'root',47,'x2294;",',1016,'x2293;",',1016,'x2291;",',1016,'x2292;",',1016,'xA7;",d',125,28,37,'x2020;",d',125,28,37,'x2021;",d',125,28,37,'xB6;",a:0.3,d',125,28,37,'x2663;",',1016,'x2666;",',1016,'x2665;",',1016,'x2660;",',22,'symbol"}],cmex10:[{c',116,'h:0.04,d:1.16,n:','16,',22,'delim1"},{c',119,1812,'17,',22,1815,402,1812,'104,',22,1815,409,1812,'105,',22,'delim1',47,'xF8F0",',1812,'106,',22,'delim1',47,1704,1812,'107,',22,'delim1',47,1709,1812,'108,',22,'delim1',47,1714,1812,'109,',22,1815,1718,1812,'110,',22,1815,1721,1812,'111,',22,'delim1',47,1725,1812,'68,',22,'delim1c',47,1730,1812,'69,',22,'delim1c',24,':"|",','h:0.7,d:0,delim:{rep:','12},',22,1737,1738,1879,'13},',22,1737,136,1812,'46,',22,'delim1b',47,1752,1812,'47,',22,'delim1b','"},{c:"(",','h:0.04,d:1.76,n:','18,',22,'delim2',24,119,1900,'19,',22,'delim2',1899,'h:0.04,d:2.36,n:','32,',22,'delim3"},{c',119,1911,'33,',22,1914,402,1911,'34,',22,1914,409,1911,'35,',22,'delim3',47,1699,1911,'36,',22,'delim3',47,1704,1911,'37,',22,'delim3',47,1709,1911,'38,',22,'delim3',47,1714,1911,'39,',22,1914,1718,1911,'40,',22,1914,1721,1911,'41,',22,'delim3',47,1725,1911,'42,',22,'delim3c',47,1730,1911,'43,',22,'delim3c',24,136,1911,'44,',22,'delim3b',47,1752,1911,'45,',22,'delim3b',1899,'h:0.04,d:2.96,','n:48,',22,'delim4"},{c',119,1989,'n:49,',22,1992,402,1989,'n:50,',22,1992,409,1989,'n:51,',22,'delim4',47,1699,1989,'n:52,',22,'delim4',47,1704,1989,'n:53,',22,'delim4',47,1709,1989,'n:54,',22,'delim4',47,1714,1989,'n:55,',22,1992,1718,1989,'n:56,',22,1992,1721,1989,'n:57,',22,'delim4',47,1725,1989,22,'delim4c',47,1730,1989,22,'delim4c',24,136,1989,22,'delim4b',47,1752,1989,22,'delim4b',24,136,1900,'30,',22,'delim2b',47,1752,1900,'31,',22,'delim2b',47,'xF8EB;",h:0.8,d:0.15,delim:{top:48,bot:64,rep:66},',22,'delim',24,':"&'], + ['#xF8F6',';",h:0.8,d:0.15,delim:{','top:','49,bot:65,rep:67','},tclass:"delim"},{c:"&#','xF8EE',1,2,'50,bot:52,rep:54',4,'xF8F9',1,2,'51,bot:53,rep:55',4,'xF8F0',1,'bot:52,rep:54',4,'xF8FB',1,'bot:53,rep:55',4,'xF8EF',1,2,'50,rep:54',4,'xF8FA',1,2,'51,rep:55',4,'xF8F1',1,2,'56,mid:60,bot:58,rep:62',4,'xF8FC',1,2,'57,mid:61,bot:59,rep:62',4,'xF8F3',1,'top:56,bot:','58,rep:62',4,'xF8FE',1,'top:57,bot:','59,rep:62',4,'xF8F2',1,'rep:63',4,'xF8FD',1,'rep:119',4,'xF8F4',1,'rep:62},tclass:"delim"},{c:"|",','h:0.65,d:0,delim:{top:','120,bot:121',',rep:63},tclass:"','vertical','"},{c:"&#','xF8ED',1,45,'59,rep:62',4,'xF8F8',1,50,'58,rep:62',4,'xF8EC',1,'rep:66',4,'xF8F7',1,'rep:67',4,'x3008;",','h:0.04,d:1.76,n:','28',',tclass:"','delim2c',68,'x3009;",',88,'29',90,91,68,'x2294',';",h:0,d:1,n:','71',90,'bigop1',68,'x2294',';",h:0.1,d:1.5,tclass:"','bigop2',68,'x222E',';",h:0,d:1.11,ic:0.095,n:','73',90,'bigop1c',68,'x222E;",h:0,d:2.22,ic:0.222',90,'bigop2c',68,'x2299',100,'75',90,103,68,'x2299',106,107,68,'x2295',100,'77',90,103,68,'x2295',106,107,68,'x2297',100,'79',90,103,68,'x2297',106,107,68,'x2211',100,'88',90,'bigop1a',68,'x220F',100,'89',90,153,68,'x222B',110,'90',90,113,68,'x222A',100,'91',90,'bigop1b',68,'x2229',100,'92',90,171,68,'x228E',100,'93',90,171,68,'x2227',100,'94',90,103,68,'x2228',100,'95',90,103,68,'x2211;",h:0.1,d:1.6',90,'bigop2a',68,'x220F',106,199,68,'x222B;",h:0,d:2.22,ic:0.222',90,117,68,'x222A',106,'bigop2b',68,'x2229',106,211,68,'x228E',106,211,68,'x2227',106,107,68,'x2228',106,107,68,'x2210',100,'97',90,153,68,'x2210',106,199,68,'xFE3F;",h:0.','722,w:0.65,n:99',90,'wide1',68,239,'85,w:1.1,n:100',90,'wide2',68,239,'99,w:1.65',90,'wide3',68,'x2053;",h:0.','722,w:0.75,n:102',90,'wide1a',68,254,'8,w:1.35,n:103',90,'wide2a',68,254,'99,w:2',90,'wide3a','"},{c:"[",',88,'20',90,'delim2','"},{c:"]",',88,'21',90,272,68,'xF8F0;",',88,'22',90,272,68,'xF8FB;",',88,'23',90,272,68,'xF8EE;",',88,'24',90,272,68,10,'",',88,'25',90,272,'"},{c:"{",',88,'26',90,272,'"},{c:"}",',88,'27',90,272,'"},{c:"",h:0.','04,d:1.16,n:113',90,'root',313,'190',315,'925em',317,'04,d:1.76,n:114',90,320,313,'250',315,'925em',317,'06,d:2.36,n:115',90,320,313,'320',315,'92em',317,'08,d:2.96,n:116',90,320,313,'400',315,'92em',317,'1,d:3.75,n:117',90,320,313,'500',315,'9em',317,'12,d:4.5,n:118',90,320,313,'625',315,'9em',317,'14,d:5.7',90,320,'"},{c:"||",',64,'126,bot:127',',rep:119},tclass:"',67,68,'x25B5;",h:0.','45,delim:{',2,'120',66,'arrow1',68,'x25BF;",h:0.',376,'bot:121',66,380,313,'67',315,'35em; margin-','left:-.5em\\">&#','x256D',';",h:0.','1',90,'symbol',313,'67',315,390,'right:-.5em\\">&#','x256E',393,'1',90,396,313,'67',315,390,391,'x2570',393,'1',90,396,313,'67',315,390,401,'x256F',393,'1',90,396,68,375,'5,delim:{',2,'126',372,'arrow2',68,382,429,'bot:127',372,433,'"}],cmti10:[{c:"Γ",ic:0.133,','tclass:"igreek"},{c:"&','Delta;",',441,'Theta;",','ic:0.094,',441,'Lambda;",',441,'Xi;",ic:0.153,',441,'Pi;",ic:0.164,',441,'Sigma;",ic',':0.12,',441,'Upsilon;",ic:0.111,',441,'Phi;",ic:0.0599,',441,'Psi;",ic:0.111,',441,'Omega;",ic:0.103',90,'igreek','"},{c:"ff','",ic:0.212,krn:{"39":0.104,"63":0.104,"33":0.104,"41":0.104,"93":0.104},lig:{"105":','14,"108":15},','tclass:"italic"},{c',':"fi','",ic:0.103,',468,':"fl',470,468,':"ffi',470,468,':"ffl',470,468,':"ı",a:0,','ic:0.','0767,',468,':"j",d:0.2,','ic:0.0374,',468,':"`",','tclass:"iaccent"},{c:"&#','xB4;",ic:0.0969,',489,'x2C7;",ic:0.083,',489,'x2D8;",','ic:0.108,',489,'x2C9;",ic:0.103,',489,'x2DA;",tclass:"','iaccent','"},{c:"?",','d:0.17,w:0.46,',468,':"ß",','ic:0.105,',468,':"æ",a:0,','ic:0.0751,',468,':"œ",a:0,',508,468,':"ø",','ic:0.0919,',468,':"Æ",','ic',454,468,':"Œ",','ic',454,468,':"Ø",',445,468,':"?",krn:{"108":-0.','256,"76":-0.321},',468,':"!",','ic:0.124,lig:{"96":','60},',468,':"”",','ic:0.0696,',468,':"#",ic:0.0662,',468,':"$",',468,':"%",ic:0.136,',468,':"&",','ic:0.0969,',468,':"’",','ic:0.124,','krn:{"63":0.','102,"33":0.102},lig:{"39":34},',468,':"(",d:0.2,','ic:0.162,',468,':")",d:0.2,','ic:0.0369,',468,':"*",ic:0.149,',468,':"+",a:0.1,','ic:0.0369,',468,':",",a:-0.3,d:0.2,w:0.278,',468,':"-",a:0,ic:0.0283',',lig:{"45":','123},',468,':".",a:-0.25,',468,':"/",ic:0.162,',468,':"0",ic:0.136,',468,':"1",ic:0.136,',468,':"2",ic:0.136,',468,':"3",ic:0.136,',468,':"4",ic:0.136,',468,':"5",ic:0.136,',468,':"6",ic:0.136,',468,':"7",ic:0.136,',468,':"8",ic:0.136,',468,':"9",ic:0.136,',468,':":",ic:0.0582,',468,':";",ic:0.0582,',468,':"¡",','ic:0.0756,',468,':"=",a:0,d:-0.1,','ic:0.0662,',468,':"¿",',468,':"?",','ic:0.122,','lig:{"96":','62},',468,':"@",ic:0.096,',468,':"A",','krn:{"110":-0.0256,"108":-0.0256,"114":-0.0256,"117":-0.0256,"109":-0.0256,"116":-0.0256,"105":-0.0256,"67":-0.0256,"79":-0.0256,"71":-0.0256,"104":-0.0256,"98":-0.0256,"85":-0.0256,"107":-0.0256,"118":-0.0256,"119":-0.0256,"81":-','0.0256,"84','":-0.0767,"','89',614,'86','":-0.102,"','87',618,'101','":-0.0511,"','97',622,'111',622,'100',622,'99',622,'103',622,'113','":-0.0511','},',468,':"B',470,468,':"C",','ic:0.145,',468,':"D",',445,'krn:{"88','":-0.0256,"','87',646,'65',646,'86',646,'89":-0.','0256},',468,':"E",ic',454,468,':"F','",ic:0.133,krn:{"','111',614,'101',614,'117','":-0.0767,"114":-0.0767,"97":-0.0767,"','65',618,'79',646,'67',646,'71',646,'81":-0.0256','},',468,':"G",ic:0.0872,',468,':"H",ic:0.164,',468,':"I",ic:0.158,',468,':"J",ic:0.14,',468,':"K",',641,'krn:{"79',646,'67',646,'71',646,675,'},',468,':"L",krn:{"84',614,'89',614,'86',618,'87',618,'101',622,'97',622,'111',622,'100',622,'99',622,'103',622,'113',634,'},',468,':"M",ic:0.164,',468,':"N",ic:0.164,',468,':"O",',445,'krn:{"88',646,'87',646,'65',646,'86',646,653,'0256},',468,':"P',470,'krn:{"65":-0.0767},',468,':"Q",d:1,',445,468,':"R",ic:0.0387,',612,'0.0256,"84',614,'89',614,'86',618,'87',618,'101',622,'97',622,'111',622,'100',622,'99',622,'103',622,'113',634,'},',468,':"S",ic',454,468,':"T',660,'121',614,'101',614,'111',666,'117',614,'65":-0.0767},',468,':"U",ic:0.164,',468,':"V",ic:0.','184,krn:{"','111',614,'101',614,'117',666,'65',618,'79',646,'67',646,'71',646,675,'},',468,':"W",ic:0.',789,'65":-0.0767},',468,':"X",ic:0.158,krn:{"79',646,'67',646,'71',646,675,'},',468,':"Y",ic:0.','194',',krn:{"101',614,'111',666,'117',614,'65":-0.0767},',468,':"Z",',641,468,':"[",d:0.1,','ic:0.188,',468,':"“",','ic:0.169,',468,':"]",d:0.1,','ic:0.105,',468,':"ˆ",ic:0.0665,',489,'x2D9;",ic:0.118,',489,'x2018;",',531,'92},',468,':"a','",a:0,ic:0.',483,468,':"b",ic:0.0631',822,622,'97',622,'111',622,'100',622,'99',622,'103',622,'113',634,'},',468,':"c',851,'0565',822,622,'97',622,'111',622,'100',622,'99',622,'103',622,'113',634,'},',468,':"d',470,'krn:{"108":','0.0511},',468,':"e',851,'0751',822,622,'97',622,'111',622,'100',622,'99',622,'103',622,'113',634,'},',468,':"f',466,'12,"102":11,"108":13},',468,':"g','",a:0,d:0.2,ic:0.','0885,',468,':"h",ic:0.',483,468,':"i",ic:0.102,',468,485,641,468,':"k",',495,468,':"l',470,892,'0.0511},',468,':"m',851,483,468,':"n',851,483,'krn:{"39":-0.102},',468,':"o',851,'0631',822,622,'97',622,'111',622,'100',622,'99',622,'103',622,'113',634,'},',468,':"p',919,'0631',822,622,'97',622,'111',622,'100',622,'99',622,'103',622,'113',634,'},',468,':"q',919,'0885,',468,':"r',851,'108',822,622,'97',622,'111',622,'100',622,'99',622,'103',622,'113',634,'},',468,':"s',851,'0821,',468,':"t",ic:0.0949,',468,':"u',851,483,468,':"v',851,'108,',468,':"w',851,1020,892,'0.0511},',468,':"x',851,'12,',468,':"y',919,'0885,',468,':"z',851,'123,',468,':"–",a:0.1,ic:0.','0921',565,'124},',468,':"—",a:0.1,ic:0.','0921,',468,':"˝",',605,489,'x2DC;",ic:0.116,',489,'xA8;",tclass:"',500,'"}],cmbx10:[{c:"&Gamma',';",tclass:"bgreek"},{c:"&','Delta',1056,'Theta',1056,'Lambda',1056,'Xi',1056,'Pi',1056,'Sigma',1056,'Upsilon',1056,'Phi',1056,'Psi',1056,'Omega;",tclass:"bgreek"},{c:"ff','",ic:0.0778,krn:{"39":0.0778,"63":0.0778,"33":0.0778,"41":0.0778,"93":0.0778},lig:{"105":','14,"108":15},','tclass:"bold"},{c',':"fi",',1078,':"fl",',1078,':"ffi",',1078,':"ffl",',1078,481,1078,485,1078,':"`',';",tclass:"baccent"},{c:"&#','xB4',1092,'x2C7',1092,'x2D8',1092,'x2C9',1092,499,'baccent',501,1078,504,1078,507,1078,510,1078,513,1078,516,1078,520,1078,524,1078,527,'278,"76":-0.319},',1078,530,606,'60},',1078,534,1078,':"#",',1078,':"$",',1078,':"%",',1078,543,1078,546,548,'111,"33":0.111},lig:{"39":34},',1078,551,1078,554,1078,':"*",',1078,559,1078,':",",a:-0.3,d:0.2,w:0.278,',1078,':"-",a:0',565,'123},',1078,':".",a:-0.25,',1078,':"/",',1078,':"0",',1078,':"1",',1078,':"2",',1078,':"3",',1078,':"4",',1078,':"5",',1078,':"6",',1078,':"7",',1078,':"8",',1078,':"9",',1078,':":",',1078,':";",',1078,596,1078,599,1078,':"¿",',1078,604,606,'62},',1078,':"@",',1078,':"A",krn:{"116','":-0.0278,"','67',1195,'79',1195,'71',1195,'85',1195,'81',1195,'84','":-0.0833,"','89',1207,'86":-0.','111,"87":-0.111},',1078,':"B",',1078,640,1078,':"D",krn:{"88',1195,'87',1195,'65',1195,'86',1195,653,'0278},',1078,':"E",',1078,':"F",krn:{"111',1207,'101',1207,'117','":-0.0833,"114":-0.0833,"97":-0.0833,"65":-0.','111,"79',1195,'67',1195,'71',1195,'81":-0.0278','},',1078,':"G",',1078,':"H",',1078,':"I",krn:{"73":0.0278},',1078,':"J",',1078,':"K",krn:{"79',1195,'67',1195,'71',1195,1242,'},',1078,':"L",krn:{"84',1207,'89',1207,1210,'111,"87":-0.111},',1078,':"M",',1078,':"N",',1078,':"O",krn:{"88',1195,'87',1195,'65',1195,'86',1195,653,'0278},',1078,':"P",krn:{"65',1207,'111',1195,'101',1195,'97',1195,'46',1207,'44":-0.0833},',1078,742,1078,':"R",krn:{"116',1195,'67',1195,'79',1195,'71',1195,'85',1195,'81',1195,'84',1207,'89',1207,1210,'111,"87":-0.111},',1078,':"S",',1078,':"T",krn:{"121',1195,'101',1207,'111',1235,'0833,"117":-0.0833','},',1078,':"U",',1078,788,'0139,krn:{"','111',1207,'101',1207,'117',1235,'111,"79',1195,'67',1195,'71',1195,1242,'},',1078,807,1331,'111',1207,'101',1207,'117',1235,'111,"79',1195,'67',1195,'71',1195,1242,'},',1078,':"X",krn:{"79',1195,'67',1195,'71',1195,1242,'},',1078,820,'025',822,1207,'111',1235,1325,'},',1078,830,1078,833,1078,836,1078,839,1078,':"ˆ',1092,'x2D9',1092,846,606,'92},',1078,':"a','",a:0,krn:{"','118',1195,'106":0.','0556,"121',1195,'119":-0.','0278},',1078,':"b",krn:{"101','":0.0278,"','111',1409,'120',1195,'100',1409,'99',1409,'113',1409,'118',1195,1402,'0556,"121',1195,1405,'0278},',1078,':"c',1399,'104',1195,'107":-0.0278},',1078,':"d",',1078,':"e",a:0,',1078,':"f',1076,'12,"102":11,"108":13},',1078,':"g',919,1331,1402,'0278},',1078,':"h",krn:{"116',1195,'117',1195,'98',1195,'121',1195,'118',1195,1405,'0278},',1078,':"i",',1078,485,1078,':"k",krn:{"97":-0.0556,"101',1195,'97',1195,'111',1195,'99":-0.','0278},',1078,':"l",',1078,':"m',1399,'116',1195,'117',1195,'98',1195,'121',1195,'118',1195,1405,'0278},',1078,':"n',1399,'116',1195,'117',1195,'98',1195,'121',1195,'118',1195,1405,'0278},',1078,':"o",a:0',822,1409,'111',1409,'120',1195,'100',1409,'99',1409,'113',1409,'118',1195,1402,'0556,"121',1195,1405,'0278},',1078,':"p",a:0,d:0.2',822,1409,'111',1409,'120',1195,'100',1409,'99',1409,'113',1409,'118',1195,1402,'0556,"121',1195,1405,'0278},',1078,':"q",a:0,d:0.2,',1078,':"r",a:0,',1078,':"s",a:0,',1078,':"t",krn:{"121',1195,1405,'0278},',1078,':"u',1399,1405,'0278},',1078,':"v',851,1331,'97":-0.0556,"101',1195,'97',1195,'111',1195,1471,'0278},',1078,':"w',851,'0139',822,1195,'97',1195,'111',1195,1471,'0278},',1078,':"x",a:0,',1078,':"y',919,1331,'111',1195,'101',1195,'97',1195,'46',1207,'44":-0.0833},',1078,':"z",a:0,',1078,1040,'0278',565,'124},',1078,1045,'0278,',1078,':"˝',1092,'x2DC',1092,1053,1102,'"}]});','jsMath.Setup.Styles','({".typeset .math','":"font-style: ','normal','",".typeset .','italic',1622,1625,1624,'bold":"','font-weight: bold',1624,'cmr10','":"font-family: ','serif',1624,'cal',1633,'cursive',1624,'arrows','":"",".typeset .',380,1641,433,1641,'harpoon','":"font-size: ','125%",".typeset .',396,1641,'symbol2',1641,'delim1',1647,'133',315,'75em',1624,'delim1b',1647,'133',315,'8em; margin',': -.1em',1624,'delim1c',1647,'120',315,'8em',';",".typeset .',272,1647,'180',315,1657,1624,'delim2b',1647,'190',315,1663,': -.1em',1624,91,1647,'167',315,'8em',1671,'delim3',1647,'250',315,'725em',1624,'delim3b',1647,'250',315,1663,': -.1em',1624,'delim3c',1647,'240',315,'775em',1671,'delim4',1647,'325',315,'7em',1624,'delim4b',1647,'325',315,1663,': -.1em',1624,'delim4c',1647,'300',315,'8em',1671,'delim',1641,67,1641,'greek',1641,464,1622,1625,1624,'bgreek":"',1630,1624,103,1647,'133%; ','position: relative; top',': .85em; margin:-.05em',1624,153,1647,'100%; ',1745,': .775em',1671,171,1647,'160%; ',1745,': .7em','; margin:-.1em',1624,113,1647,'125%; ',1745,': .',1657,1759,1671,107,1647,'200%; ',1745,': .',1663,':-.07em',1624,199,1647,'175%; ',1745,1758,1671,211,1647,'270%; ',1745,': .62em',1759,1624,117,1647,'250%; ',1745,1758,'; margin:-.17em',1671,242,1647,'67%; ',1745,':-.8em',1624,247,1647,'110%; ',1745,':-.5em',1624,252,1647,'175%; ',1745,':-.32em',1624,257,1647,'75%; ',1745,1807,1624,262,1647,'133%; ',1745,': -.15em',1624,267,1647,'200%; ',1745,': -.05em',1624,320,1641,'accent":"',1745,': .02em',1624,500,'":"',1745,1837,'; font-style: ',1625,1624,1102,'":"',1745,1837,'; ',1630,'"});',1620,'();jsMath.Macro("not','","\\\\mathrel{\\\\','rlap{\\\\kern 4mu/}}");jsMath.Macro("joinrel',1855,'kern-2mu}");jsMath.Box.DelimExtend=jsMath.Box.DelimExtendRelative;jsMath.Box.defaultH=0.8;'] +]); \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-global-controls.html b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-global-controls.html new file mode 100644 index 0000000..0c5ffe7 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-global-controls.html @@ -0,0 +1,106 @@ + + + + + + + + + + +
+ + + +
+ + + + + + + + + +
+
+ + + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-global.html b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-global.html new file mode 100644 index 0000000..1732662 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-global.html @@ -0,0 +1,414 @@ + + + +jsMath Global Frame + + + + + + + + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-loader-omniweb4.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-loader-omniweb4.js new file mode 100644 index 0000000..051110e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-loader-omniweb4.js @@ -0,0 +1,39 @@ +/* + * jsMath-loader-omniweb4.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file synchronizes the jsMath-loader.html file with + * the actual loading of the source javascript file. + * OmniWeb 4 has a serious bug where the loader file is run + * several times (and out of sequence), which plays havoc + * with the Start() and End() calls. + * + * --------------------------------------------------------------------- + * + * Copyright 2006 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +if (window.jsMath.Autoload) { + jsMath.Autoload.Script.endLoad(); +} else { + if (!window.phase2) { + jsMath.Script.Start(); + window.phase2 = 1; + } else { + jsMath.Script.End(); + jsMath.Script.endLoad(); + } +} \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-loader-post.html b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-loader-post.html new file mode 100644 index 0000000..0de7cb9 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-loader-post.html @@ -0,0 +1,78 @@ + + + + + + + + + + + + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-loader.html b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-loader.html new file mode 100644 index 0000000..ae9c81e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-loader.html @@ -0,0 +1,92 @@ + + + + + + + + + + + + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-msie-mac.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-msie-mac.js new file mode 100644 index 0000000..cf19f76 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-msie-mac.js @@ -0,0 +1,53 @@ +/* + * jsMath-msie-mac.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file makes changes needed for use with MSIE on the Mac. + * + * --------------------------------------------------------------------- + * + * Copyright 2004-2006 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +/* + * MSIE crashes if it changes the page too quickly, so we add a + * delay between processing math entries. Unfortunately, this really + * slows down math in MSIE on the mac. + */ + +jsMath.Add(jsMath,{ + + msieProcess: jsMath.Process, + msieProcessBeforeShowing: jsMath.ProcessBeforeShowing, + + Process: function () { + // we need to delay a bit before starting to process the page + // in order to avoid an MSIE display bug + jsMath.Message.Set("Processing Math: 0%"); + setTimeout('jsMath.msieProcess()',jsMath.Browser.delay); + }, + + ProcessBeforeShowing: function () { + // we need to delay a bit before starting to process the page + // in order to avoid an MSIE display bug + setTimeout('jsMath.msieProcessBeforeShowing()',5*jsMath.Browser.delay); + } + +}); + +jsMath.Browser.delay = 75; // hope this is enough of a delay! diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-old-browsers.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-old-browsers.js new file mode 100644 index 0000000..35dcf18 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath-old-browsers.js @@ -0,0 +1,58 @@ +/* + * jsMath-old-browsers.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file makes changes needed by older versions of some browsers + * + * --------------------------------------------------------------------- + * + * Copyright 2004-2006 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +jsMath.Add(jsMath.HTML,{ + /* + * Use the blank GIF image for spacing and rules + */ + Blank: function (w,h,d,isRule) { + var style = ''; + if (isRule) { + if (h*jsMath.em < 1.5) {h = '1px'} else {h = jsMath.HTML.Em(h)} + style = 'border-top:'+h+' solid;'; h = 0; + } + if (d == null) {d = 0} + style += 'width:'+this.Em(w)+'; height:'+this.Em(h+d)+';'; + if (d) {style += 'vertical-align:'+this.Em(-d)} + return ''; + } +}); + +if (jsMath.browser == 'Konqueror') { + + jsMath.Package(jsMath.Box,{Remeasured: function() {return this}}); + + jsMath.Add(jsMath.HTML,{ + Spacer: function (w) { + if (w == 0) {return ''}; + return '' + + ' '; + } + }); + + jsMath.Browser.spaceWidth = this.EmBoxFor('     ').w/5; + +} + +jsMath.styles['.typeset .spacer'] = ''; diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath.js new file mode 100644 index 0000000..fb981d8 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/jsMath.js @@ -0,0 +1,51 @@ +/***************************************************************************** + * + * jsMath: Mathematics on the Web + * + * This jsMath package makes it possible to display mathematics in HTML pages + * that are viewable by a wide range of browsers on both the Mac and the IBM PC, + * including browsers that don't process MathML. See + * + * http://www.math.union.edu/locate/jsMath + * + * for the latest version, and for documentation on how to use jsMath. + * + * Copyright 2004-2008 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *****************************************************************************/ + +if (!window.jsMath) {jsMath = {}} +if (!jsMath.Script) {jsMath.Script = {}} + +jsMath.Script.Uncompress = function (data) { + for (var k = 0; k < data.length; k++) { + var d = data[k]; var n = d.length; + for (var i = 0; i < n; i++) {if (typeof(d[i]) == 'number') {d[i] = d[d[i]]}} + data[k] = d.join(''); + } + eval(data.join('')); +} + +//start = new Date().getTime(); +jsMath.Script.Uncompress([ + ['if(!','window.','jsMath','||!',1,'jsMath.','loaded','){var ','jsMath_old','=',1,2,';',0,'document.','getElementById','||!',14,'childNodes||!',14,'createElement','){','alert("','The',' mathematics ','on this page requires W3C DOM support in its JavaScript. Unfortunately, your ','browser',' doesn\'t seem to have this.")}','else{',1,2,'={version:"3.6c",document:document,','window',':',32,',','platform',':(','navigator.',36,'.match(/','Mac/)?"mac":',38,36,40,'Win/)?"pc":"unix"),','sizes',':[50,60,70,85,100,120,144,173,207,249],styles:{".math','":{"font-family":"serif","font-style":"normal","font-weight":"normal','"},".typeset',48,'","line-height":"normal','","text-indent":"0px','","white-space":"','normal','"},".typeset .',54,48,'"},"div','.typeset','":{"text-align":"','center",margin:"1em 0px"},"span',59,60,'left',49,' span',60,'left",border',':"0px",margin:"0px','",padding',':"0px"},"a .typeset img, .typeset a img','":{border:"0px','","border-bottom":"','1px solid',' blue;"},".typeset .size0','":{"font-size":"','50','%"},".typeset .','size1',76,'60',78,'size2',76,'70',78,'size3',76,'85',78,'size4',76,'100',78,'size5',76,'120',78,'size6',76,'144',78,'size7',76,'173',78,'size8',76,'207',78,'size9',76,'249',78,'cmr10','":{"font-family":"jsMath-',115,', serif',55,'cmbx10',116,120,', ',2,'-cmr10',55,'cmti10',116,127,', ',2,125,55,'cmmi10',116,134,55,'cmsy10',116,138,55,'cmex10',116,142,55,'textit','":{"font-family":"','serif","','font-style":"italic',55,'textbf',147,'serif","font-weight":"bold',55,'link":{"','text-decoration":"none',55,'error',76,'90%","',149,'","background-color','":"#FFFFCC',70,':"1px','",border:"',74,' #CC0000',55,'blank','":{display:"','inline-block','",overflow:"','hidden',166,'0px none",width:"0px",height:"0px',55,'spacer',171,172,'"},"#','jsMath_hiddenSpan":{','visibility:"hidden",position:"absolute",','top:"0px",left:"0px',51,52,181,'jsMath_message','":{position:"fixed",bottom:"','1px",left:"2px',162,'":"#E6E6E6','",border:"solid 1px #959595",margin:"0px",padding:"','1px 8px','","z-index":"','102','",color:"black","font-size":"','small",width:"auto','"},"#jsMath_panel',189,'1.75em",right:"1.5em',70,':".8em 1.6em',162,'":"#DDDDDD',166,'outset 2px',195,'103",','width:"auto',197,'10pt","font-style":"',54,199,' .disabled":{color:"#888888',199,' .infoLink',76,'85%"},"#jsMath_panel *":{"','font-size":"inherit","font-style":"inherit","font-family":"inherit',51,199,' div":{"','background-color":"inherit",color:"inherit"},"#jsMath_panel ','span":{"',224,'td',72,70,69,'","',224,'tr',72,70,69,'","',224,'table',72,70,69,162,'":"inherit",color:"inherit",height:"auto",',210,181,'jsMath_button',189,'1px",right:"2px',162,'":"white',193,'0px 3px 1px 3px',195,'102",color:"black","',156,'","font-size":"x-',198,'",cursor:"hand"},"#',247,' *":{padding:"0px",border',69,51,'","',220,181,'jsMath_global":{"',149,181,'jsMath_noFont',' .message":{"text-align":"center",padding:".8em 1.6em",border:"3px solid #DD0000","background-color":"#FFF8F8",color:"#AA0000","font-size":"',198,181,'jsMath_noFont .link":{padding:"0px 5px 2px 5px',166,'2px outset',162,'":"#E8E8E8',197,'80%",',210,259,'jsMath_PrintWarning',271,'x-',198,'"},"@media print":{"#',247,171,'none',181,'jsMath_Warning',171,'none"}},"@media screen":{"#',283,171,'none"}}},Element',':function(','a','){return ',5,14,15,'("jsMath_"+a)},','BBoxFor',298,'a','){this.','hidden.innerHTML','=\'<','span class="','typeset"><',311,'scale">\'+a+"";var b={w:this.',174,'.offsetWidth',',h:this.',174,'.offsetHeight','};this.',309,'="";return b},EmBoxFor',298,'b){var a=',5,'Global.cache.R;if(!a[this.em]){a[this.em]={}}if(!a[this.em][b]){var c=this.BBoxFor(b);','a[this.em][b]={w:c.w/this.em,h:c.h/this.em}}return a[this.em][b]},','EmBoxForItalics',298,324,5,326,'if(b.match(/|class=\\"(icm|italic|igreek|iaccent)/i)){c.w=c.Mw=','this.BBoxFor','(b+',5,'Browser.','italicString',').w-',5,337,'italicCorrection','}',327,'Init',':function(){','if(',5,'Setup.inited','!=1){',0,5,349,'){',5,'Setup.','Body()}if(',5,349,'!=1){if(',5,349,'==-100','){return}',22,'It looks like ',2,' failed to set up properly (error code "+',5,349,'+"). I will try to keep going, but it could get ugly.");',5,349,'=1}}this.em=this.CurrentEm();','var a=',5,'Global.cache','.B;',0,'a[this.em]){a[this.em]={};','a[this.em].','bb=',334,'("x");var c=',381,'bb.h;',381,'d=',334,'("x"+',5,'HTML.Rule(1,','c/',5,'em)).h-c;if(',5,337,338,'){',381,'ic=',5,305,'(',5,337,338,').w}}',5,337,342,'=',381,'ic;var g=',381,'bb;var e=g.h;var f=',381,'d;this.h=(e-f)/this.em;this.d=f/this.em;this.hd=this.h+','this.d;this.',356,'TeXfonts','();var b=this.EmBoxFor(\'<',311,115,'">M\').w/2;this.TeX.M_height=b*(26/14);this.TeX.h=this.h;this.TeX.d=',419,'TeX.hd=this.hd;this.Img.Scale();',0,'this.initialized',308,356,'Sizes','();this.','Img.UpdateFonts()}this.p_height=(','this.TeX.cmex10[0].','h+',435,'d)/0.85;',429,'=1},ReInit',346,'if(this.','em!=this.CurrentEm()){this.Init()}},CurrentEm',346,375,334,'(\'\').','w/27;if(a>0',300,'a}return ',334,'(\'\').w/13},Loaded',346,'if(',8,7,'b=["Process","ProcessBeforeShowing","ProcessElement","ConvertTeX","ConvertTeX2","ConvertLaTeX","ConvertCustom","CustomSearch","Synchronize","Macro","document"];','for(var a=0;a<','b','.length;a++){','if(',8,'[b[a]]){','delete ',8,'[b[a]]}}}if(',8,'){this.Insert(',2,',',8,')}',8,'=null;',5,6,'=1},Add',298,'c,a){for(var b in a){','c[b]=a[b]}},Insert',298,486,'if(c[b]&&typeof(a[b])=="object"&&(','typeof(c[b])=="','object"||',491,'function")){this.Insert(c[b],a[b])}',28,'c[b]=a[b]}}},Package',298,'b,a',475,'b.prototype,a)}};',5,'Global={isLocal:1,cache:{','T:{},D:{},R:{},B',':{}},ClearCache',346,5,377,'={',503,':{}}},GoGlobal',298,324,'String(',5,1,'location',');var d=(',5,'isCHMmode','?"#":"?");if(b){a=a.replace(/\\?.*/,"")+"?"+b}',5,'Controls.','Reload(',5,'root+"',2,'-global.html"+d+escape(a))},Init',346,'if(',5,'Controls.cookie.','global=="always"&&!',5,'noGoGlobal','){if(',38,'accentColorName',364,0,5,32,'){',5,32,'=',32,'}',5,522,6,'=1;',5,522,'defaults.hiddenGlobal=null;this.GoGlobal(',5,522,'SetCookie(2))}},Register',346,375,5,1,'parent;',0,5,519,'){',5,519,'=(',5,1,516,'.protocol','=="mk:")}try{',0,5,519,308,'Domain()}if(a.',2,'&&a.',5,'isGlobal){a.',5,'Register(',5,32,')}}catch(b){',5,534,'=1}},Domain',346,'if(',38,'appName=="Microsoft Internet Explorer"&&',5,36,'=="mac"&&',38,'userProfile','!=null',364,'if(',5,14,'all&&!',5,1,'opera',364,'if(',32,'==parent',364,'var b=',5,14,'domain',';try{while(true){try{if(parent.',14,'title',601,'){return}}','catch(a){}',0,14,618,'.match(/\\..*\\./)){break}',5,14,618,'=',5,14,618,'.replace(/^[^.]*\\./,"")}}',624,5,14,618,'=b}};',5,'Script={request:null,Init',346,'if(!(',5,531,'asynch&&',5,531,'progress',')){if(',1,'XMLHttpRequest','){try{','this.request','=new ',654,'}catch(c){}if(',656,'&&',5,'root.match','(/^file:\\/\\//)){try{',656,'.open("GET",',5,525,5,'js",false);',656,'.send(null)}catch(','c){',656,'=null;if(',1,'postMessage&&',1,'addEventListener',308,'mustPost','=1;',5,1,679,'("message",',5,'Post.','Listener,false)}}}}',0,656,'&&',1,'ActiveXObject','&&!this.',681,7,'a=["MSXML2.XMLHTTP.5','.0","MSXML2.XMLHTTP','.4',699,'.3',699,'","Microsoft.XMLHTTP"];','for(var b=0;b<','a.length&&!',656,';b++){try{',656,'=new ',694,'(a[b])}catch(c){}}}}',0,656,'||',5,356,'domainChanged',308,'Load=this.delayedLoad;this.needsBody=1}},Load',298,'b,a){','if(a){',5,'Message.Set("Loading "+','b);',5,'Script.','Delay(1);',5,'Script.Push(','this,"xmlRequest",b',');',5,731,5,'Message',',"Clear")}',28,5,731,732,')}},xmlRequest',298,'url){','this.blocking','=1;try{',656,666,'url,false);',656,672,'err){',746,'=0;if(',5,'Translate.','restart&&',5,'Translate.asynchronous){return""}throw Error("jsMath can\'t load the file \'"+url+"\'\\','nMessage: "+err.message)}if(',656,'.status',601,'&&(',656,763,'>=400||',656,763,'<0)){',746,'=0;if(',5,757,'restart&&',5,760,'nError status: "+',656,763,')}',0,'url','.match(/\\.js$/)){','return(',656,'.responseText',')}var tmpQueue','=this.queue;this.queue','=[];',5,1,'eval(',656,788,');',746,'=0;','this.queue=this.queue.concat(','tmpQueue);this.Process();return""},cancelTimeout:30*1000,blocking:0,cancelTimer:null,needsBody:0,queue:[],Synchronize',298,'a,b','){if(typeof(','a)!="string"){',5,731,'null,a,b)}',28,5,731,5,32,',"eval",a)}},Push',298,'a,c,b',308,'queue[','this.queue.length',']=[a,c,b];if(!(',746,'||(this.needsBody&&!',5,14,'body))){this.Process()}},Process',346,'while(',819,'&&!',746,7,'c=this.queue[0];this.queue=this.queue.slice(1);',375,'this.SaveQueue();var b=c[0];var e=c[1];var d=c[2];if(b){b[e](d)}',28,'if(e){e(d)}}this.','RestoreQueue','(a)}},SaveQueue',346,'var a',790,'=[];return a},',837,298,'a){',800,'a)},delayedLoad',298,'a',308,'Push(','this,"','startLoad','",a)},',853,298,'a',7,'b=',5,14,20,'("iframe");b','.style.visibility="',174,'";b.style.','position="absolute";','b','.style.width="','0px";b','.style.height="','0px";if(',5,14,'body.firstChild','){',5,14,'body.insertBefore(b,',5,14,875,')}',28,5,14,'body','.appendChild(','b)}',746,'=1;this.','url=a;if(a','.substr(0,',5,'root.length',')==',5,'root){a=a.substr(',5,895,')}',5,725,'a);this.cancelTimer=setTimeout("',5,728,'cancelLoad','()",this.cancelTimeout);',442,681,'){','b.src=',5,688,853,'(a,b)}',28,'if(a',785,912,5,525,2,'-loader.html"}',28,912,'this.url}}},','endLoad',298,'a){if(this.cancelTimer){clearTimeout(this.cancelTimer);this.cancelTimer=null}',5,688,928,'();',5,737,'.Clear();if(a!="cancel"){',746,'=0;this.Process','()}},Start',346,'this.tmpQueue',790,'=[]},End',346,800,942,');',471,942,'},',907,298,'b,',930,'if(b==null){b','="Can\'t load file"}if(a==null){a=2000}',5,737,'.Set(b);setTimeout(\'',5,728,928,'("cancel")\',a)},Delay',298,'a){',746,'=1;setTimeout("',5,728,'endDelay','()",a)},',971,346,746,939,'()},','imageCount',':0,WaitForImage',298,'b){',746,891,978,'++;',442,'img==null',308,'img=[]}',375,'new Image',433,'img[this.img.length]=a;a.onload=function(){if(--',5,728,978,'==0){',5,728,971,'()}};a.onerror=a.onload;a.onabort=a.onload;a.src=b},Uncompress',298,'data){for(var k=0;k\'+b[65].c','+"");b.hd=a.h;b.d=',5,1551,'+',5,392,'b.hd)+"").h-b.hd;b.h=b.hd-b.d;','if(c=="',134,'"){b.skewchar=','127}',28,1559,138,1561,'48}}},',421,346,465,5,1531,467,'if(',5,1531,'[a]){this.TeXfont(',5,1531,'[a])}}},Sizes',346,5,'TeXparams','=[];var b;var a;for(a=0;a<',5,46,467,5,1583,'[a]={}}for(b in ',5,'TeX',804,5,'TeX[b])!="object"){for(a=0;a<',5,46,467,5,1583,'[a][b]=',5,46,'[a]*',5,'TeX[b]/100}}}},Styles',298,'a){',0,'a){a=',5,'styles;a[".typeset .scale"]={"font-size":',5,531,'scale+"%"};this.stylesReady=1}',5,731,852,'AddStyleSheet','",a);if(',5,337,'styleChangeDelay','){',5,731,5,'Script,"Delay",1)}},StyleString',298,'e',7,'a={},f;for(f in e){if(typeof e[f]==="string"){a[f]=e[f]}',28,'if(f',893,'1)==="@"){a[f]=','this.StyleString(','e[f])}',28,'if(e[f]!=null',7,'d=[];for(var c in e[f]){if(e[f][c]!=null){d[d.length]=c+": "+e[f][c]}}a[f]=d.join("; ")}}}}var b="";for(f in a){b+=f+" {"+a[f]+"}\\n"}return b},',1619,298,'d',7,'b=',5,14,1356,'head")[0];if(',324,1637,'d);if(',5,14,'createStyleSheet){b.insertAdjacentHTML("beforeEnd",\'<','span style="display:','none">x")}',28,'var c=',5,14,20,'("style");c.type="text/css";c',888,5,14,1145,'(a));b',888,'c)}}',28,0,5,'noHEAD){',5,'noHEAD=1;',22,'Document is missing its section. Style sheet can\'t be created without it.")}}},Body',346,442,'inited',364,'this.inited=-','1;',5,356,'Hidden();',1685,'2;',5,337,1167,1685,'3;if(',5,531,170,'){',5,737,'.Blank()}',1685,'4;',5,356,'Styles();',1685,'5;',5,522,1167,1685,'6;',5,731,5,'Setup,"User","pre-font");',1685,'7;',5,731,5,'Font,"Check");if(',5,'Font.register.length){',5,731,5,'Font,"LoadRegistered")}this.inited=1},User',298,'a){if(',5,'Setup.UserEvent[a',']){(',5,1735,'])()}},UserEvent:{"pre-font":null,onload:null}};',5,'Update={',421,298,'d){for(var a in d){for(var b in d[a]){for(var c in d[a][b]){',5,'TeX[a][b][c]=d[a][b][c]}}}},TeXfontCodes',298,'c){',1301,705,'c[a].',1361,5,'TeX[a][b].c=c[a][b]}}}};',5,'Browser={allowAbsolute:1,allowAbsoluteDelim:0,','separateSkips',':0,valignBug:0,operaHiddenFix:"",','msieCenterBugFix',':"",','msieInlineBlockFix',':"",msieSpaceFix:"",imgScale:1,renameOK:1,',1623,':0,delay:1,version:0,','TestSpanHeight',346,5,309,'=\'<','span style="\'+this.block','+\';height:2em;width:','1px">\';var b=',5,'hidden.firstChild;',375,1309,';this.','spanHeightVaries','=(b',319,'>=a',319,'&&b',319,'>0);','this.spanHeightTooBig','=(b',319,'>a',319,');',5,309,'=""},','TestInlineBlock',346,'this.block="display',':-','moz-inline-box";','this.hasInlineBlock','=',5,'BBoxFor(\'\').w>0;if','(',1801,'){',5,'styles[".typeset',' .',170,'"].display="-',1800,471,5,1810,' .spacer"].display','}',28,1798,':',172,'";',1801,'=',5,1804,1805,'(!',1801,623,'this.block+=";overflow:',174,'";',375,5,305,'("x").h;this.mozInlineBlockBug=',5,1804,'+";height:"+a+\'px;width:1px','">x','<',1770,'+";height:"+a+"px;width:1px;vertical-align:-"+a+\'px',451,'h>2*a;this.widthAddsBorder=',5,1804,'+\';overflow:',174,';height:1px;width:10px',';border-left:','10px solid',451,'w>10;','this.msieBorderBug','=',5,1804,1842,1843,'\').h!=',5,1804,1842,1854,74,1843,'\').h;','this.blankWidthBug=',1858,'||',5,1804,1771,'0px',451,'h==0},','TestRenameOK',346,5,309,'="";',375,5,1775,'a.setAttribute("name","','jsMath_test','");this.renameOK=(',5,14,'getElementsByName("',1890,'").length>0);',5,309,1795,'TestStyleChange',346,5,309,'=\'x\';var b=',5,1775,375,'b',316,';',5,356,1619,'({"#',1890,'":"font-size:200%"});this.',1623,'=(b',316,'==a);',5,309,1795,'VersionAtLeast',298,324,1407,'this.version',').split(".");','b=',1407,'b',1931,'if(b[1]==null){b[1]="0"}return a[0]>b[0]||(a[0]==b[0]&&a[1]>=b[1])},Init',346,5,26,'="unknown";this.',1796,433,1765,433,1881,433,1900,433,'MSIE',433,'Mozilla',433,'Opera',433,'OmniWeb',433,'Safari',433,'Konqueror();if(','this.allowAbsoluteDelim','){',5,'Box.DelimExtend=',5,'Box.DelimExtendAbsolute;',5,'Box.Layout=',5,'Box.LayoutAbsolute}',28,5,'Box.DelimExtend=',5,'Box.DelimExtendRelative;',5,'Box.Layout=',5,'Box.LayoutRelative}',442,1757,'){',5,'HTML.Place=',5,'HTML.','PlaceSeparateSkips',';',5,'Typeset.prototype.','Place=',5,1989,1986,'}},MSIE',346,442,1779,'&&!',1787,'){',5,26,'="MSIE";if(',5,36,'=="pc"){this.','IE7=(',1,654,601,');','this.quirks','=(',5,14,'compatMode=="BackCompat");this.msieStandard6=!',2012,695,'IE7;',1960,891,1757,'=1',';this.buttonCheck=1;this.','msieBlankBug=1;this.','msieAccentBug',891,'msieRelativeClipBug','=1;this.msieDivWidthBug=1;this.',1254,891,'msieIntegralBug',891,'waitForImages',891,'msieAlphaBug','=!this.IE7;this.','alphaPrintBug',2037,1759,'="position:relative; ";this.',1761,'=" display:',172,';";this.msieTeXfontBaselineBug=!',2012,';',1858,'=',1872,'1;this.msieSpaceFix=\'x";',5,'EmBoxFor=',5,328,'}',28,'if(',5,36,'=="mac"){this.msieAbsoluteBug',891,'msieButtonBug',2029,2025,'quirks=1;',5,356,'Script("',2,'-msie-mac.js");',5,'Parser.prototype.macros.angle=["Replace","ord",\'\',"',54,'"];',5,2096,'width="42em";',5,531,'printwarn=0}}',5,2060,'not',2062,2078,'kern3mu/}}");',5,'Macro("angle","\\\\raise1.','84pt','{\\\\kern2.5mu\\\\rlap{\\\\scriptstyle/}\\\\','kern.5pt\\\\','rule{.4em}{-','1.5pt}{1.84pt}\\\\kern2.5mu}")}},',1951,346,'if(',5,174,'.ATTRIBUTE_NODE&&',5,1,'directories){',5,26,'="',1951,'";if(',5,36,2006,2038,'=1}',1960,'=1;',5,2103,'cursor=',5,2138,'cursor="pointer",',5,2060,'not',2062,2078,'kern3mu/}}");',5,2226,'34pt',2228,2230,'1pt}{1.34pt}\\\\kern2.5mu}");if(',38,'vendor=="Firefox"){',1930,'=',38,'vendorSub}',28,'if(',38,'userAgent.match(" Firefox/([0-9.]+)([a-z ]|$)")){',1930,'=RegExp.$1}}',442,1926,'("3.0")){this.mozImageSizeBug=1}}},',1955,346,'if(',38,'accentColorName){',5,26,'="',1955,'";','this.allowAbsolute','=',1801,';',1960,'=',2296,';this.valignBug=!',2296,2024,1174,'=1;',5,'noChangeGlobal=1;',0,1801,'){jsMath.'], + ['Setup','.Script','("','jsMath','-old-browsers.js','")}}},Opera',':function(){','if(this.','spanHeightTooBig){',3,'.browser="','Opera";','var b=','navigator.userAgent.match','("Opera 7");','this.allowAbsolute=0;this.','delay=10;','this.','operaHiddenFix="[Processing]";if(b){',3,'.Setup.Script','("',3,4,'")}','var a=','navigator.appVersion.match','(/^(\\d+\\.\\d+)/);if(a){','this.version=a','[1]}else{',17,'vesion=0}',17,'operaAbsoluteWidthBug=',17,'operaLineHeightBug=(a[1]>=9.5&&a[1]<9.6)}},Safari',6,'if(',26,'(/Safari\\//)){',3,10,'Safari";if(navigator.vendor','.match(/','Google/)){',3,10,'Chrome"}',25,13,'("Safari/([0-9]+)");a=(a)?a[1]:400;',28,';',3,'.TeX.','axis_height','+=0.05;',17,'allowAbsoluteDelim=','a>=125;',17,'safariIFRAMEbug=a>=312&&a<412;',17,'safariButtonBug=a<412;',17,'safariImgBug=1;',17,'textNodeBug=1;',17,'buttonCheck=a<500;',17,'styleChangeDelay=1;',3,'.Macro("not","\\\\mathrel{\\\\rlap{\\\\kern3.25mu/}}")}},','Konqueror',6,'if(','navigator.product','&&',77,'.match("',74,'")){',3,10,74,'";',15,58,'0;if(',13,'(/',74,'\\/(\\d+)\\.(\\d+)/)){if(RegExp.$1<3||(RegExp.$1==3&&RegExp.$2<3)){',17,'separateSkips=1;',17,'valignBug=1;',3,20,'("',3,4,'")}}',3,'.Add(',3,'.styles,{".typeset .cmr10":"','font-family: ',3,'-','cmr10, ',3,' cmr10',', serif','",".typeset .','cmbx10":"',108,3,'-cmbx10, ',3,' cmbx10, ',3,'-',111,3,113,115,'cmti10":"',108,3,'-cmti10, ',3,' cmti10, ',3,'-',111,3,113,115,'cmmi10":"',108,3,'-cmmi10, ',3,' cmmi10',115,'cmsy10":"',108,3,'-cmsy10, ',3,' cmsy10',115,'cmex10":"',108,3,'-cmex10',', ',3,' cmex10"});',3,'.Font.testFont','="',3,157,', ',3,' cmex10"}}};',3,'.Font={testFont:"',3,157,'",fallback:"symbol",register:[],message:"No ',3,' TeX fonts ','found -- using',' image fonts instead','.
\\nThese may be slow and might not print well.
\\nUse the ',3,' control panel to get additional information','.",','extra_message',':\'Extra',175,'not found:
Using',177,'. This may be slow and might not print well.
\\nUse the ',3,180,'.\',','print_message',':"To print higher-resolution math symbols, click the
\\nHi-Res Fonts for Printing button on the ',3,' control panel.
\\n",','alpha_message',':"If the math symbols print as black boxes, turn off image alpha channels
\\nusing the Options pane of the ',3,194,'Test1',':function(','c,','f,d,e){if(f==null){f=124}if(d==null){d=2}if(e==null){e=""}var b=jsMath.BBoxFor(\'\'+jsMath.TeX[c][f].c+"");var a=jsMath.BBoxFor(\'\'+jsMath.TeX[c][f].c+"");return(','b.w>d*a.w&&b.h!=0)},Test2',200,'c,',202,'a.w>d*b.w&&b.h!=0)},CheckTeX',6,25,3,'.BBoxFor(\'<','span style="','font-family: \'+',3,162,'+\', serif">\'+',3,54,'cmex10[1','].c+"");',3,'.nofonts=((a.w*3>a.h||a.h==0)&&!this.Test1("cmr10','",null,null,"',3,'-"));if(!',3,'.nofonts){','return}','if(',3,'.browser!="Mozilla"||(',3,'.platform','=="mac"&&(!',3,'.Browser.VersionAtLeast(','1.5)||',3,236,'3)))||(',3,233,'!="mac"&&!',3,236,'3))){a=',3,'.BBoxFor(\'<',212,108,'CMEX10, serif">\'+',3,54,'cmex10[1',220,3,222,'"));if(!',3,227,3,20,'("',3,'-BaKoMa-fonts.js")}}},Check',6,25,3,'.Controls.','cookie;',17,'CheckTeX();if(',3,227,'if(a.autofont','||a','.font=="tex"){','a.font=',17,'fallback;if(a.warn){',3,'.nofontMessage=1;a.warn=0;',3,269,'SetCookie(0);if','(',3,'.window.NoFontMessage','){',3,288,'()}else{','this.Message(this.','message)}}}}else{',275,'){a.font="tex"}if(a',277,'return}}if(',3,'.noImgFonts){','a.font="unicode"}if(a','.font=="unicode','"){',3,20,'("',3,'-fallback','-"+',3,233,'+".js");',3,'.Box.TeXnonfallback=',3,'.Box.TeX',';',3,316,'=',3,'.Box.TeXfallback;return}','if(!a.print&&a.printwarn){',17,'PrintMessage','((',3,'.Browser.','alphaPrintBug&&',3,269,'cookie.alpha)?',17,191,'+',17,195,':',17,191,')}if(',3,328,'waitForImages){',3,1,'.Push(',3,1,',"WaitForImage",',3,'.blank)}if(a.font=="symbol"){',3,20,'("',3,308,'-symbols.js");',3,'.Box.TeXnonfallback=',3,316,';',3,316,'=',3,322,3,'.Img.SetFont','({cmr10:["all"],cmmi10:["all"],cmsy10:["all"],cmex10:["all"],cmbx10:["all"],cmti10:["all"]});',3,'.Img.LoadFont','("cm-fonts")},Message',200,'a){if(',3,'.Element("Warning',82,228,12,3,'.Setup.DIV("','Warning','",{});b.innerHTML=\'
\'+a','+\'
<',212,'float:left; ','margin: 8px ','0px 0px 20px">',3,399,'<',212,391,'20px 0px 0px; float:right">


\'},',410,6,25,3,378,'");if(a','){a.style.display="none"}},',325,200,376,3,'.Element("','PrintWarning',82,228,12,3,383,429,385,387,'+\'',3,'\';if(!',3,'.Global.','isLocal&&!',3,'.noShowGlobal){a',502,'+=\'Global \'}if(a.offsetWidth<30){a.style.width="auto"}if(!','this.cookie','.button',423,'MoveButton',6,3,'.fixedDiv.style.','left=','document.body.','scrollLeft+"px";',3,637,'top=',639,'scrollTop+',639,'clientHeight+"px";',3,637,'width=',639,'clientWidth+"px"},GetCookie',6,'if(','this.defaults','==null){',655,'={}}',3,105,655,',',631,');',17,'userSet={};var c=',3,'.document.cookie',';if(',3,'.window.location','.protocol.match(',17,561,')){c=',17,'localGetCookie','();',17,'isLocalCookie','=1}if(c',43,3,'=([^;]+)/)){var d=unescape(RegExp.$1).split(/,/);for(',12,'0;b\'},Blank',1071,'b,f,i,g){var a','="";var e="";','if(g){e+="border-left',':"+this.Em(','b)+" solid;";if(',1151,'widthAddsBorder){b=0}}if(b==0){if(',1151,'blankWidthBug){if(',1151,'quirks','){e+="width:1px',';";a=\'<',1163,'right:-1px">\'}else{if(!g',1178,';margin-right:-1px;"}}}}else{e+="width',1170,'b)+";"}if(i==null){i=0}if(f){var c=this.Em(f+i);if(g&&f*jsMath.em<=1.5){c="1.5px";f=1.5/jsMath.em}e+="height:"+c+";"}if(',1151,'mozInlineBlockBug){i=-f}if(',1151,'msieBorderBug&&!g){i-=jsMath.d}if(i){e+="','vertical-align:"+','this.Em(-i)}return a+\'\'},Rule',1071,'a,b){if(b==null){b','=jsMath.TeX.default_rule_thickness}',1129,'Blank(a,b,0,1)},Class',1071,'a,b){return\'\'+b+""},Place',1071,'b,a,d){',1120,'a)<0.0001){a=0}',1120,'d)<0.0001){d=0}if(a||d){var c=\'<','span style="position',': relative',';\';if(a){c+=" margin-left',1170,'a)+";"}if(d){c+=" top:"+this.Em(-d)+";"}b=c',1201,'>"}return b},PlaceSeparateSkips',1071,'e',',g,f,i,a,h){if(Math.abs(g)<0.0001){g=0}if(Math.abs(f)<0.0001){f=0}','if(f){var d=0;var c=0;','var b="";if(','i!=null){c=','a-h;d=i;b=" width',1170,'a-i)+";"}e=','this.Spacer','(d-c)+\'<',1209,1210,'; top:\'+this.Em(-f)+";left',1170,'c',')+";"+b+\'">\'+',1225,'(-d)+e+',1225,'(c)+""}if(g){e=',1225,'(g)+e}return e},PlaceAbsolute',1071,'d',1218,'var c',1168,1220,1151,'msieRelativeClipBug&&',1221,1225,'(-i);g+=i;e=',1225,'(a-h)}if(',1151,'operaAbsoluteWidthBug){b=" width: "+this.Em(h+2)}d=\'<',1209,':absolute; ',1164,'g)+"; top',1170,'f',1232,'c+d+e+" ";','return d},','Absolute',1071,'b,a,c,e,f){if(f!="none"){',1120,'f)<0.0001){f=0}b=\'<',1209,1255,'top:\'+','jsMath.HTML.','Em(f)+\'; left:0em;">\'+b+" "}if(e=="none"){e=0}b+=this.Blank(a,c-e,e);if(',1151,'msieAbsoluteBug){b=\'<',1209,':relative',';">\'+b+""}b=\'<',1209,1276,';\'+',1151,'msieInlineBlockFix',1201,'>";return b}};','jsMath.Box','=function(c,f,a,b,e){','if(e==null','){e=jsMath.d}this.type="typeset";this.w=a;this.h=b;this.d=e;this.bh=b;this.bd=e;this.x=0;this.y=0;this.mw=0;this.Mw=a;this.html=f;this.format=c};jsMath.Add(',1285,',{defaultH:0,Null',1089,'return new ',1285,'("null","",0,0,0)},Text',1071,'l,k,b,m,j,i){var g=','jsMath.Typeset.AddClass(','k,l);g=','jsMath.Typeset.','AddStyle(','b,m,g);var c','=jsMath.EmBoxFor(','g);var e=',1299,'TeX(b,m);var h=((k=="cmsy10"||k=="cmex10")?c.h-e.h:e.d*c.h/e.hd);var f=new ',1285,'("text",l,c.w,c.h-h,h);f.style=b;f.size=m;f.tclass=k;if(i!=null){f.d=i*e.scale}else{f.d=0}if(j==null||j==1){f.h=0.9*e.M_height}else{f.h=1.1*e.x_height+e.scale*j}return f},TeX',1071,'g,a,d,b){var h=',1095,'a][g];if(h.d==null){h.d=0}if(h.h==null){h.h=0}if(h.img!=null&&h.c!=""){this.TeXIMG(a,g,',1299,'StyleSize(d,b))}var f=',1299,'TeX(d,b).scale;var e=new ',1285,'("text",h.c,h.w*f,h.h*f,h.d*f);e.style=d;e.size=b;if(h.tclass){e.tclass=h.tclass;if(h.img){e.bh=h.img.bh;e.bd=h.img.bd}else{e.bh=f*jsMath.h;e.bd=f*jsMath.d}}else{e.tclass=a;e.bh=f*',1095,'a].h;e.bd=f*',1095,'a].d;if(',1151,'msieFontBug&&','e','.html.match(/&#/)){','e','.html+=\'x\'}}return e},TeXfallback',1071,'b,f,e,o){var m=',1095,'f][b];if(!m.tclass){m.tclass=f}if(m.img!=null){',1129,'TeXnonfallback(b,f,e,o)}if(m.h!=null&&m.a==null){m.a=m.h-1.1*jsMath.TeX.x_height}var n=m.a;var l=m.d;var k=this.Text(m.c,m.tclass,e,o,n,l);var g=',1299,'TeX(e,o).scale;if(m.bh!=null){k.bh=m.bh*g;k.bd=m.bd*g}else{var j=k.bd+k.bh;var i=',1297,'k.tclass,k.html);i=',1299,1300,'e,o,i);k.bd',1302,'i+',1271,'Blank(1,j)).h-j;k.bh=j-k.bd;if(g==1){m.bh=k.bh;m.bd=k.bd}}if(jsMath.',1323,'k',1325,'k',1327,'>\'}return k},TeXIMG',1071,'f,a,t){var o=',1095,'f][a];if(o.img.size!=null&&o.img.size==t&&o.img.best!=null&&o.img.best==','jsMath.Img.best','){return}var g=(',1069,'.scale!=1);var b=',1356,'+t-4;if(b<0){b=0;g=1','}else{if(','b>=','jsMath.Img.fonts','.length){','b=',1364,'.length-1',';g=1}}var s=',1069,'[',1364,'[b]];var k=s[f][a];var i=1/',1069,'.w[',1364,'[b]];if(b!=',1356,'+t-4){if(o.w!=null){i=o.w/k[0]}else{i*=',1364,'[t]/',1364,'[4]*',1364,'[',1356,']/',1364,'[b]}}var p=k[0]*i;var l=k[1]*i;var n=-k[2]*i;var q;var j=(o.w==null||Math.abs(o.w-p)<0.01)?"":" margin-right:"+',1271,'Em(o.w-p)+";";var e="";a=',1069,'.HexCode[a];if(!g&&!',1127,'scaleImg){if(',1151,'mozImageSizeBug||2*p"}else{',1440,'m+\'" ',1192,1151,1444,'+\'" />\'}o.tclass="normal";o.img.bh=l+n;o.img.bd=-n;o.img.size=t;o.img.best=',1356,'},Space',1071,'a){return ','new jsMath.Box("html",',1271,'Spacer(a),a,0,0)},Rule',1071,'a,c){if(c==null){c',1196,'var b=',1271,'Rule(a,c);return ',1456,'b,a,c,0)},GetChar',1071,'b,a){var d=',1095,'a][b];','if(d.img!=null){this.TeXIMG(a,b',',4)}if(d.tclass','==null){d.','tclass=a}if(!d.computedW){d.w',1302,1297,'d.tclass,d.c)).w',';if(d.h',1473,'h=',1285,'.defaultH}if(','d.d',1473,'d=0}d.computedW=1}',1262,'DelimBestFit',1071,'e,j,d,g){if(j==0&&d==0){return null}var i;var f;d','=jsMath.TeX.fam[','d];var a=(g.charAt(1)=="S");var b=(g.charAt(0)=="S");while(j!=null){i=',1095,'d][j];if(i.h==null){i.h=',1285,1482,'i.d==null){i.d=0}f=i.h+i.d;if(i.delim','){return[j,d',',"",e]}if(a&&0.5*f>=e',1497,',"SS",0.5*f]}if(b&&0.7*f>=e',1497,',"S",0.7*f]}if(f>=e||i.n==null',1497,',"T",f]}j=i.n}return null},DelimExtendRelative',1071,'k,x,r,A,e){var s=',1095,'r][x];var q','=this.GetChar(s.delim.','top?s','.delim.top',':s.delim.rep,r);var ','b',1509,'rep,r);var p',1509,'bot?s','.delim.bot',1512,'f=',1297,'b.tclass,b.c);','var l=b.w;var v=b.h+b.d;var g;var d;var m;var o;var u;var t;if(s','.delim.mid){var ','z',1509,'mid,r);t','=Math.ceil((k-(','q.h+q.d)-(','z.h+z.d)-(p.h+p.d))/(2*(b.h+b.d',')));k=2*','t*(b.h+b.d)+(q.h+q.d)+(','z.h+z.d)+(p.h+p.d);if(e){g=0}else{g=k/2+A}d=g;m=',1271,'Place(',1297,'q.tclass,q.c),0,g-q.h',')+',1271,1535,1297,'p.tclass,p.c),-(','q.w+p.w)/2,g-(k-p.d))+',1271,1535,1297,'z.tclass,z.c),-(p.w+z.w)/2,g-(k+z.h-z.d)/2);o=(l-z','.w)/2;if(Math.abs(o)<0.0001){o=0}if(o){m+=jsMath.HTML.Spacer(o)}g-=q.h+q.d+b.h;for(u=0;uv[E]){v[E]=o[C].h}if(o[C].d>x[E]){x[E]=o[C].d}if(C>=g',1365,'g[C]=o[C].w',1362,'o[C].w>g[C]){',1715,'}}if(o[C].bh>f){f=o[C].bh}if(o[C].bd>m){m=o[C].bd}}}if(l[J','.length]==null){','l[J.length]=0}if(f==e){f=0}if(m==e){m=0}var a=G','*(jsMath.hd-0.01)*','L;var u=(p||1)*L/6;var t="";var n=0;var I=0;var s;var F;var q;var r;var c;var b;for(C=0;C0){r=',1285,'.SetList(c,"T",z);t+=',1271,1535,'r.html,I,0);I=g[C]-r.w+k[C]}else{I+=k[C]}}s=-k[g',1368,'];q=(v',1368,')*u+l[0];for(E=0;Eq[A]){q[A]=g[v].h}if(g[v].d>s[A]){s[A]=g[v].d}if(v>=c',1365,'c[v]=g[v].w',1362,'g[v].w>c[v]){',1765,'}}}}if(f[E',1720,'f[E.length]=0}l=(q',1368,')*p+f[0];for(A=0;A")}if(!h.match(/\\$|\\\\\\(/)){',1129,'Text(this.safeHTML(h),"normal","T",l).Styled()}var e=0;var d=0;var g;var f="";var a=[];var b,j;while(e/g,">")}','return ','a},Set',1,'c,b,a',',d){if(','c&&c.type){if(c','.type=="','typeset"){',5,'c}if(c',11,'mlist"){','c.mlist.','Atomize','(b,a);',5,17,'Typeset','(b,a)}if(c',11,'text"){c=this.Text(c.text,c.tclass,b,a,c.ascend||null,c.descend||null);if(d!=0){c','.Styled()}',5,'c}c=this','.TeX(','c.c,c.font,b,a);if(d!=0){c',26,5,'c}',5,3,'Box.Null','()},SetList',1,'d,f,c){var a=[];var g;','for(var b=0;b<','d.length;b++){g=d[b];if(g',11,12,'g=',3,'mItem','.',22,'(g)}a[a','.length]=','g}','var e=','new ',3,22,'(a);',5,'e.',22,'(f,c)}});',3,'Package(',3,'Box,{Styled',':function(){','if(this.','format=="text"){','this.html','=',3,22,'.AddClass(','this.tclass',',',68,');',68,'=',3,22,'.AddStyle(','this.style',',this.size,',68,');delete ',73,';delete ',82,';this.format="html"}',5,'this},','Remeasured',65,66,'w>0','){var a=','this.w;this.w=',3,'EmBoxFor(',68,').w;',66,'w','>this.Mw){this.Mw=this.w','}a=this.w/a;if(Math.abs(a-1)>0.05){this.h*=a;this.d*=a}}',5,'this}});',3,46,'=function(a',',b','){this.type','=a;',3,'Add(this,b)};',3,'Add(',3,46,',{Atom',1,'b,a){',5,'new ',3,46,'(b,{','atom:1,nuc:a})},','TextAtom',1,'e,h,c,b,g','){var f=','new ',3,46,'(e',',{atom:1,nuc:{type:"','text",text:h,tclass:c}});if(b','!=null){f.nuc.','ascend=b}if(g',139,'descend=g}',5,'f},TeXAtom',1,'b,d,a){',5,'new ',3,46,'(b',137,'TeX",c:d,font:a}})},Fraction',1,'b,a,f,d,e,c){',5,'new ',3,46,'("fraction",{from:b,num:a,den:f,','thickness',':d,left:e,right:c})},Space',1,'a){',5,'new ',3,46,'("space",{w:a})},',22,1,'a){',5,'new ',3,46,'("ord",{',128,'HTML',1,'a){',5,'new ',3,46,'("html",{html:a})}});',3,'mList','=function(d,a,b,c){','if(d){','this.mlist','=d}else{',191,'=[]}','if(c==null){c','="T"}if(b==null){b=4}','this.data','={openI:null,overI:null,overF:null,font:a,','size:b,style:c','};this.init={',199,'}};',3,'Package(',3,188,',{Add',1,'a){return(',191,'[','this.mlist.length',']=a)},Get',1,'a){',5,191,'[a]},Length',65,5,212,'},Last',65,'if(',212,'==0){',5,'null}',5,191,'[',212,'-1]},Range',1,'b,',2,'a==null){a=',212,'}',5,'new ',3,188,'(',191,'.slice(b,a+1))},Delete',1,'d,c){',195,'=d}if(',191,'.splice){',191,'.splice(d,c-d+1)}else{var a=[];',40,212,';b++){if(bc){a[a',50,191,'[b]}}',191,'=a}},Open',1,'d){var c=this.Add(new ',3,46,'("boundary",{','data:',197,'}));var a=',197,';',197,'={};for(var b in a){',197,'[b]=a[b]}delete ',197,'.overI',87,197,'.overF;',197,'.openI','=',212,'-1;if(d!=null){c.left=d}',5,'c},Close',1,'c){if(c!=null){c=new ',3,46,267,'right:c})}var e;','var b=',197,283,';var f=',197,'.overI;var ','g=',197,281,197,'=',191,'[b].data;if(f){e=',3,46,'.Fraction(','g.name,{','type:"mlist",mlist:this.Range(','b+1,f-1)},{',312,'f)},g.',161,',g.left,g.right);if(c',96,'new ',3,188,'([',191,'[b],e,c]);e=',3,46,'.Atom("inner",{type:"mlist",mlist:a})}}else{var d=b+1;if(c){this.Add(c);d--}e=',3,46,'.Atom((c)?"inner":"ord",{',312,'d)})}this.Delete(b,this.Length());',5,'this.Add(e)},Over',65,295,197,300,'c=',197,281,'var a=',3,46,310,'c.name,{',312,'open+1,b-1)},{',312,'b)},c.',161,',c.left,c.right);',191,'=[a]},',18,1,248,'var a;var e="";',82,'=d;this.size=c;',40,212,';b++){a=',191,'[b];a.delta=0;if(a',11,'choice"){',191,'=this.',18,'.choice(',82,',a,b,',191,');b--}else{',66,18,'[a.type]){var g=this.',18,'[a.type];g(',82,83,'a,e,this,b)}}e=a}if(a&&a',11,'bin"){a','.type="ord"}','if(',212,'>=2&&a',11,'boundary"&&',191,'[0].type=="boundary"){this.','AddDelimiters','(d,c)}},',394,1,'b,q){var p=-10000;var g=p;var k=p;for(var f=0;f<',212,';f++){var j=',191,'[f];if(j.atom||j',11,'box"){g','=Math.max(','g,j.nuc.h+j.nuc.y);k',405,'k,j.nuc.d-j.nuc.y)}}',52,3,'TeX;var l=',3,22,29,'b,q).','axis_height',';var o',405,'g-l,k+l);var n',405,'Math.floor(e.integer*o/500)*e.delimiterfactor,e.integer*(2*o-e.delimitershortfall))/e.integer;var c=',191,'[0];var m=',191,'[',212,'-1];c.nuc=',3,'Box.Delimiter(','n,c.left,b);m.nuc=',3,429,'n,m.right,b);c.type="open";c.atom=1',87,'c.left;m.type="close";m.atom=1',87,'m.right},',22,1,'c,a){',295,'new ',3,22,'(',191,');',5,'b.',22,'(c,a)}});',3,'Add(',3,188,'.prototype.',18,',{style',1,'d,c,a,e,b){b.','style=a.style},size',1,460,'size=a.size},phantom',1,8,'){var d=','a.nuc=',3,'Box.Set(','a.phantom',',c,b);if(a.h){d.',92,'();d.html=',3,'HTML.Spacer','(d.w)}else{d.html="",d.w=d.Mw=d.mw=0}if(!a.v){','d.h=d.d=0','}d.bd=d.bh=0',87,471,';a.type="box"},','smash',1,8,467,468,3,470,'a.smash',',c,b',').Remeasured();',478,87,490,482,'raise',1,8,'){',468,3,470,'a.nuc,','c,b);var d=a.raise;','a.nuc.html','=',3,'HTML.Place(',506,',0,d,a.nuc.mw,a.nuc.Mw,a.nuc.w);a.nuc.h+=d;a.nuc.d-=d;a','.type="ord";','a.atom=1},lap',1,'d,c,a){',52,3,470,504,'d,c',492,'var b=[e];if(a.lap=="llap"){e.x=-e.w}','else{if(a.lap=="','rlap"){b[1]=',3,'mItem.Space','(-e.w)}',523,'ulap"){e.y=e.d;e.h=e.d=0}',523,'dlap"){e.y=-e.h;e.h=e.d=0}}}}',468,3,'Box.SetList(','b,d,c);if(a.lap=="ulap"||a.lap=="dlap"){a.nuc.h=a.nuc.d=0}a.type="box";delete a.atom},bin',1,'d,b,a,e){if(e&&e.type){var c=e.type;if(c=="bin"||c=="op"||c=="rel"||c=="open"||c=="punct"||c==""||(c=="',391,'e.left!="")){a.type="ord"}}else{a',386,'jsMath.mList.prototype.Atomize.SupSub(','d,b,a)},rel',1,8,9,'d.type&&','d',11,'bin"){d',386,541,8,')},close',1,8,9,546,'d',11,'bin"){d',386,541,8,')},punct',1,8,9,546,'d',11,'bin"){d',386,541,8,')},open',1,8,'){',541,8,')},inner',1,8,'){',541,8,')},','vcenter',1,8,467,3,470,504,'c,b);',52,3,22,29,'c,b);d.y=e.',416,'-(d.h-d.d)/2;',468,'d;a',512,541,8,')},','overline',1,'d,c,a){var ','g=',3,22,29,'d,c);',52,3,470,504,3,22,'.PrimeStyle(','d),c',492,295,'g','.default_rule_thickness',298,3,'Box.Rule(e.w,b);f.x=-f.w;f.y','=e.h+3*b;',468,3,'Box.SetList([','e,f],d,c);a.nuc.','h+=b;a',512,541,'d,c,a)},','underline',1,611,'g=',3,22,29,'d,c);',52,3,470,504,3,22,623,'d),c',492,295,'g',628,298,3,631,'=-e.d-3*b-b;',468,3,635,636,'d+=b;a',512,541,640,'radical',1,'b,m,g',467,3,22,29,'b,m);var k=',3,22,623,'b);var f=',3,470,'g.nuc,k,m',492,'var l=d',628,';var c=l;if(b=="D"||b=="D\'"){c=d.x_height}var a=l+c/4;',52,3,429,'f.h+f.d+a+l,[0,2,112,3,112],b,1);if(e.d>f.h+f.d+a){a=(a+e.d-f.h-f.d)/2}e.y=f.h+a;var j=',3,'Box.Rule(','f.w,l);j.y=e.y-l/2;j.h+=3*l/2;f.x=-f.w;var i=',3,22,'.UpStyle(',3,22,701,'b));','var h=',3,470,'g.root||null,i,m',492,'if(g.root){h.y=0.55*(f.h+f.d+3*l+a)-f.d;e.x',405,'h.w-(11/18)*e.w,0);j.x=(7/18)*e.w;h.x=-(h.w+j.x)}g.nuc=',3,635,'e,h,j,f],b,m);g',512,541,'b,m,g)},accent',1,'b,q,j',132,3,22,29,'b,q);var m=',3,22,623,'b);var i=',3,470,'j.nuc,m,q);var o=i.w;var p;var k;var d=0;if(j.nuc',11,'TeX"){','k=',3,'TeX[j.nuc.font];if(k[j.nuc.c].krn&&k.skewchar){p=k[j.nuc.c].krn[k.skewchar]}d=k[j.nuc.c].ic;if(d==null){d=0}}if(p==null){p=0}var l=j.accent[2];',52,3,'TeX.fam[j.accent[1]];k=',3,'TeX[e];while(k[l].n&&k[k[l].n].w<=o){l=k[l].n}var n=Math.min(i.h,f.x_height);if(j.nuc',11,735,706,3,46,'.Atom("ord",j.nuc);h.sup=j.sup;h.sub=j.sub;h.delta=0;',541,'b,q,h);n+=(h.nuc.h-i.h);i=j.nuc=h.nuc',87,'j.sup',87,'j.sub}var g=',3,'Box',29,'l,e,b,q);g.y=i.h-n;g.x=-i.w+p+(o-g.w)/2;if(',3,'Browser.msieAccentBug){g.html+=',3,476,'(0.1);g.w+=0.1;g.Mw+=0.1}if(k[l].ic||d){g.x+=(d-(k[l].ic||0))*f.scale}j.nuc=',3,635,'i,g],b,q);if(j.nuc.w!=i.w',96,3,526,'(i.w-j.nuc.w);j.nuc=',3,635,'j.nuc,a],b,q)}j',512,541,'b,q,j)},op',1,'c,n,i',132,3,22,29,'c,n);var h;i.delta=0;var m=(c','.charAt(0)=="','D");if(i.limits==null&&m){i.limits=1}if(i.nuc',11,735,295,3,'TeX[i.nuc.font][','i.nuc.c];if(m&&b.n){i.nuc.c=b.n;b=',3,791,'b.n]}h=i.nuc=',3,470,'i.nuc,c,n',');if(b.ic){i.delta=b.ic*f.scale;if(i.limits||!i.sub||',3,'Browser.msieIntegralBug','){h=i.nuc=',3,635,'h,',3,526,'(i.delta)],c,n)}}h.y=-((h.h+h.d)/2-h.d-f.',416,');if(Math.abs(h.y)<0.0001){h.y=0}}if(!h){h=i.nuc=',3,470,798,').',92,'()}if(i.limits){',52,'h.w;var k=h.w;var d=[h];var j=0;var l=0;if(i.sup){var g=',3,470,'i.sup,',3,22,701,'c),n',492,'g.x=((h.w-g.w)/2+i.delta/2)-k;j=f.big_op_spacing5;e',405,'e,g.w);k+=g.x+g.w;g.y=h.h+g.d+h.y+Math.max(f.big_op_spacing1,f.big_op_spacing3-g.d);d[d',50,'g',87,'i.sup}if(i.sub',96,3,470,'i.sub,',3,22,'.DownStyle(','c),n',492,'a.x=((h.w-a.w)/2-i.delta/2)-k;l=f.big_op_spacing5;e',405,'e,a.w);k+=a.x+a.w;a.y=-h.d-a.h+h.y-Math.max(f.big_op_spacing2,f.big_op_spacing4-a.h);d[d',50,'a',87,'i.sub}if(e>h.w){h.x=(e-h.w)/2;k+=h.x}if(ke;c--){f.mlist[c+1]=f.mlist[c]}f.mlist[e+1]=',3,526,'(h[d.nuc.c])}}}}',541,'a,j,g)},fraction',1,'x,n,c){var A=',3,22,29,'x,n);var l=0;if(c.',161,'!=null){l=c.',161,857,'c.from.match(/over/)){l=A',628,'}}var s=(x',785,'D");var g=(x=="D")?"T":(x=="D\'")?"T\'":',3,22,701,'x);var q=(s)?"T\'":',3,22,840,'x);var f=',3,470,'c.num,g,n',492,52,3,470,'c.den,q,n',492,'var k;var j;var i;var o;var m;var h=(s)?A.delim1:A.delim2;var b=[',3,429,'h,c.left,x)];var y=',3,429,'h,c.right,x);if(f.w0){n+=f;m-=f}}i.',92,'();a.',92,'();i.y=n;a.y=-m;i.x=k.delta;if(i.w+i.x>a.w){i.x-=a.w;k.nuc=',3,635,'j,a,i],e,w)}else{a.x-=(i.w+i.x);k.nuc=',3,635,'j,i,a],e,w)}delete k.sup',87,'k.sub}});',3,22,110,112,'="typeset";',191,'=a};',3,'Add(',3,22,',{upStyle:{D:"S",T:"S","','D\'":"S\'","T\'":"S\'",S:"SS','",SS:"SS","','S\'":"SS\'","SS\'":"SS\'"},','downStyle:{D:"S\'",T:"S\'","',1091,'\'",SS:"SS\'","',1093,'UpStyle',1,'a){',5,'this.upStyle[a]},DownStyle',1,'a){',5,'this.downStyle[a]},PrimeStyle',1,2,'a',1044,'a',1046,5,'a}',5,'a+"\'"},StyleValue',1,'b,',2,'b=="S"||b=="S\'"){',5,'0.7*a}if(b=="SS"||b=="SS\'"){',5,'0.5*a}',5,'a},StyleSize',1,'b,a){if(b=="S"||b=="S\'"){a=Math.max(0,a-2)}else{if(b=="SS"||b=="SS\'"){a=Math.max(0,a-4)}}return ','a},TeX',1,1128,3,'TeXparams[a]},AddStyle',1,8,'){if(c=="S"||c=="S\'"){b',405,'0,b-2)}else{if(c=="SS"||c=="SS\'"){b',405,'0,b-4)}}if(b!=4){a=\'\'+a+""}',5,'a},AddClass',1,'a,b){if(a!=""&&a!="normal"){b=',3,'HTML.Class(a,b)}',5,'b}});',3,'Package(',3,22,',{DTsep:{ord',':{op:1,bin:2,rel:3,inner:1},','op',':{ord:1,op:1',',rel:3,inner:1},bin:{ord:2,op:2,open:2,inner:2},rel:{ord:3,op:3,open:3,inner:3},open:{},close',1154,'punct',1156,',rel:1,open:1,close',':1,punct:1,inner:1','},inner',1156,',bin:2,rel:3,open',1162,'}},SSsep:{ord:{op:1},op',1156,'},bin:{},rel:{},open:{},close:{op:1},punct:{},inner:{op:1}},sepW:["","thinmuskip","medmuskip","thickmuskip"],','GetSeparation',1,'a,d,b){if(a&&a.atom&&d.atom){var c=this.DTsep;if(b',785,'S"){c=this.SSsep}',52,'c[a.type];if(e&&e[d.type]!=null){',5,3,'TeX[this.sepW[e[d.type]]]}}',5,'0},',22,1,248,82,360,'var g=-10000;this.w=0;this.mw=0;this.Mw=0;this.h=g;this.d=g;this.bh=this.h;this.bd=this.d;this.tbuf="";this.tx=0;',73,'="";','this.cbuf','="";this.hbuf="";this.hx=0;var a=null;var f;this.x=0;','this.dx=0;',40,212,';b++){f=a;a=',191,'[b];switch(a.type){case"size":','this.FlushClassed();','this.size=a.size;','a=f;break;case"','style":',1198,'if(',82,1044,82,1046,82,'=a.style+"\'"}else{',82,'=a.style}',1200,'space":if(typeof(a.w)=="object"){if(',82,1044,'1)=="S"){a.w=0.5*a.w[0]/18',857,82,785,'S"){a.w=0.7*a.w[0]/18}else{a.w=a.w[0]/18}}}this.dx+=a.w-0;',1200,'html":',1198,'if(this.hbuf==""){this.hx=this.','x}','this.hbuf+=','a.html;a=f;break;default:if(!a.atom&&a.type!="box"){break}a.nuc.x+=this.dx+this.',1170,'(f,a,',82,');','if(a.nuc.x||a.nuc.y){','a.nuc',26,1192,'this.x=this.x+this.w;',66,'x','+a.nuc.x+a.nuc.','mw','\'+b.html+"";','b.h+=b.y;b.d-=b.y;b.x=0;b.y=0','},PlaceSeparateSkips',1,'b){if(b.y',467,'b.Mw-b.w;var c=b.mw;var a=b.Mw-b.mw;b.html=',3,476,'(c-d)+\'<',1348,'; top:\'+',3,1351,'(-b.y)+";left:"+',3,1351,'(d)+"; width:"+',3,1351,'(a)+\';">\'+',3,476,'(-c)+b.html+',3,476,'(d)+""}if(b.x){b.html=',3,476,'(b.x)+b.html}',1356,'}});',3,'Parse',189,52,'new ',3,'Parser','(d,a,b,c);e.Parse();',5,'e};',3,1393,189,'this.string=d;this.i=0;',191,'=new ',3,188,'(null,a,b,c)};',3,'Package(',3,1393,',{cmd:"\\\\",open:"{",close:"}",letter:/[a-z]/i,number:/[0-9]/,scriptargs:/^((math|text)..|mathcal|[hm]box)$/,mathchar:{"!":[5,0,33],"(":[4,0,40],")":[5,0,41],"*":[2,2,3],"+":[2,0,43],",":[6,1,59],"-":[2,2,0],".":[0,1,58],"/":[0,1,61],":":[3,0,58],";":[6,0,59],"<":[3,1,60],"=":[3,0,61],">":[3,1,62],"?":[5,0,63],"[":[4,0,91],"]":[5,0,93],"|":[0,2,106]},special:{"~":"Tilde","^":"HandleSuperscript",_:"HandleSubscript"," ":"Space","\\01','":"Space","\\','t',1411,'r',1411,'n":"Space","\'":"Prime","%":"HandleComment","&":"HandleEntry","#":"Hash"},mathchardef:{braceld:[0,3,122],bracerd:[0,3,123],bracelu:[0,3,124],braceru:[0,3,125],alpha:[0,1,11],beta:[0,1,12],gamma:[0,1,13],delta:[0,1,14],epsilon:[0,1,15],zeta:[0,1,16],eta:[0,1,17],theta:[0,1,18],iota:[0,1,19],kappa:[0,1,20],lambda:[0,1,21],mu:[0,1,22],nu:[0,1,23],xi:[0,1,24],pi:[0,1,25],rho:[0,1,26],sigma:[0,1,27],tau:[0,1,28],upsilon:[0,1,29],phi:[0,1,30],chi:[0,1,31],psi:[0,1,32],omega:[0,1,33],varepsilon:[0,1,34],vartheta:[0,1,35],varpi:[0,1,36],varrho:[0,1,37],varsigma:[0,1,38],varphi:[0,1,39],Gamma:[7,0,0],Delta:[7,0,1],Theta:[7,0,2],Lambda:[7,0,3],Xi:[7,0,4],Pi:[7,0,5],Sigma:[7,0,6],Upsilon:[7,0,7],Phi:[7,0,8],Psi:[7,0,9],Omega:[7,0,10],aleph:[0,2,64],imath:[0,1,123],jmath:[0,1,124],ell:[0,1,96],wp:[0,1,125],Re:[0,2,60],Im:[0,2,61],partial:[0,1,64],infty:[0,2,49],prime:[0,2,48],emptyset:[0,2,59],nabla:[0,2,114],surd:[1,2,112],top:[0,2,62],bot:[0,2,63],triangle:[0,2,52],forall:[0,2,56],exists:[0,2,57],neg:[0,2,58],lnot:[0,2,58],flat:[0,1,91],natural:[0,1,92],sharp:[0,1,93],clubsuit:[0,2,124],diamondsuit:[0,2,125],heartsuit:[0,2,126],spadesuit:[0,2,127],coprod:[1,3,96],bigvee:[1,3,87],bigwedge:[1,3,86],biguplus:[1,3,85],bigcap:[1,3,84],bigcup:[1,3,83],intop:[1,3,82],prod:[1,3,81],sum:[1,3,80],bigotimes:[1,3,78],bigoplus:[1,3,76],bigodot:[1,3,74],ointop:[1,3,72],bigsqcup:[1,3,70],smallint:[1,2,115],triangleleft:[2,1,47],triangleright:[2,1,46],bigtriangleup:[2,2,52],bigtriangledown:[2,2,53],wedge:[2,2,94],land:[2,2,94],vee:[2,2,95],lor:[2,2,95],cap:[2,2,92],cup:[2,2,91],ddagger:[2,2,122],dagger:[2,2,121],sqcap:[2,2,117],sqcup:[2,2,116],uplus:[2,2,93],amalg:[2,2,113],diamond:[2,2,5],bullet:[2,2,15],wr:[2,2,111],div:[2,2,4],odot:[2,2,12],oslash:[2,2,11],otimes:[2,2,10],ominus:[2,2,9],oplus:[2,2,8],mp:[2,2,7],pm:[2,2,6],circ:[2,2,14],bigcirc:[2,2,13],setminus:[2,2,110],cdot:[2,2,1],ast:[2,2,3],times:[2,2,2],star:[2,1,63],propto:[3,2,47],sqsubseteq:[3,2,118],sqsupseteq:[3,2,119],parallel:[3,2,107],mid:[3,2,106],dashv:[3,2,97],vdash:[3,2,96],leq:[3,2,20],le:[3,2,20],geq:[3,2,21],ge:[3,2,21],lt:[3,1,60],gt:[3,1,62],succ:[3,2,31],prec:[3,2,30],approx:[3,2,25],succeq:[3,2,23],preceq:[3,2,22],supset:[3,2,27],subset:[3,2,26],supseteq:[3,2,19],subseteq:[3,2,18],"in":[3,2,50],ni:[3,2,51],owns:[3,2,51],gg:[3,2,29],ll:[3,2,28],not:[3,2,54],sim:[3,2,24],simeq:[3,2,39],perp:[3,2,63],equiv:[3,2,17],asymp:[3,2,16],smile:[3,1,94],frown:[3,1,95],Leftrightarrow:[3,2,44],Leftarrow:[3,2,40],Rightarrow:[3,2,41],leftrightarrow:[3,2,36],leftarrow:[3,2,32],gets:[3,2,32],rightarrow:[3,2,33],to:[3,2,33],mapstochar:[3,2,55],leftharpoonup:[3,1,40],leftharpoondown:[3,1,41],rightharpoonup:[3,1,42],rightharpoondown:[3,1,43],nearrow:[3,2,37],searrow:[3,2,38],nwarrow:[3,2,45],swarrow:[3,2,46],minuschar:[3,2,0],hbarchar:[0,0,22],lhook:[3,1,44],rhook:[3,1,45],ldotp:[6,1,58],cdotp:[6,2,1],colon:[6,0,58],"#":[7,0,35],"$":[7,0,36],"%":[7,0,37],"&":[7,0,38]},delimiter:{"(":[0,0,40,3,0],")":[0,0,41,3,1],"[":[0,0,91,3,2],"]":[0,0,93,3,3],"<":[0,2,104,3,10],">":[0',',2,105,3,11],"\\\\','lt":[0',',2,104,3,10],"\\\\','gt":[0,2,105,3,11],"/":[0,0,47,3,14],"|":[0,2,106,3,12],".":[0,0,0,0,0],"\\\\":[','0,2,110,3,15],"\\\\','lmoustache":[4,3,122,3,64],"\\\\rmoustache":[5,3,123,3,65],"\\\\lgroup":[4,6,40,3,58],"\\\\rgroup":[5,6,41,3,59],"\\\\arrowvert','":[0,2,106,3,','60],"\\\\Arrowvert":[0,2,107,3,61],"\\\\bracevert',1423,'62],"\\\\Vert":[0,2,107,3,13],"\\\\|":[0,2,107,3,13],"\\\\vert',1423,'12],"\\\\uparrow":[3,2,34,3,120],"\\\\downarrow":[3,2,35,3,121],"\\\\updownarrow":[3,2,108,3,63],"\\\\Uparrow":[3,2,42,3,126],"\\\\Downarrow":[3,2,43,3,127],"\\\\Updownarrow":[3,2,109,3,119],"\\\\backslash":[',1421,'rangle":[5',1417,'langle":[4',1419,'rbrace":[5,2,103,3,9],"\\\\lbrace":[4,2,102,3,8],"\\\\}":[5,2,103,3,9],"\\\\{":[4,2,102,3,8],"\\\\rceil":[5,2,101,3,7],"\\\\lceil":[4,2,100,3,6],"\\\\rfloor":[5,2,99,3,5],"\\\\lfloor":[4,2,98,3,4],"\\\\lbrack":[0,0,91,3,2],"\\\\rbrack":[0,0,93,3,3]},macros:{displaystyle',':["HandleStyle","','D"],textstyle',1435,'T"],scriptstyle',1435,'S"],scriptscriptstyle',1435,'SS"],rm',':["HandleFont",','0],mit',1443,'1],oldstyle',1443,'1],cal',1443,'2],it',1443,'4],bf',1443,'6],font',':["Extension","','font"],left:"HandleLeft",right:"HandleRight",arcsin',':["NamedOp",0],','arccos',1457,'arctan',1457,'arg',1457,'cos',1457,'cosh',1457,'cot',1457,'coth',1457,'csc',1457,'deg',1457,'det',':"NamedOp",','dim',1457,'exp',1457,'gcd',1477,'hom',1457,'inf',1477,'ker',1457,'lg',1457,'lim',1477,'liminf',':["NamedOp",null,\'lim','inf\'],limsup',1495,'sup\'],ln',1457,'log',1457,'max',1477,'min',1477,'Pr',1477,'sec',1457,'sin',1457,'sinh',1457,'sup',1477,'tan',1457,'tanh',1457,588,':["HandleAtom","',588,'"],',609,1521,609,'"],',641,1521,641,'"],over',':"HandleOver",','overwithdelims',1532,'atop',1532,'atopwithdelims',1532,'above',1532,'abovewithdelims',1532,'brace',':["HandleOver','","\\\\{","\\\\}"],brack',1544,'","[","]"],choose',1544,'","(",")"],overbrace',':["Extension","leaders"],','underbrace',1550,'overrightarrow',1550,'underrightarrow',1550,'overleftarrow',1550,'underleftarrow',1550,'overleftrightarrow',1550,'underleftrightarrow',1550,'overset',':["Extension","underset-overset"],','underset',1566,'llap',':"HandleLap",','rlap',1570,'ulap',1570,'dlap',1570,'raise:"RaiseLower",lower:"RaiseLower",moveleft',':"MoveLeftRight",','moveright',1578,'frac:"Frac",root:"Root",sqrt:"Sqrt",hbar',':["Macro","\\\\','hbarchar\\\\kern-.5em h"],ne',1582,'not="],neq',1582,'not="],notin',1582,'mathrel{\\\\','rlap{\\\\kern2mu/}}\\\\in"],cong',1582,1589,'lower2mu{\\\\mathrel{{\\\\rlap{=}\\\\raise6mu\\\\sim}}}}"],bmod',1582,'mathbin{\\\\rm mod}"],pmod',1582,'kern 18mu ({\\\\rm mod}\\\\,\\\\,#1)",1],"int":["Macro","\\\\intop\\\\nolimits"],oint',1582,'ointop\\\\nolimits"],doteq',1582,'buildrel\\\\textstyle.\\\\over="],ldots',1582,'mathinner{\\\\','ldotp\\\\ldotp\\\\ldotp}"],cdots',1582,1603,'cdotp\\\\cdotp\\\\cdotp}"],vdots',1582,1603,'rlap{\\\\raise8pt{.\\\\rule 0pt 6pt 0pt}}\\\\rlap{\\\\raise4pt{.}}.}"],ddots',1582,1603,'kern1mu\\\\raise7pt{\\\\rule 0pt 7pt 0pt .}\\\\kern2mu\\\\raise4pt{.}\\\\kern2mu\\\\raise1pt{.}\\\\kern1mu}"],joinrel',1582,1589,'kern-4mu}"],relbar',1582,1589,'smash-}"],Relbar',1582,'mathrel="],bowtie',1582,'mathrel\\\\triangleright\\\\joinrel\\\\mathrel\\\\triangleleft"],models',1582,'mathrel|\\\\joinrel="],mapsto',1582,1589,'mapstochar\\\\','rightarrow}"],rightleftharpoons',1582,588,'{\\\\',1589,'rlap{\\\\raise3mu{\\\\rightharpoonup}}}\\\\leftharpoondown}"],hookrightarrow',1582,'lhook','\\\\joinrel\\\\rightarrow','"],hookleftarrow',1582,'leftarrow\\\\joinrel\\\\','rhook"],Longrightarrow',1582,'Relbar\\\\joinrel\\\\','Rightarrow"],','longrightarrow',1582,'relbar',1637,'"],longleftarrow',1582,1640,'relbar"],Longleftarrow',1582,'Leftarrow\\\\joinrel\\\\','Relbar"],longmapsto',1582,1589,1628,'minuschar',1637,'}"],longleftrightarrow',1582,'leftarrow',1637,'"],','Longleftrightarrow',1582,1654,1644,'iff:["Macro","\\\\;\\\\',1666,'\\\\;"],mathcal',':["Macro","{\\\\','cal #1}",1],mathrm',1673,'rm #1}",1],mathbf',1673,'bf #1}",1],','mathbb',1673,1678,'mathit',1673,'it #1}",1],textrm',1582,'mathord{\\\\hbox{#1}}",1],textit',1582,'mathord{\\\\class{','textit','}{\\\\hbox{#1}}}",1],','textbf',1582,1688,1691,1690,'pmb',1582,'rlap{#1}\\\\kern1px{#1}",1],TeX:["Macro","T\\\\kern-.1667em\\\\lower.5ex{E}\\\\kern-.125em X"],limits:["Limits",1],nolimits:["Limits",0],",":["Spacer",1/6],":":["Spacer",1/6],">":["Spacer",2/9],";":["Spacer",5/18],"!":["Spacer",-1/6],enspace:["Spacer",1/2],quad:["Spacer",1],qquad:["Spacer",2],thinspace:["Spacer",1/6],negthinspace:["Spacer",-1/6],hskip:"Hskip",kern:"Hskip",rule:["Rule","colored"],space:["Rule","blank"],big',':["MakeBig","','ord",0.85],Big',1699,'ord",1.15],bigg',1699,'ord",1.45],Bigg',1699,'ord",1.75],bigl',1699,'open",0.85],Bigl',1699,'open",1.','15],biggl',1699,1710,'45],Biggl',1699,1710,'75],bigr',1699,'close",0.85],Bigr',1699,'close",1.','15],biggr',1699,1721,'45],Biggr',1699,1721,'75],bigm',1699,'rel",0.85],Bigm',1699,'rel",1.15],biggm',1699,'rel",1.45],Biggm',1699,'rel",1.75],mathord',1521,'ord"],mathop',1521,'op"],mathopen',1521,'open"],mathclose',1521,'close"],mathbin',1521,'bin"],mathrel',1521,'rel"],mathpunct',1521,'punct"],mathinner',1521,'inner"],','mathchoice',1455,1753,'"],buildrel:"BuildRel",hbox:"HBox",text:"HBox",mbox:"HBox",fbox',1455,'fbox"],strut:"Strut",mathstrut',1582,'vphantom{(}"],phantom:["Phantom",1,1],vphantom:["Phantom",1,0],hphantom:["Phantom",0,1],smash:"Smash",acute:["MathAccent",[7,0,19]],grave'], + [':["MathAccent",[','7,0,','18]],ddot',0,1,'127]],tilde',0,1,'126]],bar',0,1,'22]],breve',0,1,'21]],check',0,1,'20]],hat',0,1,'94]],vec',0,'0,1,126]],dot',0,1,'95]],widetilde',0,'0,3,101]],widehat',0,'0,3,98]],_:["Replace","ord","_","normal",-0.4,0.1]," ":["Replace","','ord"," ","normal','"],angle:["Macro","\\\\kern2.5mu\\\\raise1.54pt{\\\\rlap{\\\\scriptstyle \\\\char{cmsy10}{54}}\\\\kern1pt\\\\rule{.45em}{-1.2pt}{1.54pt}\\\\kern2.5mu}"],matrix:"Matrix",array:"Matrix",pmatrix:["Matrix','","(",")","c"],','cases:["Matrix","\\\\{",".",["l","l"],null,2],eqalign',':["Matrix",null,null,["','r","l"],[5/18],3,"D"],displaylines',34,'c"],null,3,"D"],cr:"','HandleRow','","\\\\":"',38,'",newline:"',38,'",noalign:"','HandleNoAlign','",eqalignno',34,'r","l","r"],[5/8,3],3,"D"],','leqalignno',34,47,'begin:"Begin",end:"End",tiny',':["HandleSize",','0],Tiny',52,'1],scriptsize',52,'2],small',52,'3],normalsize',52,'4],large',52,'5],Large',52,'6],LARGE',52,'7],huge',52,'8],Huge',52,'9],dots:["Macro","\\\\ldots"],newcommand',':["Extension","','newcommand"],','newenvironment',72,73,'def',72,73,'color',72,'HTML"],','href',72,'HTML"],"class":["Extension","',82,'style',72,82,'cssId',72,82,'unicode',72,82,'bbox',72,'bbox"],require:"Require","char":"Char"},','environments',':{array:"Array",matrix',':["Array','",null,null,"c"],pmatrix',101,32,'bmatrix',101,'","[","]","c"],Bmatrix',101,'","\\\\{","\\\\}","c"],vmatrix',101,'","\\\\vert","\\\\vert","c"],Vmatrix',101,'","\\\\Vert","\\\\Vert","c"],cases',101,'","\\\\{",".","ll",null,2],eqnarray:["','Array",null,null,"rcl",[5/18,5/18],3,"D','"],"eqnarray*":["',116,'"],equation:"Equation","equation*":"Equation",align',72,'AMSmath','"],"align','*":["Extension","AMSmath"],','aligned',72,121,'"],','multline',72,121,'"],"',128,123,'split',72,121,'"],gather',72,121,'"],"gather',123,'gathered',72,121,'"]},AddSpecial',':function(','a){for(var b in a){','jsMath.Parser.prototype','.special[',148,'[b]]=a[b]}},Error',146,'a){this.i=','this.string','.length;','if(a','.error){this.error=a','.error}','else{if(!','this',157,'}}},nextIsSpace',':function(){','return ','this.string.charAt(this.i',').match(/[ \\n\\r\\t]/)},trimSpaces',146,'a){if(typeof(a)!="string"){',164,'a}',164,'a.replace(/^\\s+|\\s+$/g',',"")},','Process',146,'a){var ','c=','this.mlist.data',';a','=jsMath.Parse(','a,c.font,c.size,c.style);if(a','.error){this.Error(','a);','return null','}if(a.mlist.Length()==','0){',184,185,'1','){var b=','a.mlist.','Last();if(','b.atom&&b.type=="ord"&&b.nuc&&!b.sub&&!b.sup&&(b.nuc.type=="text"||b.nuc.type=="TeX")){',164,'b.nuc}}return{type:"mlist",mlist:a.mlist}},GetCommand',':function(){var ','a=/^([a-z]+|.) ?/i;var b=a.exec(','this.string.slice(this.i','));if(b){this.i+=b[1].length;',164,'b[1]}','this.i++;','return" "},GetArgument',146,'b,d){while','(this.nextIsSpace()){this.i','++}','if(this.','i>=',154,'.length){','if(!d){','this.Error("','Missing',' argument for "+b)}',184,'}if(',165,')==this.close){',212,213,'Extra close brace','")}',184,'}if(',165,')==this.cmd){',202,164,'this.cmd+','this.GetCommand','()}if(',165,')!=this.open){',164,165,'++)}var a=++this.i;var e=1;var f="";','while(this.i0){e--;this.i+=2}}}',247,'if(',198,436,'d.length)==d){f=',165,'+d','.length);','if(f.match(/[^a-z]/i)||!d.match(/[a-z]/i)){var a=',154,'.slice(g,this.i-1);this.i+=d',155,164,'a}}}this.i++}}}}',213,406,408,'+d+" for "+b);',184,'},','ProcessUpto',146,'b,c',264,'this.GetUpto','(b,c);',267,268,269,'GetEnd',146,'c){var a="";var b="";while(b!=c){a+=',466,'("begin{"+c+"}","end");',267,268,'b=','this.GetArgument(this.cmd','+"end");',267,324,164,'a},Space',':function(){},','Prime',146,'d',190,'this.mlist.',192,'b==null||(!b.atom&&b','.type!="box"&&','b','.type!="frac")){','b=','this.mlist.Add(jsMath.mItem.','Atom("ord",{type:null}))}','if(b.sup){',213,'Prime causes double exponent',': use braces to clarify");return','}var a','="";while(d=="\'"){a+=this.cmd+"prime";d',381,'d=="\'"){this.i++}}b.sup=this.',174,'(a);b.sup.isPrime=1},RaiseLower',146,176,'b','=this.GetDimen(this.cmd+','a,1);',267,'}var c','=this.ProcessScriptArg','(',230,'a);',267,'}if(a=="lower"){b=-b}','this.mlist.Add(new jsMath.mItem("','raise",{nuc:c,raise:b}))},MoveLeftRight',146,'b){var ','a',512,'b,1);',267,'}var c',516,'(',230,'b);',267,'}if(b=="moveleft"){a=-a}',497,'Space(a','));',497,'Atom("ord",c));',497,'Space(-a))},Require',146,176,'b=',479,409,267,'}b=','jsMath.Extension','.URL(b);if(','jsMath.Setup.','loaded[b]){return}','this.Extension(null,[','b])},Extension',146,'a,b){','jsMath.Translate','.restart=1;if(a','!=null){','delete ',148,'[b[1]||"macros"][a]}',551,'.Require(b[0],',559,'.asynchronous',');throw"restart"},Frac',146,525,'a','=this.ProcessArg(this.cmd+','b);',267,'}var c',573,'b);',267,'}',497,'Fraction("over",a,c))},Sqrt',146,525,'d=',291,230,'b);',267,503,573,'b);',267,'}var c=jsMath.mItem.Atom("','radical",a);','if(d!=""){c.root=this.',174,'(d);',267,'}}',490,'Add(c)},','Root',146,525,'d=this.',462,'(',230,'b,"of");',267,503,573,'b);',267,594,595,'c.root=d;',490,602,'BuildRel',146,176,'b=this.',462,'(',230,'a,"over");',267,'}var d',573,'a);',267,594,'op",d);c.limits=1;c.sup=b;',490,602,'MakeBig',146,337,'c=d[0];var b=d[1]*jsMath.p_height;var e','=this.GetDelimiter(this.cmd+','a);',267,'}',497,'Atom(c,','jsMath.Box.Delimiter(','b,e,"T")))},Char',146,'b',264,479,'+b);',267,'}var c=',479,'+b);',267,'}if(!',365,'[a]){',365,'[a]=[];',555,'jsMath.Font.URL(a',')])}else{',497,'Typeset(','jsMath.Box.TeX(c-0,a,',178,'.style,',178,'.size)))}},Matrix',146,'b,h){var e=',178,';var a=',479,'+b);',267,'}var g=','new jsMath.','Parser(a','+this.cmd+"\\\\",null,','e.size,h[5]||"T");g.matrix=b;g.row=[];g.table=[];g.rspacing=[];g.Parse();if(g',182,'g);return}g.',38,'(',528,'var d','=jsMath.Box.','Layout(e.size,g.table,h[2]||null,h[3]||null,g.rspacing,h[4]||null);if(h[0]&&h[1]){',417,648,'d.h+d','.d-jsMath.hd/4,this.delimiter[','h[0]],"T");var c=',648,'d.h+d',698,'h[1]],"T");d',693,'SetList([','f,d,c],e.style,e.size)}',497,'Atom((h','[0]?"inner":"ord"),','d))},HandleEntry',146,'b){if(!this.matrix){this.Error(b','+" can only appear in a matrix or array");return}if(',178,'.openI!=null',264,490,'Get(',178,'.openI);if','(a.left){',213,214,408,'+"right','")}else{',213,257,'")}}if(',178,'.overI',561,490,'Over()}var d=',178,';',490,'Atomize(','d.style,d.size);','var c=',490,669,739,'c.entry=d.entry;delete d.entry;if(!c.entry){c.entry={}}this.row[','this.row.length',']=c;this.mlist=',683,'mList(null,null,d.size,d.style)},',38,146,'a,c){var b;if(!this.matrix){','this.Error(this.cmd+a',713,'a=="\\\\"){b=',291,230,'a);',267,'}if(b){b=',348,'b,',230,'a,0,1)}}this.HandleEntry(a);if(!c||',745,'>1||this.row[0].format!="null"){this.table[this.table.length]=this.row}if(b){','this.rspacing[this.table.length',']=b}this.row=[]},',44,146,'b',264,479,'+b);',267,656,'a.replace(/^.*(vskip|vspace)([^a-z])/i,"$2");if(c.length==a',211,'return}var ','e=',348,'c,',230,'RegExp.$1,0,1);',267,'}',766,']=(',766,']||0)+e},Array',146,'b,c){var ','e=c[2];var i=c[3];if(!e){e=',479,'+"begin{"+b+"}");',267,'}}e=e.replace(/[^clr]/g,"");e=e.split("");var g=',178,678,'c[5]||"T";var k=this.GetEnd(b);',267,'}',417,683,'Parser(k',685,'g.size,a);f.matrix=b;f.row=[];f.table=[];f.rspacing=[];f.Parse();if(f',182,'f);return}f.',38,'(',528,'var h',693,'Layout(g.size,f.table,e,i,f.rspacing,c[4],c[6],c[7]);if(c[0]&&c[1]){var d=',648,'h.h+h',698,'c[0]],"T");var j=',648,'h.h+h',698,'c[1]],"T");h',693,705,'d,h,j],g.style,g.size)}',497,'Atom((c',709,'h))},Begin',146,176,'b=',479,409,267,'}if(b.match(/[^a-z*]/i)){this.Error(\'Invalid environment name "\'+b+\'"\');return}if(!this.',99,'[b]){this.Error(\'Unknown environment "\'+b+\'"\');return',656,'this.',99,'[b];if(typeof(','c',')=="string"){','c=[c]}this[c[0]](b,c.slice(1))},End',146,176,'b=',479,409,267,'}',752,'+"{"+b+"} without matching',408,'+"begin")},Equation',146,'b',264,'this.GetEnd(b);',267,'}',154,'=a+',198,');this.i=0},Spacer',146,'b,a){',497,538,'-0))},Hskip',146,525,'a',512,'b);',267,'}',497,538,'))},HBox',146,176,'c=',479,409,267,'}var b',693,'InternalMath(c,',178,'.size);',497,669,'b))},Rule',146,'b,f){var a',512,528,267,'}var e',512,528,267,'}var g',512,528,267,'}e+=g;var c;if(e!=0){e=Math.max(1.05/jsMath.em,e)}if(e==0||a==0||f=="blank"){c=','jsMath.HTML.','Blank(a,e)}else{c=',910,'Rule(a,e)}if(g){c=\'\'+c','+""}',497,669,683,'Box("html",c,a,e-g,g)))},Strut',196,'a=',178,'.size;var b',693,'Text("","normal","T",a).Styled();b.bh=b.bd=0;b.h=0.8;b.d=0.3;b.w=b.Mw=0;',497,669,'b))},Phantom',146,791,'a',573,'b);',267,'}',522,'phantom",{phantom:a,v:c[0],h:c[1]}))},Smash',146,791,'a',573,'b);',267,'}',522,'smash",{smash:a}))},MathAccent',146,'b,',176,'e',573,'b);',267,'}var d','=jsMath.mItem.','Atom("accent",e);d.accent=a[0];',490,'Add(d)},NamedOp',146,'c,f){var b=(c.match(/[^acegm-su-z]/))?1:0;var g=(c.match(/[gjpqy]/))?0.2:0;if(f[1]){c=f[1]}var e',956,'TextAtom("','op",c,',365,'.fam[0],b,g);if(f[0]!=null){e.limits=f[0]}',490,'Add(e)},Limits',146,'a,c',190,490,'Last();if(!b||b.type!="op"){',752,'+" is allowed only on operators");return}b.limits=c[0]},Macro',146,'b,d){var e=d[0];if(d[1]){var a=[];for(var c=0;cb',211,213,'Illegal ','macro parameter ','reference");',184,'}e=this.AddArgs(',986,'f),b[g-1]);f=""}}else{f+=g}}}',164,986,'f)},AddArgs',146,'b,a){if(','a.match(/^[a-z]/i)&&b.match(/(^|[^\\\\])(\\\\\\\\)*\\\\[a-z]+$/i)){b+=" "}',164,'b+a},Replace',146,558,497,'TextAtom(','b[0],b[1],b[2','],b[3]))},Hash',146,'a){',213,'You can\'t use \'',1007,'character #\' in math mode")},Tilde',146,'a){',497,963,30,'"))},HandleLap',146,176,624,261,'();',267,'}b=',522,'lap",{nuc:b,lap:a}))},HandleAtom',146,791,'a',573,'b);',267,'}',497,'Atom(c[0],a))},HandleMathCode',146,'a,b','){this.HandleTeXchar(',1025,'])},HandleTeXchar',146,'b,a,c){if(b==7&&',178,'.font',561,'a=',178,'.font}a=',365,'.fam[a];if(!',365,'[a]){',365,'[a]=[];',555,666,')])}else{',497,'TeXAtom(',365,'.atom[b],c,a))}},','HandleVariable',146,'a',1059,'7,1,','a.charCodeAt(0))},','HandleNumber',146,'a',1059,1,1088,'HandleOther',146,'a){',497,963,'ord",a,"normal"))},HandleComment',196,'a;',238,'a=',165,241,'a=="\\r"||a=="\\n"){return}}},HandleStyle',146,558,178,'.style=b[0];',522,'style",{style:b[0]}))},HandleSize',146,558,178,'.size=b[0];',522,'size",{size:b[0]}))},HandleFont',146,868,178,'.font=a[0]},HandleCS',196,'b=',231,'();',267,'}',208,'macros[b]){var a=this','.macros',842,'a',844,'a=[a]}this[a[0]](b,a.slice(1','));return}',208,'mathchardef','[','b]){this.HandleMathCode(b,this.',1139,'[b]);return}if(',326,230,1141,'delimiter[',230,'b].slice(0,3',1137,213,'Unknown control sequence \'"+',230,'b+"\'")},HandleOpen',163,490,'Open()},HandleClose',163,'if(',178,'.openI==null){',213,222,'");',778,'a=',490,'Get(',178,720,'(!a||a.left==null){',490,'Close()}else{',213,222,' or missing',408,725,'");return}},HandleLeft',146,176,'b',642,'a);',267,'}',490,'Open(b)},HandleRight',146,525,'c',642,'b);',267,503,'=',490,'Get(',178,720,'(a&&a.left',561,490,'Close(c)}else{',213,'Extra open brace or missing',408,'+"left")}},HandleOver',146,558,'if(',178,731,561,213,'Ambiguous use of',408,409,'return}',178,731,'=',490,'Length();',178,'.overF={name:a};if(b.length>0){',178,'.overF.','left=',326,'b[0]];',178,1228,'right=',326,'b[1]]}',245,'a.match(/withdelims$/)){',178,1228,'left',642,'a);',267,'}',178,1228,'right',642,'a);',267,'}}else{',178,1228,'left=null;',178,1228,1234,'null}}if(a.match(/^above/)){',178,1228,'thickness',512,'a,1);',267,1252,178,1228,'thickness=null}},HandleSuperscript',196,'a=',490,192,178,731,'==',490,'Length()){a=null}if(a==null||(!a.atom&&a',493,'a',495,'a=',497,498,'if(a.sup){if(a.sup.isPrime){a=',497,498,'else{',213,'Double exponent',502,'}}a.sup',516,'("superscript");',267,'}},HandleSubscript',196,'a=',490,192,178,731,'==',490,'Length()){a=null}if(a==null||(!a.atom&&a',493,'a',495,'a=',497,498,'if(a.sub){',213,'Double subscripts',502,'}a.sub',516,'("subscript");',267,'}},Parse',196,'b;',238,'b=',165,241,'this.mathchar[',1141,'mathchar[b])}',245,'this',149,'b]){this[this',149,'b]](b)}else{',208,'letter','.test(b)){this.',1083,'(b)}else{',208,'number',1338,1089,1340,'this.',1095,'(b)}}}}}if(',178,'.openI!=null',264,490,'Get(',178,720,'(a.left){',213,214,408,725,726,213,257,'")}}if(',178,731,561,490,'Over()}},Atomize',196,'a=',490,'init;if(!this.error){',490,738,'a.style,a.size)}},Typeset',196,'f=',490,'init;var ',606,'typeset=',490,669,'f.style,f',892,267,'\'\'+this.error',916,'if(d.format=="null"){return""}d.Styled().Remeasured();var e=0;var c=0;if(d.bh>d.h&&','d.bh>jsMath.h+0.001){','e=1}if(d.bd>d.d&&d.bd>jsMath.d+0.001){e=1}if(d.h>jsMath.h||d.d>jsMath.d){c=1}var b=d.html;if(e){if(','jsMath.Browser.','allowAbsolute){var g=0;if(',1391,'g=jsMath.h-d.bh}b=',910,'Absolute(b,d.w,jsMath.h,0,g)}',245,1393,'valignBug){','b=\'\'+b',916,159,1393,'operaLineHeightBug',264,910,'Em(Math.max(0,d.bd-jsMath.hd)/3);',1402,')+"; position:relative; top:"+a+"; vertical-align:"+a+\'">\'+b+""}}}c=1}if(c){b+=',910,'Blank(0,d.h+0.05,d.d+0.05)}return\'\'+b+""}});',148,'.AddSpecial({cmd:"HandleCS",open:"HandleOpen",close:"HandleClose"});','jsMath.Add(jsMath,{','Macro',146,176,'c=',148,1132,';c[a]=["Macro"];for(var b=1;b=0){','c=c.replace(/&','lt;/g,"<");',1570,'gt;/g,">");',1570,'quot;/g,\'"\');',1570,'amp;/g,"&")}',164,'c},',1568,146,1558,'b.nodeValue',561,'if(b.nodeName!=="#comment"){',164,1583,'}',164,1583,'.replace(/^\\[CDATA\\[((.|\\n)*)\\]\\]$/,"$1")}if(',1559,'===0){return" "}var c="";for(var a=0;a<',1559,';a++){c+=this.',1568,'(',1561,'a])}',164,'c},ResetHidden',146,'a){a.innerHTML=\'\'+',1393,'operaHiddenFix;a','.className','="";','jsMath.hidden','=a.firstChild;if(!jsMath.BBoxFor("x").w){','jsMath.hidden=jsMath.hiddenTop','}jsMath.ReInit()},ConvertMath',146,'c,b,',176,606,1556,'(b);this.ResetHidden(b);if(d.match(/^\\s*\\\\nocache([^a-zA-Z])/)){a=true;d=d.replace(/\\s*\\\\nocache/,"")}',606,'Parse(c,d,a);b',1606,'="typeset";b.innerHTML=d},',1518,146,'c){','this.restart','=0;if(!c',1606,'.match(/(^| )math( |$)/)){',778,'a=(c',1606,'.toLowerCase','().match(/(^| )nocache( |$)/)!=null);try{var d=(c.tagName',1632,'()=="div"?"D":"T");this.ConvertMath(d,c,a);c.onclick=jsMath.Click.CheckClick;c.ondblclick=jsMath.Click.CheckDblClick}catch(e){if(c.alt',190,'c.alt;b=b.replace(/&/g,"&").replace(//g,">");c.innerHTML=b;c',1606,'="math";if(a){c',1606,'+=" nocache"}}',1610,'}},','ProcessElements',146,'b){',1496,'blocking=','1;if(b>=','this.element','.length||this.cancel){this.','ProcessComplete','();',208,'cancel){','jsMath.Message.','Set("',174,' Math: Canceled");',1656,'Clear()}',1496,1648,'0;',1496,174,'()}else{var a=',1496,'SaveQueue();','this.ProcessElement(this.element[','b]);if(',1625,'){',1496,1497,'this,"',1644,'",b);',1496,'RestoreQueue(a);',1496,1648,'0;setTimeout("',1496,174,'()",',1393,'delay)}else{',1496,1680,'b++;var c=Math.floor(100*b/',1650,449,'jsMath.Message.Set("Processing Math',': "+c+"%");setTimeout("',559,'.',1644,'("+b+")",',1393,'delay)}}},',1500,146,'a','){if(!jsMath.initialized){jsMath.Init()}this.element','=this.GetMathElements(','a);',1496,1648,'1;this.cancel=0;this',568,'=1;',1694,': 0%",1);setTimeout("',559,'.',1644,'(0)",',1393,'delay)},',1512,146,1017,'a==null',1705,1706,'b);a=0}this',568,'=0;while(a<',1650,211,1670,'a]);if(',1625,'){','jsMath.Synchronize','("',559,'.',1512,'(null,"+a+")");',1496,174,'();return}a++}this.',1652,'(1)},ProcessOne',146,'a',1705,'=[a];this.',1512,'(null,0)},GetMathElements',146,'d){var b=[];var a;',212,'d=','jsMath.document','}if(typeof(d',844,'d=',1757,'.getElementById(d)}if(!','d.getElementsByTagName','){',184,656,1763,'("div','");for(a=0;a=0;a--){b[a].removeAttribute("name")}}',1610,';',1650,'=[];',1625,'=null;if(!c){',1694,': Done");',1656,'Clear()}',1656,'UnBlank();if(',1393,'safariImgBug&&(',1508,'font=="symbol"||',1508,'font=="image")){',208,'timeout){clearTimeout(this.timeout)}this.timeout=setTimeout("','jsMath.window.resizeBy','(-1,0); ',1825,'(1,0); ',559,'.timeout = null",2000)}},Cancel',163,559,'.cancel=1;if(',1496,'cancelTimer){',1496,'cancelLoad()}}};',1417,'ConvertTeX',146,'a){',1496,'Push(jsMath.tex2math,"',1839,1501,'ConvertTeX2',146,'a){',1496,1843,1846,1501,'ConvertLaTeX',146,'a){',1496,1843,1853,1501,'ConvertCustom',146,'a){',1496,1843,1860,1501,'CustomSearch',146,'c,b,a,d){',1496,1497,'null,function(){jsMath.tex2math.',1867,'(c,b,a,d)})},tex2math:{',1839,485,1846,485,1853,485,1860,485,1867,':function(){}}});',1736,'=',1496,'Synchronize;try{if(','window.parent','!=window&&window.jsMathAutoload){',1889,'.jsMath=jsMath;',1757,'=',1889,'.document;jsMath.window=',1889,'}}catch(err){}',1533,'Register();jsMath.Loaded();jsMath.Controls.GetCookie();',553,'Source();',1533,'Init();',1496,'Init();',553,'Fonts();if(',1757,'.body){',553,'Body()}',553,'User("onload")}};'] + +]); +//end = new Date().getTime(); +//alert(end-start); diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/local/macros.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/local/macros.js new file mode 100644 index 0000000..974fba9 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/local/macros.js @@ -0,0 +1,17 @@ +/* + * local/macros.js + * + * Use jsMath.Macro() to declare your own local macro definitions here, + * and add "local/macros.js" to the loadFiles array in easy/load.js so + * that they will be loaded automatically when jsMath is used. + * + * See http://www.math.union.edu/locate/jsMath/authors/macros.html + * for details on defining macros for jsMath. + */ + +// +// Examples: +// +// jsMath.Macro('R','{\\bf R}'); +// jsMath.Macro('red','\\color{red}{#1}',1); +// diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/plugins/CHMmode.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/plugins/CHMmode.js new file mode 100644 index 0000000..1bab915 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/plugins/CHMmode.js @@ -0,0 +1,85 @@ +/* + * CHMmode.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file makes jsMath work with MicroSoft's HTML Help system + * from within .chm files (compiled help archives). + * + * This file should be loaded BEFORE jsMath.js. + * + * --------------------------------------------------------------------- + * + * Copyright 2006-2007 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +if (!window.jsMath) {window.jsMath = {}} +if (!jsMath.Controls) {jsMath.Controls = {}} +if (!jsMath.Controls.cookie) {jsMath.Controls.cookie = {}} + +jsMath.isCHMmode = 1; + +jsMath.noChangeGlobal = 1; +jsMath.noShowGlobal = 1; +jsMath.noImgFonts = 1; +jsMath.Controls.cookie.global = 'always'; +jsMath.Controls.cookie.hiddenGlobal = 1; + +if (window.location.protocol == "mk:") { + + /* + * Work around bug in hh.exe that causes it to run at 100% CPU + * and not exit if the page is reloaded after an IFRAME is used + * to load the controls file, so fake it using XMLHttpRequest. + * Load the data into a DIV instead of an IFRAME, and make sure + * that the styles are correct for it. Change the GetPanel() + * call to hide the other panel and open the correct one. + */ + + jsMath.Controls.Init = function () { + this.controlPanels = jsMath.Setup.DIV("controlPanels"); + if (!jsMath.Browser.msieButtonBug) {this.Button()} + else {setTimeout("jsMath.Controls.Button()",500)} + } + + jsMath.Controls.Panel = function () { + jsMath.Translate.Cancel(); + jsMath.Setup.AddStyleSheet({ + '#jsMath_options': jsMath.styles['#jsMath_panel'], + '#jsMath_options .disabled': jsMath.styles['#jsMath_panel .disabled'], + '#jsMath_options .infoLink': jsMath.styles['#jsMath_panel .infoLink'] + }); + if (this.loaded) {this.panel = jsMath.Element("panel"); this.Main(); return} + var html = jsMath.Script.xmlRequest(jsMath.root+"jsMath-controls.html"); + var body = (html.match(/([\s\S]*)<\/body>/))[1]; + this.controlPanels.innerHTML = body; + var script = (body.match(/ + + + +
+ +

jsMath Image Mode Test Page

+ +If you see typeset mathematics below, then jsMath Image Mode is working. If you see +TeX code instead, jsMath Image Mode is not working for you. +

+ +


+ + +
+\left(\, \sum_{k=1}^n a_k b_k \right)^2 \le +\left(\, \sum_{k=1}^n a_k^2 \right) \left(\, \sum_{k=1}^n b_k^2 \right) +
+

+ +

+\warning{       jsMath image mode is not working!       } +
+ + +
+

+If the mathematics does not show up properly, you may not have not +installed the jsMath +image fonts file correctly. Follow the instructions on the linked +page. +

+ +Once you have jsMath working, go on to the sample +page to see if easy/load.js is configured properly. + +

+ + + + + + +

+


+ + + +
+ + + + + + +
[HOME]jsMath web pages
+Created: 14 Feb 2007
+ +Last modified: Jun 16, 2007 8:56:17 AM + +
+Comments to: dpvc@union.edu
+
 
+
+ + + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/test/index.html b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/test/index.html new file mode 100644 index 0000000..559d9e4 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/test/index.html @@ -0,0 +1,114 @@ + + +jsMath (Test): jsMath Test Page + + + + + + + + +
+ + +
jsMath (Test)
+
+

+ + + + + + + +

+Warning: jsMath +requires JavaScript to process the mathematics on this page.
+If your browser supports JavaScript, be sure it is enabled. +
+
+ + +
+ +
+ +
+ +

jsMath Test Page

+ +If you see typeset mathematics below, then jsMath is working. If you see +TeX code instead, jsMath is not working for you. +

+ +


+ + +
+\left(\, \sum_{k=1}^n a_k b_k \right)^2 \le +\left(\, \sum_{k=1}^n a_k^2 \right) \left(\, \sum_{k=1}^n b_k^2 \right) +
+

+ +

+\warning{       jsMath is not working!       } +
+ + +
+

+ +Once you have jsMath working properly, view the image mode test page to make sure that the +image fallback mode is working as well. + +

+ + + + + + +

+


+ + + +
+ + + + + + +
[HOME]jsMath web pages
+Created: 14 Feb 2007
+ +Last modified: Feb 12, 2009 6:14:47 PM + +
+Comments to: dpvc@union.edu
+
 
+
+ + + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/test/jsMath40.jpg b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/test/jsMath40.jpg new file mode 100644 index 0000000..db53794 Binary files /dev/null and b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/test/jsMath40.jpg differ diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/test/sample.html b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/test/sample.html new file mode 100644 index 0000000..4497e7a --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/test/sample.html @@ -0,0 +1,165 @@ + + +jsMath (Test): jsMath Sample Page + + + + + + + + + +
+ +

jsMath Sample Page

+ +This is a sample file showing you how to use jsMath to display mathematics +in your web pages. Be sure you have followed the installation +instructions before loading this file. Also, you may need to edit the +jsMath/easy/load.js file to set the root URL for where jsMath +can be found on your web site. The rest of this document gives examples of +how to enter mathematics in your pages. Depending on the settings in +jsMath/easy/load.js, not all of the mathematics below will be +processed by jsMath. Experiment with the settings in that file to see how +they work. +

+ +


+

+ +

Some mathematics using tex2math

+ +The easiest way to enter mathematics is to use jsMath's tex2math +plugin to identify the mathematics in your document by looking for \rm\TeX-like math delimiters. Here are some math +equations using those markers. Some inline math: $\sqrt{1-x^2}$ or \(ax^2+bx+c\), +and some displayed math: +$$\int {1\over x}\,dx = \ln(x)+C$$ +and +\[\sum_{i=1}^n i = {n(n+1)\over 2}.\] +Note that the first of these will not be processed unless you have enabled +processSingleDollars in jsMath/easy/load.js, +which is disabled by default. That is because a single dollar sign can +appear in normal text (as in "That will cost from $3.50 to +$5.00 to repair"), and you don't want jsMath to try to typeset +the "3.50 to " as mathematics. +

+ +If you enable processSingleDollars, you might also want to +enable fixEscapedDollars, so that it is possible to enter +dollar signs by preceding them with a backslash. Here's one that you can +use to see the results of these settings: \$ (an escaped dollar) and $x+1$ +(not escaped). +

+ +It is also possible to use your own custom delimiters for marking the +mathematics within your pages. If you uncomment the customDelimiters +array in jsMath/easy/load.js, then the following math will be +typeset by jsMath: some inline math [math]\sin(2\pi x)[/math] and some +display math [display]x={-b\pm \sqrt{b^2-4ac}\over 2a}.[/display] +You may change the delimiters to nearly anything you want, but they can not +look like HTML tags, since some browsers will eliminate unknown tags, and +jsMath doesn't get to look for the custom delimiters until after the +browser has interpreted the page. +

+ +

+You can prevent the tex2math plugin from processing a portion +of a page by enclosing it in a tag that is of +CLASS="tex2math_ignore". Often, that tag will be a +DIV or SPAN, but it can be anything. This +paragraph is wrapped in a DIV tag with +CLASS="tex2math_ignore", and so no math delimiters will be +processed: $f\colon X\to Y$, \(x^2 \gt 5\), $$1\over 1+x^2$$ and +\[\matrix{a& b\cr c& d}.\] +Note that this includes the processing of escaped dollars (\$) and +custom delimiters ([math]a \mapsto a^2[/math]) as well. +This makes it possible to produce examples of how to enter mathematics on +your site, for instance. +
+

+JsMath will automatically ignore the text within +PRE tags, so you can easily enter examples that way as well: +

+   $f\colon X\to Y$, \(x^2 \gt 5\),
+   $$1\over 1+x^2$$ and \[\matrix{a& b\cr c& d}.\]
+
+

+ +Note that since the < and > symbols are used to denote HTML tags, +these can be hard to incorporate into your \rm\TeX +code. Often, putting spaces around the < or > will make it work, but +it is probably better to use \lt and \gt instead. +Also note that the tex2math plugin does not allow any HTML +tags to be within the math delimiters, with the exception of +<BR>, which is ignored. +

+ +See the tex2math +documentation for more information. +

+ +


+

+ +

Mathematics without tex2math

+

+ +If you are not using tex2math, then you will need to enclose +your mathematics within SPAN or DIV tags that +are of CLASS="math". Use a SPAN for in-line math +and a DIV for displayed math. For instance, P = (x_1,\ldots,x_n) and +

+ A = \left\lgroup\matrix{a_{11}& \cdots& a_{1m}\cr + \vdots& \ddots& \vdots\cr + a_{n1}& \cdots& a_{nm}\cr}\right\rgroup. +
+

+


+

+

More information

+

+ +See the jsMath +example files for more examples of using jsMath. There are several extensions +to \rm\TeX that allow jsMath to interact better +with HTML. These provide features such as colored text, tagging mathematics +with CSS styles, and so on. +

+ +More information is available from the jsMath author's +documentation site. JsMath also has a home page at +SourceForge, and that includes public forums +for jsMath where you can ask the jsMath user community for help. +

+ + + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/def.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/def.js new file mode 100644 index 0000000..0b5b6a1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/def.js @@ -0,0 +1,1442 @@ +jsMath.Img.AddFont(50,{ + cmr10: [ + [5,5,0], [6,6,0], [6,6,1], [5,6,0], [5,5,0], [6,5,0], [5,5,0], [6,5,0], + [5,5,0], [6,5,0], [5,5,0], [5,5,0], [4,5,0], [4,5,0], [6,5,0], [6,5,0], + [2,4,0], [3,6,2], [3,2,-3], [3,2,-3], [3,2,-3], [3,2,-3], [4,2,-3], [4,3,-3], + [3,3,2], [4,6,1], [5,5,1], [6,5,1], [4,5,1], [7,5,0], [7,6,1], [6,7,1], + [2,2,-1], [2,6,0], [3,3,-2], [6,7,2], [4,7,1], [6,7,1], [6,7,1], [2,3,-2], + [3,8,2], [3,8,2], [4,4,-2], [6,6,1], [2,3,2], [2,1,-1], [2,1,0], [4,8,2], + [4,6,1], [3,5,0], [4,5,0], [4,6,1], [4,5,0], [4,6,1], [4,6,1], [4,6,1], + [4,6,1], [4,6,1], [2,4,0], [2,6,2], [2,6,2], [6,3,0], [3,6,2], [3,5,0], + [6,6,1], [6,6,0], [5,5,0], [5,6,1], [5,5,0], [5,5,0], [5,5,0], [6,6,1], + [6,5,0], [3,5,0], [4,6,1], [6,5,0], [5,5,0], [7,5,0], [6,5,0], [6,6,1], + [5,5,0], [6,7,2], [6,6,1], [4,6,1], [5,5,0], [6,6,1], [6,6,1], [8,6,1], + [6,5,0], [6,5,0], [4,5,0], [2,8,2], [4,3,-2], [2,8,2], [3,2,-3], [2,2,-3], + [2,3,-2], [4,5,1], [4,6,1], [3,5,1], [4,6,1], [3,5,1], [3,5,0], [4,6,2], + [4,5,0], [2,5,0], [3,7,2], [4,5,0], [2,5,0], [6,4,0], [4,4,0], [4,5,1], + [4,6,2], [4,6,2], [3,4,0], [3,5,1], [3,6,1], [4,5,1], [4,5,1], [5,5,1], + [4,4,0], [4,6,2], [3,4,0], [4,1,-1], [7,1,-1], [3,2,-3], [3,1,-4], [3,2,-3] + ], + cmmi10: [ + [6,5,0], [6,6,0], [6,6,1], [5,6,0], [6,5,0], [7,5,0], [6,5,0], [5,5,0], + [5,5,0], [5,5,0], [6,5,0], [5,5,1], [5,7,2], [4,6,2], [4,6,1], [3,5,1], + [4,7,2], [4,6,2], [4,6,1], [3,5,1], [4,5,1], [4,6,1], [4,6,2], [4,4,0], + [4,7,2], [4,5,1], [4,6,2], [4,5,1], [4,5,1], [4,5,1], [5,7,2], [5,6,2], + [5,7,2], [5,5,1], [3,5,1], [4,6,1], [6,5,1], [4,6,2], [3,5,1], [5,6,2], + [7,3,-1], [7,3,1], [7,3,-1], [7,3,1], [2,3,-1], [2,3,-1], [4,5,1], [4,5,1], + [4,5,1], [3,4,0], [4,4,0], [4,6,2], [4,6,2], [4,6,2], [4,6,1], [4,6,2], + [4,6,1], [4,6,2], [2,1,0], [2,3,2], [5,5,1], [4,8,2], [5,5,1], [4,4,0], + [4,7,1], [6,6,0], [6,5,0], [6,6,1], [6,5,0], [6,5,0], [6,5,0], [6,6,1], + [7,5,0], [4,5,0], [5,6,1], [7,5,0], [5,5,0], [8,5,0], [7,5,0], [6,6,1], + [6,5,0], [6,7,2], [6,6,1], [5,6,1], [5,5,0], [6,6,1], [6,6,1], [8,6,1], + [6,5,0], [6,5,0], [6,5,0], [3,7,1], [3,8,2], [3,8,2], [7,3,0], [7,3,0], + [3,6,1], [4,5,1], [3,6,1], [4,5,1], [4,6,1], [4,5,1], [4,7,2], [4,6,2], + [4,6,1], [3,6,1], [4,7,2], [4,6,1], [2,6,1], [6,5,1], [4,5,1], [4,5,1], + [5,6,2], [4,6,2], [4,5,1], [3,5,1], [3,6,1], [4,5,1], [4,5,1], [5,5,1], + [4,5,1], [4,6,2], [4,5,1], [3,5,1], [4,6,2], [5,6,2], [5,2,-3], [5,2,-3] + ], + cmsy10: [ + [5,1,-1], [2,2,-1], [5,4,0], [4,4,0], [6,5,1], [4,4,0], [6,5,0], [6,6,2], + [6,6,1], [6,6,1], [6,6,1], [6,6,1], [6,6,1], [7,8,2], [4,4,0], [4,4,0], + [6,4,0], [6,4,0], [5,6,1], [5,6,1], [5,6,1], [5,6,1], [5,6,1], [5,6,1], + [6,3,0], [6,4,0], [5,5,1], [5,5,1], [7,5,1], [7,5,1], [5,5,1], [5,5,1], + [7,3,0], [7,3,0], [3,7,2], [3,7,2], [7,3,0], [7,7,2], [7,7,2], [6,4,0], + [7,5,1], [7,5,1], [5,7,2], [5,7,2], [7,5,1], [7,7,2], [7,7,2], [6,5,1], + [2,4,0], [7,5,1], [5,5,1], [5,5,1], [6,6,0], [6,6,2], [5,8,2], [1,4,0], + [4,6,1], [4,5,0], [5,3,0], [4,7,1], [5,7,1], [5,6,1], [6,5,0], [6,5,0], + [4,5,0], [6,7,1], [5,6,1], [4,6,1], [6,5,0], [4,6,1], [6,6,1], [5,6,1], + [6,6,1], [6,5,0], [6,6,1], [6,6,1], [5,6,1], [8,6,1], [8,7,1], [6,6,1], + [6,6,1], [6,6,1], [6,6,1], [5,6,1], [6,6,0], [6,6,1], [5,6,1], [8,6,1], + [6,5,0], [6,6,1], [6,5,0], [5,6,1], [5,6,1], [5,6,1], [5,6,1], [5,6,1], + [4,5,0], [4,5,0], [3,8,2], [2,8,2], [3,8,2], [2,8,2], [3,8,2], [3,8,2], + [3,8,2], [2,8,2], [2,8,2], [3,8,2], [3,8,2], [5,8,2], [4,8,2], [2,6,1], + [6,8,7], [5,5,0], [6,6,1], [4,8,2], [5,5,0], [5,5,0], [5,6,1], [5,6,1], + [3,7,2], [3,7,2], [3,7,2], [5,7,2], [6,7,1], [6,8,2], [6,7,1], [6,7,1] + ], + cmex10: [ + [3,10,9], [3,10,9], [3,10,9], [2,10,9], [4,10,9], [2,10,9], [4,10,9], [2,10,9], + [4,10,9], [4,10,9], [3,10,9], [3,10,9], [2,6,5], [3,6,5], [4,10,9], [4,10,9], + [4,14,13], [3,14,13], [5,18,17], [4,18,17], [4,18,17], [2,18,17], [4,18,17], [3,18,17], + [4,18,17], [3,18,17], [5,18,17], [5,18,17], [5,18,17], [5,18,17], [7,18,17], [7,18,17], + [6,22,21], [4,22,21], [4,22,21], [3,22,21], [5,22,21], [3,22,21], [5,22,21], [3,22,21], + [5,22,21], [5,22,21], [5,22,21], [5,22,21], [9,22,21], [9,22,21], [6,14,13], [6,14,13], + [6,14,13], [5,14,13], [5,14,13], [3,14,13], [5,14,13], [3,14,13], [3,6,5], [3,6,5], + [6,8,7], [4,8,7], [6,8,7], [4,8,7], [4,14,13], [6,14,13], [4,4,3], [3,6,5], + [6,14,13], [5,14,13], [3,6,5], [5,6,5], [4,14,13], [4,14,13], [6,8,7], [8,11,10], + [5,9,8], [7,17,16], [8,8,7], [11,11,10], [8,8,7], [11,11,10], [8,8,7], [11,11,10], + [7,8,7], [7,8,7], [5,9,8], [6,8,7], [6,8,7], [6,8,7], [6,8,7], [6,8,7], + [10,11,10], [9,11,10], [7,17,16], [8,11,10], [8,11,10], [8,11,10], [8,11,10], [8,11,10], + [7,8,7], [9,11,10], [5,3,-3], [9,2,-4], [12,2,-4], [4,2,-4], [7,2,-4], [11,2,-4], + [4,14,13], [2,14,13], [4,14,13], [3,14,13], [4,14,13], [3,14,13], [4,14,13], [4,14,13], + [8,10,9], [8,14,13], [8,18,17], [8,22,21], [6,14,13], [6,6,5], [8,6,5], [4,6,5], + [4,6,5], [4,6,5], [5,3,2], [5,3,2], [5,3,0], [5,3,0], [6,6,5], [6,6,5] + ], + cmbx10: [ + [5,5,0], [7,5,0], [6,6,1], [6,5,0], [6,5,0], [7,5,0], [6,5,0], [6,5,0], + [6,5,0], [6,5,0], [6,5,0], [6,5,0], [5,5,0], [5,5,0], [7,5,0], [7,5,0], + [2,4,0], [3,6,2], [3,2,-3], [4,2,-3], [4,2,-3], [4,2,-3], [4,2,-3], [4,2,-3], + [4,3,2], [4,6,1], [6,5,1], [7,5,1], [4,5,1], [8,5,0], [8,6,1], [6,7,1], + [3,2,-1], [2,5,0], [4,3,-2], [7,7,2], [4,7,1], [7,7,1], [6,6,1], [2,3,-2], + [3,8,2], [3,8,2], [4,4,-2], [6,6,1], [2,4,2], [3,1,-1], [2,2,0], [4,8,2], + [4,6,1], [4,5,0], [4,5,0], [4,6,1], [4,5,0], [4,6,1], [4,6,1], [4,6,1], + [4,6,1], [4,6,1], [2,4,0], [2,6,2], [2,6,2], [6,3,0], [4,6,2], [4,5,0], + [6,6,1], [6,5,0], [6,5,0], [6,6,1], [6,5,0], [6,5,0], [5,5,0], [6,6,1], + [7,5,0], [3,5,0], [4,6,1], [6,5,0], [5,5,0], [8,5,0], [7,5,0], [6,6,1], + [6,5,0], [6,7,2], [6,6,1], [5,6,1], [6,5,0], [6,6,1], [6,6,1], [9,6,1], + [6,5,0], [6,5,0], [5,5,0], [3,8,2], [4,3,-2], [2,8,2], [4,2,-3], [2,2,-3], + [2,3,-2], [4,5,1], [5,6,1], [4,5,1], [5,6,1], [4,5,1], [4,5,0], [4,6,2], + [5,5,0], [2,5,0], [3,7,2], [5,5,0], [3,5,0], [7,4,0], [5,4,0], [4,5,1], + [5,6,2], [5,6,2], [4,4,0], [3,5,1], [3,6,1], [5,5,1], [5,5,1], [6,5,1], + [5,4,0], [5,6,2], [4,4,0], [5,2,-1], [9,2,-1], [4,2,-3], [4,1,-4], [4,2,-3] + ], + cmti10: [ + [5,5,0], [6,6,0], [6,6,1], [5,6,0], [6,5,0], [6,5,0], [6,5,0], [6,5,0], + [6,5,0], [6,5,0], [6,5,0], [7,7,2], [6,7,2], [6,7,2], [8,7,2], [8,7,2], + [3,5,1], [4,6,2], [4,2,-3], [4,2,-3], [4,2,-3], [4,2,-3], [4,2,-3], [5,3,-3], + [3,3,2], [6,7,2], [6,5,1], [6,5,1], [4,5,1], [7,5,0], [8,6,1], [6,7,1], + [3,2,-1], [3,6,0], [4,3,-2], [6,7,2], [5,6,1], [6,7,1], [6,7,1], [3,3,-2], + [4,8,2], [3,8,2], [5,4,-2], [6,5,1], [2,3,2], [3,1,-1], [2,1,0], [5,8,2], + [4,6,1], [4,5,0], [4,6,1], [4,6,1], [4,7,2], [4,6,1], [4,6,1], [5,6,1], + [4,6,1], [4,6,1], [3,4,0], [3,6,2], [3,6,2], [6,3,0], [4,6,2], [4,6,0], + [6,6,1], [5,6,0], [6,5,0], [6,6,1], [6,5,0], [6,5,0], [6,5,0], [6,6,1], + [6,5,0], [4,5,0], [5,6,1], [7,5,0], [5,5,0], [8,5,0], [6,5,0], [6,6,1], + [6,5,0], [6,7,2], [6,6,1], [5,6,1], [6,5,0], [6,6,1], [7,6,1], [8,6,1], + [6,5,0], [7,5,0], [5,5,0], [4,8,2], [5,3,-2], [4,8,2], [4,2,-3], [3,2,-3], + [3,3,-2], [4,5,1], [4,6,1], [4,5,1], [4,6,1], [4,5,1], [5,7,2], [4,6,2], + [4,6,1], [3,6,1], [4,7,2], [4,6,1], [3,6,1], [6,5,1], [5,5,1], [4,5,1], + [4,6,2], [4,6,2], [4,5,1], [3,5,1], [3,6,1], [4,5,1], [4,5,1], [5,5,1], + [4,5,1], [4,6,2], [4,5,1], [4,1,-1], [8,1,-1], [5,2,-3], [4,2,-3], [4,2,-3] + ] +}); + +jsMath.Img.AddFont(60,{ + cmr10: [ + [5,6,0], [7,6,0], [6,7,1], [6,6,0], [5,6,0], [6,6,0], [6,6,0], [6,6,0], + [6,6,0], [6,6,0], [6,6,0], [6,6,0], [5,6,0], [5,6,0], [7,6,0], [7,6,0], + [2,4,0], [3,6,2], [3,2,-4], [4,2,-4], [4,2,-4], [4,2,-4], [4,1,-4], [4,2,-4], + [3,3,2], [4,7,1], [6,5,1], [6,5,1], [4,6,1], [7,6,0], [8,7,1], [6,7,1], + [3,2,-2], [2,6,0], [3,3,-3], [7,8,2], [4,7,1], [7,7,1], [6,7,1], [2,3,-3], + [3,8,2], [3,8,2], [4,4,-2], [6,6,1], [2,3,2], [3,1,-1], [2,1,0], [4,8,2], + [4,7,1], [4,6,0], [4,6,0], [4,7,1], [4,6,0], [4,7,1], [4,7,1], [4,7,1], + [4,7,1], [4,7,1], [2,4,0], [2,6,2], [2,6,2], [6,2,-1], [4,6,2], [4,6,0], + [6,7,1], [6,6,0], [6,6,0], [6,7,1], [6,6,0], [6,6,0], [5,6,0], [6,7,1], + [6,6,0], [3,6,0], [4,7,1], [6,6,0], [5,6,0], [8,6,0], [6,6,0], [6,7,1], + [5,6,0], [6,8,2], [6,7,1], [4,7,1], [6,6,0], [6,7,1], [6,7,1], [9,7,1], + [6,6,0], [6,6,0], [5,6,0], [3,8,2], [4,3,-3], [2,8,2], [4,2,-4], [2,2,-4], + [2,3,-3], [4,5,1], [5,7,1], [4,5,1], [5,7,1], [4,5,1], [3,6,0], [4,6,2], + [5,6,0], [2,6,0], [3,8,2], [5,6,0], [3,6,0], [7,4,0], [5,4,0], [4,5,1], + [5,6,2], [5,6,2], [3,4,0], [3,5,1], [3,6,1], [5,5,1], [5,5,1], [6,5,1], + [5,4,0], [5,6,2], [4,4,0], [4,1,-2], [8,1,-2], [4,2,-4], [4,2,-4], [4,2,-4] + ], + cmmi10: [ + [6,6,0], [7,6,0], [6,7,1], [6,6,0], [7,6,0], [8,6,0], [7,6,0], [6,6,0], + [6,6,0], [6,6,0], [7,6,0], [5,5,1], [5,8,2], [5,6,2], [4,7,1], [4,5,1], + [4,8,2], [4,6,2], [4,7,1], [3,5,1], [5,5,1], [5,7,1], [5,6,2], [5,4,0], + [4,8,2], [5,5,1], [5,6,2], [5,5,1], [5,5,1], [5,5,1], [5,8,2], [5,6,2], + [6,8,2], [5,5,1], [4,5,1], [5,7,1], [7,5,1], [5,6,2], [4,5,1], [5,6,2], + [8,4,-1], [8,4,1], [8,4,-1], [8,4,1], [2,3,-1], [2,3,-1], [4,6,1], [4,6,1], + [4,5,1], [4,4,0], [4,4,0], [4,6,2], [4,6,2], [4,6,2], [4,7,1], [4,6,2], + [4,7,1], [4,6,2], [2,1,0], [2,3,2], [6,6,1], [4,8,2], [6,6,1], [4,4,0], + [5,7,1], [6,6,0], [7,6,0], [7,7,1], [7,6,0], [7,6,0], [7,6,0], [7,7,1], + [8,6,0], [4,6,0], [6,7,1], [8,6,0], [6,6,0], [9,6,0], [8,6,0], [6,7,1], + [7,6,0], [6,8,2], [7,7,1], [6,7,1], [6,6,0], [7,7,1], [7,7,1], [9,7,1], + [7,6,0], [7,6,0], [6,6,0], [3,7,1], [3,8,2], [3,8,2], [8,2,-1], [8,3,-1], + [4,7,1], [4,5,1], [4,7,1], [4,5,1], [5,7,1], [4,5,1], [5,8,2], [4,6,2], + [5,7,1], [3,7,1], [5,8,2], [5,7,1], [3,7,1], [7,5,1], [5,5,1], [4,5,1], + [5,6,2], [4,6,2], [4,5,1], [4,5,1], [3,7,1], [5,5,1], [4,5,1], [6,5,1], + [5,5,1], [4,6,2], [4,5,1], [3,5,1], [4,6,2], [5,6,2], [5,2,-4], [6,2,-4] + ], + cmsy10: [ + [6,2,-1], [2,2,-1], [6,4,0], [4,4,0], [6,6,1], [4,4,0], [6,6,0], [6,6,2], + [6,6,1], [6,6,1], [6,6,1], [6,6,1], [6,6,1], [8,8,2], [4,4,0], [4,4,0], + [6,4,0], [6,4,0], [6,8,2], [6,8,2], [6,8,2], [6,8,2], [6,8,2], [6,8,2], + [6,2,-1], [6,4,0], [6,6,1], [6,6,1], [8,6,1], [8,6,1], [6,6,1], [6,6,1], + [8,4,0], [8,4,0], [4,8,2], [4,8,2], [8,4,0], [8,8,2], [8,8,2], [6,4,0], + [8,6,1], [8,6,1], [5,8,2], [5,8,2], [8,6,1], [8,8,2], [8,8,2], [6,5,1], + [3,5,0], [8,5,1], [5,6,1], [5,6,1], [7,6,0], [7,6,2], [6,8,2], [1,4,0], + [5,7,1], [4,6,0], [5,3,0], [4,8,1], [6,7,1], [6,7,1], [6,6,0], [6,6,0], + [5,6,0], [7,7,1], [6,7,1], [5,7,1], [7,6,0], [5,7,1], [7,7,1], [5,7,1], + [7,7,1], [7,6,0], [7,7,1], [6,7,1], [6,7,1], [9,7,1], [9,8,1], [7,7,1], + [6,7,1], [7,7,1], [7,7,1], [6,7,1], [7,6,0], [7,7,1], [6,7,1], [9,7,1], + [7,6,0], [6,8,2], [7,6,0], [5,6,1], [5,6,1], [5,6,1], [5,6,1], [5,6,1], + [5,6,0], [5,6,0], [4,8,2], [3,8,2], [4,8,2], [3,8,2], [4,8,2], [4,8,2], + [3,8,2], [3,8,2], [2,8,2], [3,8,2], [4,10,3], [5,10,3], [4,8,2], [2,6,1], + [7,9,8], [6,6,0], [7,7,1], [4,8,2], [5,5,0], [5,5,0], [6,8,2], [6,8,2], + [3,8,2], [4,8,2], [4,8,2], [5,8,2], [6,8,2], [6,8,2], [6,7,1], [6,8,2] + ], + cmex10: [ + [4,11,10], [3,11,10], [4,11,10], [2,11,10], [4,11,10], [3,11,10], [4,11,10], [3,11,10], + [4,11,10], [4,11,10], [4,11,10], [3,11,10], [2,6,5], [4,6,5], [5,11,10], [5,11,10], + [5,16,15], [4,16,15], [6,20,19], [5,20,19], [5,20,19], [3,20,19], [5,20,19], [3,20,19], + [5,20,19], [3,20,19], [5,20,19], [5,20,19], [6,20,19], [5,20,19], [8,20,19], [8,20,19], + [7,25,24], [5,25,24], [5,25,24], [3,25,24], [6,25,24], [3,25,24], [6,25,24], [3,25,24], + [6,25,24], [6,25,24], [6,25,24], [6,25,24], [10,25,24], [10,25,24], [7,16,15], [7,16,15], + [7,16,15], [5,16,15], [6,16,15], [3,16,15], [6,16,15], [3,16,15], [4,6,5], [3,6,5], + [6,9,8], [5,9,8], [6,9,8], [5,9,8], [5,16,15], [6,16,15], [5,4,3], [3,6,5], + [7,16,15], [5,16,15], [4,6,5], [5,6,5], [5,16,15], [4,16,15], [7,9,8], [9,13,12], + [5,10,9], [8,19,18], [9,9,8], [12,13,12], [9,9,8], [12,13,12], [9,9,8], [12,13,12], + [8,9,8], [8,9,8], [5,10,9], [7,9,8], [7,9,8], [7,9,8], [7,9,8], [7,9,8], + [12,13,12], [10,13,12], [8,19,18], [9,13,12], [9,13,12], [9,13,12], [9,13,12], [9,13,12], + [8,9,8], [10,13,12], [6,2,-4], [10,3,-4], [13,3,-4], [5,2,-4], [8,2,-4], [12,2,-4], + [4,16,15], [2,16,15], [5,16,15], [3,16,15], [5,16,15], [3,16,15], [5,16,15], [5,16,15], + [9,11,10], [9,16,15], [9,20,19], [9,25,24], [6,16,15], [6,6,5], [9,6,5], [5,6,5], + [5,6,5], [5,6,5], [5,3,2], [5,3,2], [5,3,0], [5,3,0], [6,6,5], [6,6,5] + ], + cmbx10: [ + [6,6,0], [8,6,0], [7,7,1], [7,6,0], [6,6,0], [7,6,0], [7,6,0], [7,6,0], + [7,6,0], [7,6,0], [7,6,0], [6,6,0], [5,6,0], [5,6,0], [8,6,0], [8,6,0], + [3,4,0], [4,6,2], [3,2,-4], [4,2,-4], [4,2,-4], [4,2,-4], [4,1,-4], [5,2,-4], + [4,3,2], [5,7,1], [7,5,1], [7,5,1], [5,6,1], [9,6,0], [10,7,1], [7,7,1], + [3,2,-2], [3,6,0], [4,4,-2], [8,8,2], [5,7,1], [8,7,1], [7,7,1], [3,4,-2], + [4,8,2], [3,8,2], [4,4,-2], [7,8,2], [2,4,2], [3,2,-1], [2,2,0], [5,8,2], + [5,7,1], [4,6,0], [5,6,0], [5,7,1], [5,6,0], [5,7,1], [5,7,1], [5,7,1], + [5,7,1], [5,7,1], [2,4,0], [2,6,2], [3,6,2], [7,4,0], [4,6,2], [4,6,0], + [7,7,1], [7,6,0], [7,6,0], [7,7,1], [7,6,0], [6,6,0], [6,6,0], [7,7,1], + [7,6,0], [4,6,0], [5,7,1], [7,6,0], [6,6,0], [9,6,0], [7,6,0], [7,7,1], + [6,6,0], [7,8,2], [7,7,1], [5,7,1], [7,6,0], [7,7,1], [7,7,1], [10,7,1], + [7,6,0], [7,6,0], [6,6,0], [3,8,2], [5,4,-2], [2,8,2], [4,2,-4], [2,2,-4], + [2,4,-2], [5,5,1], [5,7,1], [4,5,1], [5,7,1], [4,5,1], [4,6,0], [5,6,2], + [5,6,0], [3,6,0], [4,8,2], [5,6,0], [3,6,0], [8,4,0], [5,4,0], [5,5,1], + [5,6,2], [5,6,2], [4,4,0], [4,5,1], [4,7,1], [5,5,1], [5,5,1], [7,5,1], + [5,4,0], [5,6,2], [4,4,0], [5,1,-2], [10,1,-2], [4,2,-4], [4,2,-4], [4,2,-4] + ], + cmti10: [ + [6,6,0], [7,6,0], [7,7,1], [6,6,0], [7,6,0], [7,6,0], [7,6,0], [7,6,0], + [6,6,0], [7,6,0], [7,6,0], [8,8,2], [6,8,2], [7,8,2], [9,8,2], [9,8,2], + [3,5,1], [4,6,2], [4,2,-4], [5,2,-4], [5,2,-4], [5,2,-4], [5,1,-4], [6,2,-4], + [3,3,2], [6,8,2], [6,5,1], [6,5,1], [5,6,1], [8,6,0], [9,7,1], [7,7,1], + [3,2,-2], [3,6,0], [5,3,-3], [7,8,2], [6,7,1], [7,7,1], [7,7,1], [3,3,-3], + [5,8,2], [4,8,2], [5,4,-2], [7,6,1], [2,3,2], [3,1,-1], [2,1,0], [5,8,2], + [5,7,1], [4,6,0], [5,7,1], [5,7,1], [4,8,2], [5,7,1], [5,7,1], [5,7,1], + [5,7,1], [5,7,1], [3,4,0], [3,6,2], [3,6,2], [7,2,-1], [4,6,2], [5,6,0], + [7,7,1], [6,6,0], [6,6,0], [7,7,1], [7,6,0], [6,6,0], [6,6,0], [7,7,1], + [7,6,0], [5,6,0], [5,7,1], [7,6,0], [5,6,0], [9,6,0], [7,6,0], [7,7,1], + [6,6,0], [7,8,2], [6,7,1], [6,7,1], [7,6,0], [7,7,1], [7,7,1], [9,7,1], + [7,6,0], [7,6,0], [6,6,0], [4,8,2], [5,3,-3], [4,8,2], [5,2,-4], [3,2,-4], + [3,3,-3], [5,5,1], [4,7,1], [4,5,1], [5,7,1], [4,5,1], [5,8,2], [4,6,2], + [5,7,1], [3,7,1], [4,8,2], [5,7,1], [3,7,1], [7,5,1], [5,5,1], [5,5,1], + [5,6,2], [4,6,2], [4,5,1], [4,5,1], [3,7,1], [5,5,1], [4,5,1], [6,5,1], + [5,5,1], [5,6,2], [4,5,1], [5,1,-2], [9,1,-2], [5,2,-4], [5,2,-4], [5,2,-4] + ] +}); + +jsMath.Img.AddFont(70,{ + cmr10: [ + [6,7,0], [8,8,0], [8,9,1], [7,8,0], [7,7,0], [8,7,0], [7,7,0], [8,8,0], + [7,7,0], [8,7,0], [7,8,0], [7,8,0], [6,8,0], [6,8,0], [9,8,0], [9,8,0], + [3,5,0], [4,8,3], [3,2,-5], [4,2,-5], [4,2,-5], [4,2,-5], [5,1,-5], [5,3,-5], + [4,4,3], [5,9,1], [7,6,1], [8,6,1], [5,8,2], [9,7,0], [10,9,1], [8,9,1], + [3,2,-2], [2,8,0], [4,4,-3], [8,9,2], [5,9,1], [8,9,1], [8,9,1], [3,4,-3], + [4,11,3], [3,11,3], [5,5,-3], [8,7,1], [3,4,2], [3,2,-1], [2,2,0], [5,11,3], + [5,8,1], [5,7,0], [5,7,0], [5,8,1], [5,7,0], [5,8,1], [5,8,1], [5,8,1], + [5,8,1], [5,8,1], [2,5,0], [2,7,2], [2,8,3], [8,3,-1], [5,8,3], [5,8,0], + [8,9,1], [8,8,0], [7,7,0], [7,9,1], [8,7,0], [7,7,0], [7,7,0], [8,9,1], + [8,7,0], [4,7,0], [5,8,1], [8,7,0], [6,7,0], [9,7,0], [8,7,0], [8,9,1], + [7,7,0], [8,10,2], [8,8,1], [5,9,1], [7,7,0], [8,8,1], [8,8,1], [11,8,1], + [8,7,0], [8,7,0], [6,7,0], [3,11,3], [5,4,-3], [2,11,3], [4,2,-5], [2,2,-5], + [2,4,-3], [5,6,1], [6,8,1], [5,6,1], [6,8,1], [5,6,1], [4,8,0], [5,8,3], + [6,7,0], [3,7,0], [4,10,3], [6,7,0], [3,7,0], [9,5,0], [6,5,0], [5,6,1], + [6,7,2], [6,7,2], [4,5,0], [4,6,1], [4,8,1], [6,6,1], [6,6,1], [8,6,1], + [6,5,0], [6,8,3], [5,5,0], [5,1,-2], [10,1,-2], [5,2,-5], [5,2,-5], [4,2,-5] + ], + cmmi10: [ + [8,7,0], [8,8,0], [8,9,1], [7,8,0], [8,7,0], [9,7,0], [9,7,0], [8,8,0], + [7,7,0], [7,7,0], [8,8,0], [7,6,1], [6,10,2], [6,8,3], [5,9,1], [4,6,1], + [5,10,3], [5,8,3], [5,9,1], [4,6,1], [6,6,1], [6,8,1], [6,8,3], [6,5,0], + [5,10,3], [6,6,1], [6,8,3], [6,6,1], [6,6,1], [6,6,1], [6,10,3], [6,8,3], + [7,10,3], [7,6,1], [5,6,1], [6,9,1], [9,6,1], [6,7,2], [5,7,2], [7,8,3], + [10,4,-2], [10,4,1], [10,4,-2], [10,4,1], [3,3,-2], [3,3,-2], [5,7,1], [5,7,1], + [5,6,1], [5,5,0], [5,5,0], [5,8,3], [5,7,2], [5,8,3], [5,8,1], [5,8,3], + [5,8,1], [5,8,3], [2,2,0], [3,4,2], [7,7,1], [5,11,3], [7,7,1], [5,5,0], + [6,9,1], [8,8,0], [8,7,0], [8,9,1], [9,7,0], [8,7,0], [8,7,0], [8,9,1], + [9,7,0], [5,7,0], [7,8,1], [9,7,0], [7,7,0], [11,7,0], [9,7,0], [8,9,1], + [8,7,0], [8,10,2], [8,8,1], [7,9,1], [8,7,0], [8,8,1], [8,8,1], [11,8,1], + [9,7,0], [8,7,0], [8,7,0], [4,9,1], [4,11,3], [4,11,3], [10,3,-1], [10,3,-1], + [4,9,1], [5,6,1], [5,8,1], [5,6,1], [6,8,1], [5,6,1], [6,11,3], [5,8,3], + [6,8,1], [3,8,1], [5,10,3], [6,8,1], [3,8,1], [9,6,1], [6,6,1], [5,6,1], + [6,7,2], [5,7,2], [5,6,1], [5,6,1], [4,8,1], [6,6,1], [5,6,1], [7,6,1], + [6,6,1], [5,8,3], [5,6,1], [3,6,1], [5,8,3], [7,8,3], [7,3,-5], [7,2,-5] + ], + cmsy10: [ + [7,1,-2], [2,3,-1], [7,5,0], [5,5,0], [8,7,1], [5,5,0], [8,7,0], [8,7,2], + [8,7,1], [8,7,1], [8,7,1], [8,7,1], [8,7,1], [10,11,3], [5,5,0], [5,5,0], + [8,5,0], [8,5,0], [7,9,2], [7,9,2], [7,9,2], [7,9,2], [7,9,2], [7,9,2], + [8,3,-1], [8,5,0], [7,7,1], [7,7,1], [10,7,1], [10,7,1], [7,7,1], [7,7,1], + [10,5,0], [10,5,0], [5,9,2], [5,9,2], [10,5,0], [10,9,2], [10,9,2], [8,5,0], + [10,7,1], [10,7,1], [6,9,2], [6,9,2], [10,7,1], [10,9,2], [10,9,2], [8,6,1], + [3,6,0], [10,6,1], [6,7,1], [6,7,1], [9,8,0], [9,8,3], [7,11,3], [2,5,0], + [6,8,1], [5,7,0], [7,4,0], [5,9,1], [8,9,1], [7,9,1], [8,7,0], [8,7,0], + [6,7,0], [8,9,1], [7,9,1], [6,9,1], [8,7,0], [6,9,1], [9,8,1], [7,10,2], + [9,8,1], [8,7,0], [9,9,2], [8,9,1], [7,9,1], [12,9,1], [11,9,1], [8,9,1], + [8,8,1], [8,10,2], [9,8,1], [7,9,1], [8,8,0], [8,8,1], [7,8,1], [11,8,1], + [9,7,0], [8,9,2], [8,7,0], [7,7,1], [7,7,1], [7,7,1], [7,7,1], [7,7,1], + [6,7,0], [6,7,0], [5,11,3], [3,11,3], [5,11,3], [3,11,3], [5,11,3], [5,11,3], + [4,11,3], [3,11,3], [2,11,3], [4,11,3], [5,11,3], [6,11,3], [5,11,3], [3,7,1], + [9,11,10], [8,7,0], [8,8,1], [5,11,3], [7,6,0], [7,6,0], [8,9,2], [7,9,2], + [4,11,3], [4,11,3], [4,11,3], [6,9,2], [8,10,2], [8,10,2], [8,9,1], [8,10,2] + ], + cmex10: [ + [5,13,12], [4,13,12], [4,13,12], [3,13,12], [5,13,12], [3,13,12], [5,13,12], [3,13,12], + [5,13,12], [5,13,12], [4,13,12], [4,13,12], [2,8,7], [5,8,7], [6,13,12], [6,13,12], + [6,19,18], [5,19,18], [7,25,24], [6,25,24], [6,25,24], [3,25,24], [6,25,24], [4,25,24], + [6,25,24], [4,25,24], [7,25,24], [7,25,24], [7,25,24], [7,25,24], [10,25,24], [10,25,24], + [8,31,30], [6,31,30], [6,31,30], [4,31,30], [7,31,30], [4,31,30], [7,31,30], [4,31,30], + [7,31,30], [7,31,30], [7,31,30], [7,31,30], [13,31,30], [13,31,30], [8,19,18], [8,19,18], + [9,19,18], [6,19,18], [7,19,18], [4,19,18], [7,19,18], [4,19,18], [4,8,7], [4,8,7], + [8,11,10], [6,11,10], [8,10,9], [6,10,9], [6,20,19], [8,20,19], [6,5,4], [4,8,7], + [9,19,18], [6,19,18], [5,8,7], [6,8,7], [6,19,18], [5,19,18], [8,11,10], [11,15,14], + [7,13,12], [10,24,23], [11,11,10], [15,15,14], [11,11,10], [15,15,14], [11,11,10], [15,15,14], + [10,11,10], [9,11,10], [7,13,12], [8,11,10], [8,11,10], [8,11,10], [8,11,10], [8,11,10], + [14,15,14], [13,15,14], [10,24,23], [11,15,14], [11,15,14], [11,15,14], [11,15,14], [11,15,14], + [9,11,10], [13,15,14], [7,3,-5], [12,3,-5], [16,3,-5], [6,2,-6], [10,2,-6], [15,2,-6], + [5,19,18], [3,19,18], [6,19,18], [4,19,18], [6,19,18], [4,19,18], [6,19,18], [6,19,18], + [11,13,12], [11,19,18], [11,25,24], [11,31,30], [8,19,18], [8,8,7], [11,7,6], [6,8,7], + [6,7,6], [6,7,6], [6,5,3], [6,5,3], [6,4,0], [6,4,0], [8,7,6], [8,7,6] + ], + cmbx10: [ + [7,7,0], [9,7,0], [9,8,1], [8,7,0], [8,7,0], [9,7,0], [8,7,0], [9,7,0], + [8,7,0], [9,7,0], [8,7,0], [8,7,0], [7,7,0], [7,7,0], [10,7,0], [10,7,0], + [3,5,0], [4,7,2], [4,3,-5], [5,3,-5], [5,2,-5], [5,2,-5], [5,2,-5], [6,3,-5], + [5,3,2], [6,8,1], [8,6,1], [9,6,1], [6,8,2], [11,7,0], [12,8,1], [9,9,1], + [4,3,-2], [3,8,0], [5,4,-3], [9,9,2], [6,9,1], [9,9,1], [9,9,1], [3,4,-3], + [4,11,3], [4,11,3], [5,5,-3], [9,9,2], [3,4,2], [4,2,-1], [3,2,0], [6,11,3], + [6,8,1], [5,7,0], [6,7,0], [6,8,1], [6,7,0], [6,8,1], [6,8,1], [6,8,1], + [6,8,1], [6,8,1], [3,5,0], [3,7,2], [3,8,3], [9,3,-1], [5,7,2], [5,7,0], + [9,8,1], [9,7,0], [8,7,0], [8,8,1], [9,7,0], [8,7,0], [7,7,0], [9,8,1], + [9,7,0], [5,7,0], [6,8,1], [9,7,0], [7,7,0], [11,7,0], [9,7,0], [8,8,1], + [8,7,0], [9,9,2], [9,8,1], [6,8,1], [8,7,0], [9,8,1], [9,8,1], [12,8,1], + [9,7,0], [9,7,0], [7,7,0], [3,11,3], [6,4,-3], [2,11,3], [5,2,-5], [3,2,-5], + [3,4,-3], [6,6,1], [6,8,1], [5,6,1], [7,8,1], [5,6,1], [5,7,0], [6,8,3], + [7,7,0], [3,7,0], [4,9,2], [6,7,0], [3,7,0], [10,5,0], [7,5,0], [6,6,1], + [6,7,2], [7,7,2], [5,5,0], [5,6,1], [4,8,1], [7,6,1], [6,6,1], [9,6,1], + [6,5,0], [6,7,2], [5,5,0], [6,1,-2], [12,1,-2], [5,3,-5], [5,2,-5], [5,2,-5] + ], + cmti10: [ + [8,7,0], [8,8,0], [8,9,1], [7,8,0], [8,7,0], [9,7,0], [8,7,0], [9,8,0], + [8,7,0], [9,7,0], [8,8,0], [9,11,3], [7,11,3], [8,11,3], [11,11,3], [11,11,3], + [4,6,1], [5,8,3], [5,2,-5], [6,2,-5], [6,2,-5], [6,2,-5], [6,1,-5], [7,3,-5], + [4,3,2], [7,11,3], [8,6,1], [8,6,1], [6,8,2], [10,7,0], [11,9,1], [9,9,1], + [4,2,-2], [4,8,0], [6,4,-3], [9,9,2], [7,9,1], [9,9,1], [9,9,1], [4,4,-3], + [6,11,3], [4,11,3], [6,5,-3], [8,7,1], [3,4,2], [4,2,-1], [3,2,0], [7,11,3], + [6,8,1], [5,7,0], [6,8,1], [6,8,1], [5,9,2], [6,8,1], [6,8,1], [7,8,1], + [6,8,1], [6,8,1], [4,5,0], [4,7,2], [4,8,3], [8,3,-1], [5,8,3], [6,8,0], + [8,9,1], [7,8,0], [8,7,0], [9,9,1], [8,7,0], [8,7,0], [8,7,0], [9,9,1], + [9,7,0], [6,7,0], [7,8,1], [9,7,0], [7,7,0], [11,7,0], [9,7,0], [8,9,1], + [8,7,0], [8,10,2], [8,8,1], [7,9,1], [9,7,0], [9,8,1], [9,8,1], [12,8,1], + [9,7,0], [9,7,0], [8,7,0], [5,11,3], [7,4,-3], [5,11,3], [6,2,-5], [4,2,-5], + [4,4,-3], [6,6,1], [5,8,1], [5,6,1], [6,8,1], [5,6,1], [6,11,3], [5,8,3], + [6,8,1], [4,8,1], [5,10,3], [6,8,1], [4,8,1], [9,6,1], [6,6,1], [6,6,1], + [6,7,2], [5,7,2], [5,6,1], [5,6,1], [4,8,1], [6,6,1], [5,6,1], [7,6,1], + [6,6,1], [6,8,3], [5,6,1], [6,1,-2], [11,1,-2], [6,2,-5], [6,2,-5], [6,2,-5] + ] +}); + +jsMath.Img.AddFont(85,{ + cmr10: [ + [7,9,0], [10,9,0], [9,10,1], [8,9,0], [8,9,0], [9,9,0], [8,9,0], [9,9,0], + [8,9,0], [9,9,0], [9,9,0], [8,9,0], [7,9,0], [7,9,0], [10,9,0], [10,9,0], + [3,6,0], [4,9,3], [4,3,-6], [5,3,-6], [5,2,-6], [5,3,-6], [6,2,-6], [6,3,-6], + [5,4,3], [6,10,1], [9,7,1], [9,7,1], [6,9,2], [11,9,0], [12,10,1], [9,10,1], + [4,2,-3], [3,9,0], [5,5,-4], [10,12,3], [6,10,1], [10,10,1], [9,10,1], [3,5,-4], + [4,12,3], [4,12,3], [6,6,-3], [9,8,1], [3,5,3], [4,1,-2], [3,2,0], [6,12,3], + [6,9,1], [6,8,0], [6,8,0], [6,9,1], [6,9,0], [6,9,1], [6,9,1], [6,10,1], + [6,9,1], [6,9,1], [3,6,0], [3,9,3], [3,9,3], [9,4,-1], [5,9,3], [5,9,0], + [9,10,1], [9,9,0], [8,9,0], [8,10,1], [9,9,0], [8,9,0], [8,9,0], [9,10,1], + [9,9,0], [4,9,0], [6,10,1], [9,9,0], [7,9,0], [11,9,0], [9,9,0], [9,10,1], + [8,9,0], [9,12,3], [9,10,1], [6,10,1], [9,9,0], [9,10,1], [9,10,1], [13,10,1], + [9,9,0], [9,9,0], [7,9,0], [4,12,3], [6,5,-4], [2,12,3], [5,3,-6], [3,3,-6], + [3,5,-4], [6,7,1], [7,10,1], [5,7,1], [7,10,1], [5,7,1], [5,9,0], [6,9,3], + [7,9,0], [3,9,0], [4,12,3], [7,9,0], [4,9,0], [10,6,0], [7,6,0], [6,7,1], + [7,9,3], [7,9,3], [5,6,0], [5,7,1], [4,9,1], [7,7,1], [7,7,1], [9,7,1], + [7,6,0], [7,9,3], [5,6,0], [6,1,-3], [12,1,-3], [6,3,-6], [5,3,-6], [5,3,-6] + ], + cmmi10: [ + [9,9,0], [10,9,0], [9,10,1], [8,9,0], [10,9,0], [11,9,0], [10,9,0], [9,9,0], + [8,9,0], [9,9,0], [10,9,0], [8,7,1], [8,12,3], [7,9,3], [6,10,1], [5,7,1], + [6,12,3], [6,9,3], [6,10,1], [4,7,1], [7,7,1], [7,10,1], [7,9,3], [7,6,0], + [6,12,3], [7,7,1], [7,9,3], [7,7,1], [7,7,1], [7,7,1], [7,12,3], [8,9,3], + [8,12,3], [8,7,1], [6,7,1], [7,10,1], [10,7,1], [7,9,3], [5,8,2], [8,9,3], + [12,5,-2], [12,5,1], [12,5,-2], [12,5,1], [3,4,-2], [3,4,-2], [6,8,1], [6,8,1], + [6,7,1], [6,6,0], [6,6,0], [6,9,3], [6,9,3], [6,9,3], [6,9,1], [6,9,3], + [6,9,1], [6,9,3], [3,2,0], [3,5,3], [9,8,1], [6,12,3], [9,8,1], [6,6,0], + [7,10,1], [9,9,0], [10,9,0], [10,10,1], [10,9,0], [10,9,0], [10,9,0], [10,10,1], + [11,9,0], [6,9,0], [8,10,1], [11,9,0], [8,9,0], [13,9,0], [11,9,0], [9,10,1], + [10,9,0], [9,12,3], [10,10,1], [8,10,1], [9,9,0], [10,10,1], [10,10,1], [13,10,1], + [11,9,0], [10,9,0], [9,9,0], [4,10,1], [4,12,3], [4,12,3], [12,4,-1], [12,4,-1], + [5,10,1], [6,7,1], [5,10,1], [6,7,1], [7,10,1], [6,7,1], [7,12,3], [6,9,3], + [7,10,1], [4,9,1], [6,11,3], [7,10,1], [4,10,1], [11,7,1], [7,7,1], [6,7,1], + [7,9,3], [6,9,3], [6,7,1], [6,7,1], [4,9,1], [7,7,1], [6,7,1], [9,7,1], + [7,7,1], [6,9,3], [6,7,1], [4,7,1], [6,9,3], [8,9,3], [8,3,-6], [8,2,-6] + ], + cmsy10: [ + [9,2,-2], [3,2,-2], [8,6,0], [6,6,0], [9,8,1], [6,6,0], [9,8,0], [9,8,2], + [9,8,1], [9,8,1], [9,8,1], [9,8,1], [9,8,1], [12,12,3], [6,6,0], [6,6,0], + [9,6,0], [9,6,0], [9,10,2], [9,10,2], [9,10,2], [9,10,2], [9,10,2], [9,10,2], + [9,4,-1], [9,6,0], [9,8,1], [9,8,1], [12,8,1], [12,8,1], [9,8,1], [9,8,1], + [12,6,0], [12,6,0], [6,12,3], [6,12,3], [12,6,0], [12,12,3], [12,12,3], [9,6,0], + [12,8,1], [12,8,1], [7,12,3], [7,12,3], [12,8,1], [12,12,3], [12,12,3], [9,7,1], + [4,7,0], [12,7,1], [7,8,1], [7,8,1], [10,9,0], [10,9,3], [8,12,3], [2,6,0], + [7,10,1], [6,9,0], [8,4,-1], [6,11,1], [9,10,1], [9,10,1], [9,8,0], [9,8,0], + [7,9,0], [10,10,1], [8,10,1], [7,10,1], [10,9,0], [7,10,1], [10,10,1], [8,11,2], + [10,10,1], [9,9,0], [11,11,2], [9,10,1], [8,10,1], [14,10,1], [13,11,1], [10,10,1], + [9,10,1], [10,11,2], [11,10,1], [8,10,1], [10,9,0], [10,10,1], [8,10,1], [13,10,1], + [10,9,0], [9,11,2], [10,9,0], [8,9,1], [8,9,1], [8,9,1], [8,9,1], [8,9,1], + [7,9,0], [7,9,0], [6,12,3], [4,12,3], [6,12,3], [4,12,3], [6,12,3], [6,12,3], + [4,12,3], [4,12,3], [2,12,3], [5,12,3], [6,14,4], [7,14,4], [6,12,3], [3,8,1], + [11,13,12], [9,9,0], [10,10,1], [6,12,3], [8,8,0], [8,8,0], [9,10,2], [9,10,2], + [5,12,3], [5,12,3], [5,12,3], [7,12,3], [9,11,2], [9,11,2], [9,10,1], [9,11,2] + ], + cmex10: [ + [5,15,14], [4,15,14], [5,15,14], [3,15,14], [6,15,14], [4,15,14], [6,15,14], [4,15,14], + [6,15,14], [6,15,14], [5,15,14], [5,15,14], [3,9,8], [5,9,8], [7,15,14], [7,15,14], + [7,23,22], [5,23,22], [9,30,29], [7,30,29], [7,30,29], [4,30,29], [7,30,29], [4,30,29], + [7,30,29], [4,30,29], [8,30,29], [8,30,29], [8,30,29], [8,30,29], [12,30,29], [12,30,29], + [10,37,36], [7,37,36], [7,37,36], [4,37,36], [8,37,36], [5,37,36], [8,37,36], [5,37,36], + [8,37,36], [8,37,36], [9,37,36], [8,37,36], [15,37,36], [15,37,36], [10,23,22], [10,23,22], + [11,23,22], [7,23,22], [8,23,22], [5,23,22], [8,23,22], [5,23,22], [5,9,8], [5,9,8], + [9,12,11], [7,12,11], [9,12,11], [7,12,11], [7,23,22], [9,23,22], [7,5,4], [5,9,8], + [11,23,22], [7,23,22], [5,9,8], [7,9,8], [7,23,22], [6,23,22], [10,13,12], [13,18,17], + [8,15,14], [12,28,27], [13,13,12], [18,18,17], [13,13,12], [18,18,17], [13,13,12], [18,18,17], + [12,13,12], [11,13,12], [8,15,14], [10,13,12], [10,13,12], [10,13,12], [10,13,12], [10,13,12], + [17,18,17], [15,18,17], [12,28,27], [13,18,17], [13,18,17], [13,18,17], [13,18,17], [13,18,17], + [11,13,12], [15,18,17], [8,3,-6], [14,4,-6], [19,4,-6], [7,2,-7], [12,2,-7], [18,2,-7], + [6,23,22], [3,23,22], [7,23,22], [4,23,22], [7,23,22], [4,23,22], [7,23,22], [7,23,22], + [13,15,14], [13,23,22], [13,30,29], [13,37,36], [9,23,22], [9,9,8], [13,8,7], [7,9,8], + [7,9,8], [7,9,8], [7,5,3], [7,5,3], [7,5,0], [7,5,0], [9,9,8], [9,9,8] + ], + cmbx10: [ + [8,9,0], [11,9,0], [10,10,1], [10,9,0], [9,9,0], [11,9,0], [10,9,0], [10,9,0], + [10,9,0], [10,9,0], [10,9,0], [9,9,0], [8,9,0], [8,9,0], [12,9,0], [12,9,0], + [4,6,0], [5,9,3], [5,3,-6], [6,3,-6], [6,2,-6], [6,3,-6], [6,2,-6], [7,3,-6], + [6,4,3], [7,10,1], [10,7,1], [11,7,1], [7,9,2], [13,9,0], [14,10,1], [10,10,1], + [4,2,-3], [4,9,0], [6,5,-4], [11,12,3], [7,10,1], [11,10,1], [11,10,1], [4,5,-4], + [5,12,3], [5,12,3], [6,6,-3], [10,10,2], [3,5,3], [4,2,-2], [3,2,0], [7,12,3], + [7,9,1], [6,8,0], [7,8,0], [7,9,1], [7,8,0], [7,9,1], [7,9,1], [7,10,1], + [7,9,1], [7,9,1], [3,6,0], [3,9,3], [4,9,3], [10,4,-1], [6,9,3], [6,9,0], + [10,10,1], [10,9,0], [10,9,0], [10,10,1], [10,9,0], [9,9,0], [9,9,0], [11,10,1], + [11,9,0], [5,9,0], [7,10,1], [11,9,0], [8,9,0], [13,9,0], [11,9,0], [10,10,1], + [9,9,0], [10,12,3], [11,10,1], [7,10,1], [10,9,0], [11,10,1], [11,10,1], [14,10,1], + [11,9,0], [11,9,0], [8,9,0], [4,12,3], [7,5,-4], [3,12,3], [6,3,-6], [3,3,-6], + [3,5,-4], [7,7,1], [8,10,1], [6,7,1], [8,10,1], [6,7,1], [6,9,0], [7,9,3], + [8,9,0], [4,9,0], [5,12,3], [8,9,0], [4,9,0], [12,6,0], [8,6,0], [7,7,1], + [8,9,3], [8,9,3], [6,6,0], [5,7,1], [5,9,1], [8,7,1], [7,7,1], [10,7,1], + [8,6,0], [7,9,3], [6,6,0], [7,1,-3], [14,1,-3], [6,3,-6], [6,2,-7], [6,3,-6] + ], + cmti10: [ + [9,9,0], [10,9,0], [10,10,1], [8,9,0], [10,9,0], [11,9,0], [10,9,0], [10,9,0], + [9,9,0], [10,9,0], [10,9,0], [11,12,3], [9,12,3], [9,12,3], [12,12,3], [13,12,3], + [4,7,1], [5,9,3], [6,3,-6], [7,3,-6], [7,2,-6], [7,3,-6], [7,2,-6], [9,3,-6], + [5,4,3], [8,12,3], [9,7,1], [9,7,1], [7,9,2], [12,9,0], [13,10,1], [10,10,1], + [5,2,-3], [5,9,0], [7,5,-4], [10,12,3], [9,10,1], [11,10,1], [10,10,1], [5,5,-4], + [7,12,3], [5,12,3], [7,6,-3], [10,8,1], [3,5,3], [5,1,-2], [3,2,0], [8,12,3], + [7,9,1], [6,8,0], [7,9,1], [7,9,1], [6,11,3], [7,9,1], [7,9,1], [8,9,1], + [7,9,1], [7,9,1], [4,6,0], [4,9,3], [4,9,3], [10,4,-1], [6,9,3], [7,9,0], + [10,10,1], [9,9,0], [9,9,0], [10,10,1], [10,9,0], [9,9,0], [9,9,0], [10,10,1], + [11,9,0], [7,9,0], [8,10,1], [11,9,0], [8,9,0], [13,9,0], [11,9,0], [10,10,1], + [9,9,0], [10,12,3], [9,10,1], [8,10,1], [10,9,0], [11,10,1], [11,10,1], [14,10,1], + [10,9,0], [11,9,0], [9,9,0], [6,12,3], [8,5,-4], [6,12,3], [7,3,-6], [5,3,-6], + [5,5,-4], [7,7,1], [6,10,1], [6,7,1], [7,10,1], [6,7,1], [7,12,3], [6,9,3], + [7,10,1], [4,9,1], [6,11,3], [7,10,1], [4,10,1], [11,7,1], [8,7,1], [7,7,1], + [7,9,3], [6,9,3], [6,7,1], [6,7,1], [5,9,1], [7,7,1], [6,7,1], [9,7,1], + [7,7,1], [7,9,3], [6,7,1], [7,1,-3], [13,1,-3], [7,3,-6], [7,3,-6], [7,3,-6] + ] +}); + +jsMath.Img.AddFont(100,{ + cmr10: [ + [9,10,0], [11,11,0], [11,11,1], [10,11,0], [9,10,0], [11,10,0], [10,10,0], [11,10,0], + [10,10,0], [11,10,0], [10,10,0], [9,10,0], [8,10,0], [8,10,0], [12,10,0], [12,10,0], + [4,7,0], [4,10,3], [5,3,-7], [6,3,-7], [6,2,-7], [6,3,-7], [7,2,-7], [7,4,-7], + [6,4,3], [7,11,1], [10,8,1], [11,8,1], [7,10,2], [13,10,0], [14,11,1], [11,12,1], + [4,3,-3], [3,11,0], [5,5,-5], [11,13,3], [7,12,1], [11,12,1], [11,12,1], [3,5,-5], + [5,15,4], [5,15,4], [7,7,-4], [11,11,2], [3,5,3], [4,2,-2], [3,2,0], [7,15,4], + [7,11,1], [6,10,0], [7,10,0], [7,11,1], [7,10,0], [7,11,1], [7,11,1], [7,11,1], + [7,11,1], [7,11,1], [3,7,0], [3,10,3], [3,11,4], [11,5,-1], [6,10,3], [6,10,0], + [11,11,1], [11,11,0], [10,10,0], [10,11,1], [10,10,0], [10,10,0], [9,10,0], [11,11,1], + [11,10,0], [5,10,0], [7,11,1], [11,10,0], [9,10,0], [13,10,0], [11,10,0], [11,11,1], + [9,10,0], [11,13,3], [11,11,1], [7,11,1], [10,10,0], [11,11,1], [11,11,1], [15,11,1], + [11,10,0], [11,10,0], [8,10,0], [4,15,4], [7,5,-5], [3,15,4], [6,3,-7], [3,3,-7], + [3,5,-5], [7,8,1], [8,11,1], [6,8,1], [8,11,1], [6,8,1], [5,10,0], [7,10,3], + [8,10,0], [4,10,0], [4,13,3], [8,10,0], [4,10,0], [12,7,0], [8,7,0], [7,8,1], + [8,10,3], [8,10,3], [6,7,0], [6,8,1], [5,10,1], [8,8,1], [8,8,1], [10,8,1], + [8,7,0], [8,10,3], [6,7,0], [7,1,-3], [14,1,-3], [6,3,-7], [6,2,-8], [6,3,-7] + ], + cmmi10: [ + [11,10,0], [12,11,0], [11,11,1], [10,11,0], [11,10,0], [13,10,0], [12,10,0], [10,10,0], + [9,10,0], [10,10,0], [11,10,0], [9,8,1], [9,13,3], [8,11,4], [7,11,1], [6,8,1], + [7,13,3], [7,11,4], [7,11,1], [5,8,1], [8,8,1], [8,11,1], [9,11,4], [8,7,0], + [7,13,3], [8,8,1], [8,11,4], [8,8,1], [8,8,1], [8,8,1], [9,13,3], [9,10,3], + [9,13,3], [9,8,1], [6,8,1], [8,11,1], [12,8,1], [8,10,3], [6,9,2], [9,11,4], + [14,5,-3], [14,5,1], [14,5,-3], [14,5,1], [4,4,-3], [4,4,-3], [7,9,1], [7,9,1], + [7,8,1], [6,7,0], [7,7,0], [7,11,4], [7,10,3], [7,11,4], [7,11,1], [7,11,4], + [7,11,1], [7,11,4], [3,2,0], [3,5,3], [10,9,1], [7,15,4], [10,9,1], [7,7,0], + [8,12,1], [11,11,0], [11,10,0], [11,11,1], [12,10,0], [11,10,0], [11,10,0], [11,11,1], + [13,10,0], [7,10,0], [9,11,1], [13,10,0], [9,10,0], [15,10,0], [13,10,0], [11,11,1], + [11,10,0], [11,13,3], [11,11,1], [10,11,1], [10,10,0], [11,11,1], [11,11,1], [15,11,1], + [12,10,0], [11,10,0], [11,10,0], [5,12,1], [5,15,4], [5,15,4], [14,5,-1], [14,5,-1], + [6,11,1], [7,8,1], [6,11,1], [7,8,1], [8,11,1], [7,8,1], [8,13,3], [7,10,3], + [8,11,1], [5,11,1], [7,13,3], [8,11,1], [4,11,1], [12,8,1], [8,8,1], [7,8,1], + [8,10,3], [7,10,3], [7,8,1], [6,8,1], [5,10,1], [8,8,1], [7,8,1], [10,8,1], + [8,8,1], [7,10,3], [7,8,1], [5,8,1], [7,10,3], [9,11,4], [9,3,-7], [10,3,-7] + ], + cmsy10: [ + [10,1,-3], [3,3,-2], [9,7,0], [7,7,0], [11,9,1], [7,7,0], [11,10,0], [11,10,3], + [11,11,2], [11,11,2], [11,11,2], [11,11,2], [11,11,2], [14,15,4], [7,7,0], [7,7,0], + [11,7,0], [11,7,0], [10,11,2], [10,11,2], [10,11,2], [10,11,2], [10,11,2], [10,11,2], + [11,5,-1], [11,7,0], [10,9,1], [10,9,1], [14,9,1], [14,9,1], [10,9,1], [10,9,1], + [14,5,-1], [14,5,-1], [6,13,3], [6,13,3], [14,5,-1], [14,13,3], [14,13,3], [11,7,0], + [14,9,1], [14,9,1], [9,13,3], [9,13,3], [14,9,1], [14,13,3], [14,13,3], [11,8,1], + [4,8,0], [14,8,1], [9,9,1], [9,9,1], [12,11,0], [12,11,4], [9,15,4], [2,7,0], + [8,11,1], [7,10,0], [9,4,-1], [7,13,2], [10,12,1], [10,11,1], [11,10,0], [11,10,0], + [8,10,0], [12,12,1], [10,11,1], [8,11,1], [11,10,0], [8,11,1], [12,11,1], [9,12,2], + [12,11,1], [10,10,0], [12,12,2], [11,11,1], [10,11,1], [16,11,1], [15,12,1], [11,11,1], + [11,11,1], [12,12,2], [12,11,1], [9,11,1], [12,11,0], [11,11,1], [10,11,1], [15,11,1], + [12,10,0], [11,12,2], [11,10,0], [9,10,1], [9,10,1], [9,10,1], [9,10,1], [9,10,1], + [8,10,0], [8,10,0], [6,15,4], [4,15,4], [6,15,4], [4,15,4], [6,15,4], [6,15,4], + [5,15,4], [4,15,4], [3,15,4], [6,15,4], [6,15,4], [9,15,4], [7,15,4], [4,11,2], + [12,15,14], [10,10,0], [11,11,1], [7,15,4], [9,9,0], [9,9,0], [10,11,2], [10,11,2], + [6,13,3], [6,14,4], [6,13,3], [9,13,3], [11,13,2], [11,14,3], [11,12,1], [11,13,2] + ], + cmex10: [ + [6,18,17], [5,18,17], [6,18,17], [3,18,17], [7,18,17], [4,18,17], [7,18,17], [4,18,17], + [7,18,17], [7,18,17], [6,18,17], [6,18,17], [3,10,9], [6,10,9], [8,18,17], [8,18,17], + [8,26,25], [6,26,25], [10,35,34], [8,35,34], [8,35,34], [4,35,34], [8,35,34], [5,35,34], + [8,35,34], [5,35,34], [9,35,34], [9,35,34], [10,35,34], [9,35,34], [14,35,34], [14,35,34], + [11,43,42], [8,43,42], [8,43,42], [5,43,42], [9,43,42], [6,43,42], [9,43,42], [6,43,42], + [10,43,42], [10,43,42], [10,43,42], [10,43,42], [18,43,42], [18,43,42], [11,26,25], [11,26,25], + [12,26,25], [9,26,25], [10,26,25], [5,26,25], [10,26,25], [5,26,25], [6,10,9], [5,10,9], + [11,14,13], [8,14,13], [11,14,13], [8,14,13], [8,27,26], [11,27,26], [8,6,5], [5,10,9], + [12,26,25], [9,26,25], [6,10,9], [9,10,9], [8,26,25], [7,26,25], [11,15,14], [15,21,20], + [9,17,16], [14,33,32], [15,15,14], [21,21,20], [15,15,14], [21,21,20], [15,15,14], [21,21,20], + [14,15,14], [13,15,14], [9,17,16], [11,15,14], [11,15,14], [11,15,14], [11,15,14], [11,15,14], + [20,21,20], [18,21,20], [14,33,32], [15,21,20], [15,21,20], [15,21,20], [15,21,20], [15,21,20], + [13,15,14], [18,21,20], [9,4,-7], [16,3,-8], [22,3,-8], [8,3,-8], [14,3,-8], [21,3,-8], + [7,26,25], [4,26,25], [8,26,25], [5,26,25], [8,26,25], [5,26,25], [8,26,25], [8,26,25], + [15,18,17], [15,26,25], [15,35,34], [15,43,42], [11,27,26], [11,10,9], [16,10,9], [8,10,9], + [8,10,9], [8,10,9], [8,5,3], [8,5,3], [8,5,0], [8,5,0], [11,10,9], [11,10,9] + ], + cmbx10: [ + [9,10,0], [13,10,0], [12,11,1], [11,10,0], [11,10,0], [13,10,0], [11,10,0], [12,10,0], + [11,10,0], [12,10,0], [11,10,0], [11,10,0], [9,10,0], [9,10,0], [13,10,0], [13,10,0], + [4,7,0], [5,10,3], [5,3,-7], [7,3,-7], [7,3,-7], [7,3,-7], [7,2,-7], [8,3,-7], + [7,4,3], [8,11,1], [12,8,1], [13,8,1], [8,10,2], [15,10,0], [16,11,1], [12,12,1], + [5,3,-3], [4,10,0], [7,6,-4], [13,13,3], [8,12,1], [13,12,1], [12,11,1], [4,6,-4], + [6,15,4], [5,15,4], [7,7,-4], [12,11,2], [4,6,3], [5,2,-2], [4,3,0], [8,15,4], + [8,11,1], [7,10,0], [8,10,0], [8,11,1], [8,10,0], [8,11,1], [8,11,1], [8,11,1], + [8,11,1], [8,11,1], [4,7,0], [4,10,3], [4,10,3], [12,5,-1], [7,10,3], [7,10,0], + [12,11,1], [12,10,0], [11,10,0], [11,11,1], [12,10,0], [11,10,0], [10,10,0], [12,11,1], + [13,10,0], [6,10,0], [8,11,1], [12,10,0], [9,10,0], [15,10,0], [13,10,0], [12,11,1], + [11,10,0], [12,13,3], [13,11,1], [9,11,1], [11,10,0], [12,11,1], [12,11,1], [17,11,1], + [12,10,0], [12,10,0], [10,10,0], [5,15,4], [8,6,-4], [3,15,4], [7,3,-7], [4,3,-7], + [4,6,-4], [8,8,1], [9,11,1], [7,8,1], [9,11,1], [7,8,1], [7,10,0], [8,10,3], + [9,10,0], [4,10,0], [5,13,3], [9,10,0], [5,10,0], [14,7,0], [9,7,0], [8,8,1], + [9,10,3], [9,10,3], [7,7,0], [6,8,1], [6,10,1], [9,8,1], [9,8,1], [12,8,1], + [9,7,0], [9,10,3], [7,7,0], [9,2,-3], [17,2,-3], [7,3,-7], [7,2,-8], [7,3,-7] + ], + cmti10: [ + [10,10,0], [11,11,0], [12,11,1], [9,11,0], [11,10,0], [12,10,0], [11,10,0], [12,10,0], + [11,10,0], [12,10,0], [11,10,0], [12,13,3], [10,13,3], [10,13,3], [14,13,3], [15,13,3], + [5,8,1], [6,10,3], [7,3,-7], [8,3,-7], [8,2,-7], [8,3,-7], [8,2,-7], [10,4,-7], + [5,4,3], [10,13,3], [11,8,1], [11,8,1], [8,10,2], [14,10,0], [15,11,1], [12,12,1], + [5,3,-3], [6,11,0], [8,5,-5], [12,13,3], [10,11,1], [12,12,1], [12,12,1], [6,5,-5], + [8,15,4], [6,15,4], [9,7,-4], [11,9,1], [4,5,3], [5,2,-2], [4,2,0], [9,15,4], + [8,11,1], [7,10,0], [8,11,1], [8,11,1], [7,13,3], [8,11,1], [8,11,1], [9,11,1], + [8,11,1], [8,11,1], [5,7,0], [5,10,3], [5,11,4], [11,5,-1], [7,11,4], [8,11,0], + [12,11,1], [10,11,0], [11,10,0], [12,11,1], [11,10,0], [11,10,0], [11,10,0], [12,11,1], + [12,10,0], [8,10,0], [9,11,1], [13,10,0], [9,10,0], [15,10,0], [12,10,0], [12,11,1], + [11,10,0], [12,13,3], [11,11,1], [9,11,1], [12,10,0], [12,11,1], [13,11,1], [16,11,1], + [12,10,0], [13,10,0], [10,10,0], [7,15,4], [9,5,-5], [7,15,4], [8,3,-7], [6,3,-7], + [6,5,-5], [8,8,1], [7,11,1], [7,8,1], [8,11,1], [7,8,1], [8,13,3], [7,10,3], + [8,11,1], [5,11,1], [6,13,3], [8,11,1], [5,11,1], [12,8,1], [9,8,1], [8,8,1], + [8,10,3], [7,10,3], [7,8,1], [6,8,1], [6,10,1], [8,8,1], [7,8,1], [10,8,1], + [8,8,1], [8,10,3], [7,8,1], [8,1,-3], [15,1,-3], [9,3,-7], [9,3,-7], [8,3,-7] + ] +}); + +jsMath.Img.AddFont(120,{ + cmr10: [ + [10,12,0], [14,13,0], [13,13,1], [12,13,0], [11,12,0], [13,12,0], [12,12,0], [13,12,0], + [12,12,0], [13,12,0], [12,12,0], [11,12,0], [9,12,0], [9,12,0], [14,12,0], [14,12,0], + [5,8,0], [5,12,4], [5,4,-8], [7,4,-8], [7,3,-8], [7,4,-8], [8,2,-9], [8,4,-9], + [7,5,4], [8,13,1], [12,9,1], [13,9,1], [8,12,2], [15,12,0], [17,13,1], [13,14,1], + [5,3,-4], [4,13,0], [6,6,-6], [14,16,4], [8,14,1], [14,14,1], [13,14,1], [4,6,-6], + [6,18,5], [5,18,5], [8,8,-5], [13,12,2], [4,6,4], [5,2,-3], [4,2,0], [8,18,5], + [8,13,1], [8,12,0], [8,12,0], [8,13,1], [8,12,0], [8,13,1], [8,13,1], [9,13,1], + [8,13,1], [8,13,1], [4,8,0], [4,12,4], [4,13,4], [13,5,-2], [8,13,4], [8,12,0], + [13,13,1], [13,13,0], [12,12,0], [12,13,1], [13,12,0], [12,12,0], [11,12,0], [13,13,1], + [13,12,0], [6,12,0], [8,13,1], [13,12,0], [10,12,0], [15,12,0], [13,12,0], [13,13,1], + [11,12,0], [13,16,4], [13,13,1], [9,13,1], [12,12,0], [13,13,1], [13,13,1], [18,13,1], + [13,12,0], [13,12,0], [10,12,0], [5,18,5], [8,6,-6], [3,18,5], [7,3,-9], [4,3,-9], + [4,6,-6], [9,9,1], [9,13,1], [8,9,1], [9,13,1], [8,9,1], [7,12,0], [9,12,4], + [10,12,0], [5,12,0], [5,16,4], [9,12,0], [5,12,0], [14,8,0], [10,8,0], [8,9,1], + [9,12,4], [9,12,4], [7,8,0], [7,9,1], [6,12,1], [10,9,1], [9,9,1], [12,9,1], + [9,8,0], [9,12,4], [7,8,0], [9,1,-4], [17,1,-4], [8,4,-8], [8,3,-9], [7,3,-9] + ], + cmmi10: [ + [13,12,0], [14,13,0], [13,13,1], [12,13,0], [14,12,0], [15,12,0], [14,12,0], [12,12,0], + [11,12,0], [12,12,0], [14,12,0], [11,9,1], [11,16,4], [10,12,4], [8,14,1], [7,9,1], + [9,16,4], [9,12,4], [8,13,1], [6,9,1], [10,9,1], [10,13,1], [10,12,4], [9,8,0], + [8,16,4], [10,9,1], [9,12,4], [10,9,1], [9,9,1], [9,9,1], [10,16,4], [11,12,4], + [11,16,4], [11,9,1], [8,9,1], [10,13,1], [14,9,1], [9,12,4], [7,10,2], [11,12,4], + [17,6,-3], [17,6,1], [17,6,-3], [17,6,1], [4,5,-3], [4,5,-3], [9,10,1], [9,10,1], + [8,9,1], [8,8,0], [8,8,0], [8,12,4], [8,12,4], [8,12,4], [8,13,1], [9,12,4], + [8,13,1], [8,12,4], [4,2,0], [4,6,4], [12,11,1], [8,18,5], [12,11,1], [9,9,0], + [10,14,1], [13,13,0], [13,12,0], [13,13,1], [14,12,0], [14,12,0], [13,12,0], [13,13,1], + [15,12,0], [9,12,0], [11,13,1], [16,12,0], [11,12,0], [18,12,0], [15,12,0], [13,13,1], + [13,12,0], [13,16,4], [13,13,1], [11,13,1], [12,12,0], [13,13,1], [14,13,1], [18,13,1], + [15,12,0], [13,12,0], [13,12,0], [6,14,1], [6,17,4], [6,17,4], [17,5,-2], [17,5,-2], + [7,13,1], [9,9,1], [8,13,1], [8,9,1], [9,13,1], [8,9,1], [10,16,4], [9,12,4], + [10,13,1], [5,13,1], [8,16,4], [9,13,1], [5,13,1], [15,9,1], [10,9,1], [8,9,1], + [10,12,4], [8,12,4], [8,9,1], [8,9,1], [6,12,1], [10,9,1], [8,9,1], [12,9,1], + [9,9,1], [9,12,4], [8,9,1], [5,9,1], [8,12,4], [11,12,4], [11,5,-8], [12,3,-9] + ], + cmsy10: [ + [12,2,-3], [4,3,-3], [11,9,0], [8,8,0], [13,11,1], [9,9,0], [13,12,0], [13,12,3], + [13,12,2], [13,12,2], [13,12,2], [13,12,2], [13,12,2], [17,17,4], [8,8,0], [8,8,0], + [13,9,0], [13,8,0], [12,14,3], [12,14,3], [12,14,3], [12,14,3], [12,14,3], [12,14,3], + [13,5,-2], [13,9,0], [12,11,1], [12,11,1], [17,12,2], [17,12,2], [12,11,1], [12,11,1], + [17,7,-1], [17,7,-1], [8,16,4], [8,16,4], [17,7,-1], [17,16,4], [17,16,4], [13,8,0], + [17,10,1], [17,10,1], [10,16,4], [10,16,4], [17,10,1], [17,16,4], [17,16,4], [13,9,1], + [5,10,0], [17,9,1], [10,11,1], [10,11,1], [15,13,0], [15,13,4], [11,17,4], [3,7,-1], + [10,13,1], [9,12,0], [11,6,-1], [8,16,2], [13,14,1], [12,13,1], [13,12,0], [13,12,0], + [10,12,0], [14,14,1], [12,13,1], [10,13,1], [14,12,0], [10,13,1], [15,13,1], [11,15,3], + [14,13,1], [12,12,0], [15,15,3], [13,13,1], [12,13,1], [19,13,1], [18,15,1], [14,13,1], + [13,13,1], [14,15,3], [15,13,1], [11,13,1], [14,13,0], [13,13,1], [12,13,1], [18,13,1], + [14,12,0], [13,15,3], [14,12,0], [11,12,1], [11,12,1], [11,12,1], [11,12,1], [11,12,1], + [10,12,0], [10,12,0], [8,18,5], [5,18,5], [8,18,5], [5,18,5], [8,18,5], [8,18,5], + [6,18,5], [5,18,5], [3,18,5], [7,18,5], [8,19,5], [10,19,5], [8,18,5], [4,12,2], + [15,18,17], [13,12,0], [14,13,1], [8,17,4], [11,11,0], [11,11,0], [13,14,3], [12,14,3], + [7,16,4], [7,16,4], [7,16,4], [10,16,4], [13,16,3], [13,16,3], [13,14,1], [13,16,3] + ], + cmex10: [ + [8,21,20], [6,21,20], [7,21,20], [4,21,20], [8,21,20], [5,21,20], [8,21,20], [5,21,20], + [8,21,20], [8,21,20], [7,21,20], [7,21,20], [4,12,11], [7,12,11], [9,21,20], [9,21,20], + [10,31,30], [8,31,30], [12,42,41], [9,42,41], [9,42,41], [5,42,41], [10,42,41], [6,42,41], + [10,42,41], [6,42,41], [11,42,41], [11,42,41], [12,42,41], [11,42,41], [17,42,41], [17,42,41], + [13,52,51], [10,52,51], [10,52,51], [6,52,51], [11,52,51], [7,52,51], [11,52,51], [7,52,51], + [12,52,51], [12,52,51], [12,52,51], [12,52,51], [21,52,51], [21,52,51], [13,31,30], [13,31,30], + [15,32,31], [10,32,31], [12,31,30], [6,31,30], [12,31,30], [6,31,30], [7,12,11], [6,12,11], + [13,17,16], [9,17,16], [13,17,16], [9,17,16], [9,32,31], [13,32,31], [9,7,6], [7,12,11], + [15,31,30], [10,31,30], [7,12,11], [10,12,11], [9,31,30], [9,31,30], [14,18,17], [18,25,24], + [11,20,19], [17,39,38], [18,18,17], [25,25,24], [18,18,17], [25,25,24], [18,18,17], [25,25,24], + [17,18,17], [16,18,17], [11,20,19], [14,18,17], [14,18,17], [14,18,17], [14,18,17], [14,18,17], + [24,25,24], [21,25,24], [17,39,38], [18,25,24], [18,25,24], [18,25,24], [18,25,24], [18,25,24], + [16,18,17], [21,25,24], [11,4,-9], [19,5,-9], [26,5,-9], [10,3,-10], [17,3,-10], [25,3,-10], + [8,31,30], [5,31,30], [9,31,30], [6,31,30], [9,31,30], [6,31,30], [10,31,30], [10,31,30], + [18,21,20], [18,31,30], [18,42,41], [18,52,51], [13,32,31], [13,12,11], [19,11,10], [9,12,11], + [10,12,11], [10,12,11], [9,7,4], [10,7,4], [9,6,0], [10,6,0], [13,12,11], [13,12,11] + ], + cmbx10: [ + [11,12,0], [16,12,0], [15,13,1], [13,12,0], [13,12,0], [15,12,0], [14,12,0], [15,12,0], + [14,12,0], [15,12,0], [14,12,0], [13,12,0], [11,12,0], [11,12,0], [16,12,0], [16,12,0], + [5,8,0], [6,12,4], [6,4,-8], [8,4,-8], [8,4,-8], [8,4,-8], [9,2,-9], [10,3,-9], + [8,5,4], [10,13,1], [14,9,1], [15,9,1], [10,12,2], [18,12,0], [20,13,1], [15,15,2], + [6,3,-4], [5,12,0], [8,7,-5], [16,16,4], [9,14,1], [16,14,1], [15,13,1], [5,7,-5], + [7,18,5], [6,18,5], [9,8,-5], [15,14,3], [5,7,4], [6,3,-2], [5,3,0], [9,18,5], + [9,13,1], [9,12,0], [9,12,0], [9,13,1], [10,12,0], [9,13,1], [9,13,1], [10,13,1], + [9,13,1], [9,13,1], [5,8,0], [5,12,4], [5,13,4], [15,6,-1], [9,13,4], [9,12,0], + [15,13,1], [15,12,0], [13,12,0], [14,13,1], [14,12,0], [13,12,0], [12,12,0], [15,13,1], + [15,12,0], [7,12,0], [9,13,1], [15,12,0], [11,12,0], [18,12,0], [15,12,0], [14,13,1], + [13,12,0], [14,16,4], [15,13,1], [10,13,1], [13,12,0], [15,13,1], [15,13,1], [20,13,1], + [15,12,0], [15,12,0], [11,12,0], [5,18,5], [10,7,-5], [4,18,5], [8,3,-9], [5,3,-9], + [5,7,-5], [10,9,1], [11,13,1], [9,9,1], [11,13,1], [9,9,1], [8,12,0], [10,12,4], + [11,12,0], [5,12,0], [6,16,4], [10,12,0], [5,12,0], [16,8,0], [11,8,0], [10,9,1], + [11,12,4], [11,12,4], [8,8,0], [8,9,1], [7,12,1], [11,9,1], [10,9,1], [14,9,1], + [10,8,0], [10,12,4], [8,8,0], [10,1,-4], [20,1,-4], [9,5,-8], [9,3,-9], [8,3,-9] + ], + cmti10: [ + [13,12,0], [13,13,0], [14,13,1], [11,13,0], [13,12,0], [15,12,0], [14,12,0], [15,12,0], + [13,12,0], [15,12,0], [13,12,0], [14,16,4], [12,16,4], [12,16,4], [17,16,4], [18,16,4], + [6,9,1], [7,12,4], [8,4,-8], [10,4,-8], [10,3,-8], [10,4,-8], [10,2,-9], [12,4,-9], + [6,5,4], [11,16,4], [13,9,1], [13,9,1], [10,12,2], [17,12,0], [18,13,1], [14,15,2], + [6,3,-4], [7,13,0], [9,6,-6], [15,16,4], [12,13,1], [15,14,1], [14,14,1], [7,6,-6], + [9,18,5], [7,18,5], [10,8,-5], [13,11,1], [4,6,4], [6,2,-3], [4,2,0], [11,18,5], + [10,13,1], [8,12,0], [10,13,1], [10,13,1], [9,16,4], [10,13,1], [10,13,1], [11,13,1], + [10,13,1], [10,13,1], [6,8,0], [6,12,4], [6,13,4], [14,5,-2], [8,13,4], [10,13,0], + [14,13,1], [12,13,0], [13,12,0], [14,13,1], [14,12,0], [13,12,0], [13,12,0], [14,13,1], + [15,12,0], [9,12,0], [11,13,1], [15,12,0], [11,12,0], [18,12,0], [15,12,0], [14,13,1], + [13,12,0], [14,16,4], [13,13,1], [11,13,1], [14,12,0], [15,13,1], [15,13,1], [20,13,1], + [15,12,0], [15,12,0], [12,12,0], [8,18,5], [11,6,-6], [8,18,5], [9,3,-9], [7,3,-9], + [7,6,-6], [10,9,1], [8,13,1], [8,9,1], [10,13,1], [8,9,1], [9,16,4], [9,12,4], + [10,13,1], [6,13,1], [8,16,4], [9,13,1], [6,13,1], [15,9,1], [10,9,1], [9,9,1], + [9,12,4], [9,12,4], [9,9,1], [8,9,1], [7,12,1], [10,9,1], [9,9,1], [12,9,1], + [9,9,1], [9,12,4], [8,9,1], [10,1,-4], [18,1,-4], [10,4,-8], [10,3,-9], [10,3,-9] + ] +}); + +jsMath.Img.AddFont(144,{ + cmr10: [ + [12,14,0], [16,15,0], [15,16,1], [14,15,0], [13,14,0], [15,14,0], [14,14,0], [15,15,0], + [14,14,0], [15,14,0], [14,15,0], [13,15,0], [11,15,0], [11,15,0], [17,15,0], [17,15,0], + [5,9,0], [6,14,5], [6,4,-10], [8,4,-10], [8,3,-10], [8,4,-10], [9,1,-11], [10,5,-10], + [8,6,5], [10,16,1], [14,10,1], [15,10,1], [10,14,3], [18,14,0], [20,16,1], [15,17,2], + [6,3,-5], [4,15,0], [7,7,-7], [16,18,4], [9,17,2], [16,17,2], [15,16,1], [5,7,-7], + [7,20,5], [6,20,5], [9,9,-6], [15,14,2], [5,7,4], [6,2,-3], [4,3,0], [9,20,5], + [10,15,1], [9,14,0], [9,14,0], [10,15,1], [10,14,0], [9,15,1], [10,15,1], [10,15,1], + [10,15,1], [10,15,1], [4,9,0], [4,13,4], [4,15,5], [15,6,-2], [9,15,5], [9,15,0], + [15,16,1], [15,15,0], [14,14,0], [14,16,1], [15,14,0], [14,14,0], [13,14,0], [15,16,1], + [15,14,0], [7,14,0], [10,15,1], [15,14,0], [12,14,0], [18,14,0], [15,14,0], [15,16,1], + [13,14,0], [15,19,4], [15,15,1], [10,16,1], [14,14,0], [15,15,1], [15,15,1], [21,15,1], + [15,14,0], [15,14,0], [12,14,0], [6,20,5], [10,7,-7], [4,20,5], [8,4,-10], [4,3,-11], + [4,7,-7], [10,10,1], [11,15,1], [9,10,1], [11,15,1], [9,10,1], [8,15,0], [10,15,5], + [11,14,0], [5,14,0], [6,19,5], [11,14,0], [6,14,0], [17,9,0], [11,9,0], [10,10,1], + [11,13,4], [11,13,4], [8,9,0], [8,10,1], [7,14,1], [11,10,1], [11,10,1], [15,10,1], + [11,9,0], [11,14,5], [9,9,0], [10,1,-5], [20,1,-5], [9,4,-10], [9,3,-11], [8,3,-11] + ], + cmmi10: [ + [15,14,0], [16,15,0], [15,16,1], [14,15,0], [16,14,0], [18,14,0], [17,14,0], [15,15,0], + [13,14,0], [14,14,0], [16,15,0], [13,10,1], [12,19,4], [11,14,5], [10,16,1], [8,10,1], + [10,19,5], [10,14,5], [10,16,1], [7,10,1], [11,10,1], [11,15,1], [12,14,5], [11,9,0], + [9,19,5], [12,10,1], [11,14,5], [12,10,1], [11,10,1], [11,10,1], [12,19,5], [12,14,5], + [13,19,5], [13,10,1], [9,11,1], [12,16,1], [17,10,1], [11,13,4], [9,12,3], [13,14,5], + [19,7,-4], [19,7,1], [19,7,-4], [19,7,1], [5,6,-4], [5,6,-4], [10,12,1], [10,12,1], + [10,11,1], [9,10,0], [9,10,0], [10,15,5], [10,14,4], [9,15,5], [10,15,1], [10,15,5], + [10,15,1], [10,15,5], [4,3,0], [5,7,4], [14,12,1], [9,20,5], [14,12,1], [10,10,0], + [12,16,1], [15,15,0], [16,14,0], [16,16,1], [17,14,0], [16,14,0], [16,14,0], [16,16,1], + [18,14,0], [10,14,0], [13,15,1], [18,14,0], [13,14,0], [21,14,0], [18,14,0], [15,16,1], + [16,14,0], [15,19,4], [16,15,1], [13,16,1], [15,14,0], [16,15,1], [16,15,1], [21,15,1], + [18,14,0], [16,14,0], [15,14,0], [7,16,1], [7,20,5], [7,20,5], [19,6,-2], [19,6,-2], + [8,16,1], [10,10,1], [9,15,1], [9,10,1], [11,15,1], [9,10,1], [12,20,5], [10,14,5], + [11,15,1], [6,15,1], [9,19,5], [11,15,1], [6,15,1], [17,10,1], [12,10,1], [10,10,1], + [11,13,4], [10,13,4], [9,10,1], [9,10,1], [7,14,1], [11,10,1], [10,10,1], [14,10,1], + [11,10,1], [10,14,5], [10,10,1], [6,10,1], [9,14,5], [13,15,5], [13,5,-10], [13,4,-10] + ], + cmsy10: [ + [14,2,-4], [4,4,-3], [13,10,0], [9,10,0], [15,12,1], [10,10,0], [15,14,0], [15,14,4], + [15,14,2], [15,14,2], [15,14,2], [15,14,2], [15,14,2], [19,20,5], [9,8,-1], [9,8,-1], + [15,10,0], [15,10,0], [14,16,3], [14,16,3], [14,16,3], [14,16,3], [14,16,3], [14,16,3], + [15,6,-2], [15,9,-1], [14,12,1], [14,12,1], [19,14,2], [19,14,2], [14,12,1], [14,12,1], + [19,8,-1], [19,8,-1], [9,18,4], [9,18,4], [19,8,-1], [19,18,4], [19,18,4], [15,10,0], + [19,12,1], [19,12,1], [12,18,4], [12,18,4], [20,12,1], [19,18,4], [19,18,4], [15,10,1], + [6,12,0], [19,10,1], [12,12,1], [12,12,1], [17,15,0], [17,15,5], [13,20,5], [3,8,-1], + [12,15,1], [10,14,0], [13,7,-1], [10,18,2], [15,16,1], [14,16,1], [15,14,0], [15,14,0], + [12,14,0], [16,16,1], [14,16,1], [11,16,1], [16,14,0], [12,16,1], [17,15,1], [13,18,3], + [17,15,1], [14,14,0], [17,17,3], [15,16,1], [14,16,1], [23,16,1], [21,17,1], [16,16,1], + [15,15,1], [16,18,3], [17,15,1], [13,16,1], [16,15,0], [15,15,1], [14,15,1], [21,15,1], + [17,14,0], [15,17,3], [16,14,0], [13,13,1], [13,13,1], [13,13,1], [13,13,1], [13,13,1], + [12,14,0], [12,14,0], [9,20,5], [6,20,5], [9,20,5], [6,20,5], [9,20,5], [9,20,5], + [7,20,5], [6,20,5], [4,20,5], [8,20,5], [9,22,6], [12,22,6], [9,20,5], [5,14,2], + [18,21,20], [15,14,0], [16,15,1], [10,20,5], [13,12,0], [13,12,0], [15,16,3], [14,16,3], + [8,20,5], [8,20,5], [8,20,5], [12,18,4], [15,18,3], [15,19,4], [15,16,1], [15,18,3] + ], + cmex10: [ + [9,25,24], [7,25,24], [8,25,24], [5,25,24], [9,25,24], [6,25,24], [9,25,24], [6,25,24], + [10,25,24], [10,25,24], [8,25,24], [8,25,24], [4,14,13], [9,14,13], [11,25,24], [11,25,24], + [12,37,36], [9,37,36], [14,49,48], [11,49,48], [11,49,48], [6,49,48], [12,49,48], [7,49,48], + [12,49,48], [7,49,48], [13,49,48], [13,49,48], [14,49,48], [13,49,48], [20,49,48], [20,49,48], + [16,61,60], [12,61,60], [12,61,60], [7,61,60], [13,61,60], [8,61,60], [13,61,60], [8,61,60], + [14,61,60], [14,61,60], [14,61,60], [14,61,60], [25,61,60], [25,61,60], [16,37,36], [16,37,36], + [17,37,36], [12,37,36], [14,37,36], [7,37,36], [14,37,36], [7,37,36], [8,14,13], [7,14,13], + [15,20,19], [11,20,19], [15,19,18], [11,19,18], [11,38,37], [15,38,37], [11,8,7], [8,14,13], + [17,37,36], [12,37,36], [9,14,13], [12,14,13], [11,37,36], [10,37,36], [16,21,20], [22,29,28], + [13,24,23], [19,46,45], [22,21,20], [30,29,28], [22,21,20], [30,29,28], [22,21,20], [30,29,28], + [20,21,20], [18,21,20], [13,24,23], [16,21,20], [16,21,20], [16,21,20], [16,21,20], [16,21,20], + [28,29,28], [25,29,28], [19,46,45], [22,29,28], [22,29,28], [22,29,28], [22,29,28], [22,29,28], + [18,21,20], [25,29,28], [13,4,-11], [22,5,-11], [30,5,-11], [12,3,-12], [20,3,-12], [29,3,-12], + [10,37,36], [5,37,36], [11,37,36], [7,37,36], [11,37,36], [7,37,36], [11,37,36], [11,37,36], + [21,25,24], [21,37,36], [21,49,48], [21,61,60], [15,37,36], [15,14,13], [22,13,12], [11,14,13], + [12,13,12], [12,13,12], [11,8,5], [11,8,5], [11,7,0], [11,7,0], [15,13,12], [15,13,12] + ], + cmbx10: [ + [13,14,0], [18,14,0], [17,15,1], [16,14,0], [15,14,0], [18,14,0], [16,14,0], [17,14,0], + [16,14,0], [17,14,0], [16,14,0], [15,14,0], [13,14,0], [13,14,0], [19,14,0], [19,14,0], + [6,9,0], [8,13,4], [7,5,-10], [10,5,-10], [9,4,-10], [10,4,-10], [10,2,-11], [12,5,-10], + [9,5,4], [12,15,1], [16,11,1], [18,11,1], [11,15,3], [21,14,0], [23,15,1], [17,17,2], + [7,4,-5], [6,15,0], [10,8,-6], [18,18,4], [11,17,2], [18,17,2], [17,16,1], [6,8,-6], + [8,20,5], [7,20,5], [10,9,-6], [17,16,3], [5,8,4], [7,3,-3], [5,4,0], [11,20,5], + [11,15,1], [10,14,0], [11,14,0], [11,15,1], [11,14,0], [11,15,1], [11,15,1], [12,15,1], + [11,15,1], [11,15,1], [5,9,0], [5,13,4], [6,15,5], [17,6,-2], [10,14,4], [10,14,0], + [17,15,1], [17,14,0], [16,14,0], [16,15,1], [17,14,0], [15,14,0], [14,14,0], [17,15,1], + [18,14,0], [9,14,0], [11,15,1], [18,14,0], [13,14,0], [22,14,0], [18,14,0], [16,15,1], + [15,14,0], [17,18,4], [18,15,1], [12,15,1], [16,14,0], [17,15,1], [17,15,1], [24,15,1], + [17,14,0], [17,14,0], [13,14,0], [6,20,5], [12,8,-6], [4,20,5], [9,4,-10], [5,4,-10], + [5,8,-6], [12,11,1], [12,15,1], [10,11,1], [13,15,1], [10,11,1], [9,14,0], [12,15,5], + [13,14,0], [6,14,0], [8,18,4], [12,14,0], [6,14,0], [19,9,0], [13,9,0], [11,11,1], + [12,13,4], [13,13,4], [9,9,0], [9,11,1], [8,14,1], [13,10,1], [12,10,1], [17,10,1], + [12,9,0], [12,13,4], [10,9,0], [12,1,-5], [23,1,-5], [10,5,-10], [10,3,-11], [10,3,-11] + ], + cmti10: [ + [15,14,0], [16,15,0], [16,16,1], [13,15,0], [16,14,0], [18,14,0], [16,14,0], [17,15,0], + [15,14,0], [17,14,0], [16,15,0], [17,20,5], [13,20,5], [14,20,5], [20,20,5], [20,20,5], + [7,10,1], [8,14,5], [9,4,-10], [12,4,-10], [11,3,-10], [12,4,-10], [12,1,-11], [14,5,-10], + [7,5,4], [13,20,5], [15,10,1], [15,10,1], [11,14,3], [20,14,0], [22,16,1], [17,17,2], + [7,3,-5], [8,15,0], [11,7,-7], [17,18,4], [14,16,1], [17,17,2], [17,16,1], [8,7,-7], + [11,20,5], [8,20,5], [12,9,-6], [16,14,2], [5,7,4], [7,2,-3], [5,3,0], [13,20,5], + [12,15,1], [10,14,0], [12,15,1], [12,15,1], [10,18,4], [12,15,1], [12,15,1], [13,15,1], + [12,15,1], [12,15,1], [7,9,0], [7,13,4], [7,15,5], [16,6,-2], [9,15,5], [12,15,0], + [16,16,1], [14,15,0], [15,14,0], [17,16,1], [16,14,0], [15,14,0], [15,14,0], [17,16,1], + [18,14,0], [11,14,0], [13,15,1], [18,14,0], [13,14,0], [21,14,0], [18,14,0], [16,16,1], + [15,14,0], [16,19,4], [15,15,1], [13,16,1], [17,14,0], [18,15,1], [18,15,1], [23,15,1], + [17,14,0], [18,14,0], [15,14,0], [9,20,5], [13,7,-7], [9,20,5], [11,4,-10], [8,3,-11], + [8,7,-7], [11,10,1], [10,15,1], [10,10,1], [12,15,1], [10,10,1], [11,20,5], [10,14,5], + [11,15,1], [7,15,1], [9,19,5], [11,15,1], [7,15,1], [17,10,1], [12,10,1], [11,10,1], + [11,13,4], [10,13,4], [10,10,1], [9,10,1], [8,14,1], [12,10,1], [10,10,1], [14,10,1], + [11,10,1], [11,14,5], [10,10,1], [12,1,-5], [21,1,-5], [12,4,-10], [12,3,-11], [11,3,-11] + ] +}); + +jsMath.Img.AddFont(173,{ + cmr10: [ + [14,17,0], [19,18,0], [18,18,1], [16,18,0], [15,17,0], [18,17,0], [16,17,0], [18,17,0], + [16,17,0], [18,17,0], [17,17,0], [16,17,0], [13,17,0], [13,17,0], [20,17,0], [20,17,0], + [6,11,0], [7,16,5], [8,5,-12], [10,5,-12], [10,4,-12], [10,5,-12], [11,2,-13], [12,6,-12], + [9,6,5], [12,18,1], [17,12,1], [18,12,1], [12,16,3], [21,17,0], [24,18,1], [18,20,2], + [7,4,-6], [5,18,0], [9,8,-9], [19,22,5], [11,20,2], [19,20,2], [18,19,1], [5,8,-9], + [8,24,6], [7,24,6], [11,11,-7], [18,16,2], [5,8,5], [7,2,-4], [5,3,0], [11,24,6], + [12,17,1], [11,16,0], [11,16,0], [11,17,1], [12,17,0], [11,17,1], [11,17,1], [12,18,1], + [11,17,1], [11,17,1], [5,11,0], [5,16,5], [5,18,6], [18,6,-3], [10,17,5], [10,17,0], + [18,18,1], [18,18,0], [16,17,0], [16,18,1], [17,17,0], [16,17,0], [15,17,0], [18,18,1], + [18,17,0], [8,17,0], [12,18,1], [18,17,0], [14,17,0], [22,17,0], [18,17,0], [18,18,1], + [15,17,0], [18,22,5], [18,18,1], [12,18,1], [17,17,0], [18,18,1], [18,18,1], [25,18,1], + [18,17,0], [18,17,0], [14,17,0], [7,24,6], [12,8,-9], [4,24,6], [10,5,-12], [5,4,-13], + [5,8,-9], [12,12,1], [13,18,1], [10,12,1], [13,18,1], [10,12,1], [9,17,0], [12,16,5], + [13,17,0], [6,17,0], [7,22,5], [13,17,0], [7,17,0], [20,11,0], [13,11,0], [12,12,1], + [13,16,5], [13,16,5], [9,11,0], [9,12,1], [8,16,1], [13,12,1], [13,12,1], [17,12,1], + [13,11,0], [13,16,5], [10,11,0], [12,1,-6], [24,1,-6], [11,5,-12], [10,4,-13], [10,4,-13] + ], + cmmi10: [ + [18,17,0], [19,18,0], [18,18,1], [16,18,0], [19,17,0], [22,17,0], [20,17,0], [17,17,0], + [16,17,0], [17,17,0], [19,17,0], [15,12,1], [15,22,5], [14,17,6], [11,19,1], [10,12,1], + [12,22,5], [12,17,6], [11,18,1], [8,12,1], [14,12,1], [14,18,1], [14,17,6], [13,11,0], + [11,22,5], [14,12,1], [13,17,6], [14,12,1], [13,12,1], [13,12,1], [14,22,5], [15,16,5], + [16,22,5], [15,12,1], [11,12,1], [14,18,1], [20,12,1], [13,16,5], [10,14,3], [15,17,6], + [23,8,-5], [23,8,1], [23,8,-5], [23,8,1], [6,7,-5], [6,7,-5], [12,14,1], [12,14,1], + [12,12,1], [11,11,0], [11,11,0], [11,17,6], [12,17,5], [11,17,6], [11,17,1], [12,18,6], + [11,17,1], [11,17,6], [5,3,0], [5,8,5], [17,14,1], [11,24,6], [17,14,1], [12,12,0], + [14,19,1], [18,18,0], [19,17,0], [19,18,1], [20,17,0], [19,17,0], [19,17,0], [19,18,1], + [22,17,0], [12,17,0], [16,18,1], [22,17,0], [16,17,0], [26,17,0], [22,17,0], [18,18,1], + [19,17,0], [18,22,5], [19,18,1], [16,18,1], [17,17,0], [19,18,1], [19,18,1], [26,18,1], + [21,17,0], [19,17,0], [18,17,0], [8,19,1], [8,24,6], [8,24,6], [23,6,-3], [23,7,-3], + [10,18,1], [12,12,1], [10,18,1], [11,12,1], [13,18,1], [11,12,1], [14,22,5], [12,16,5], + [14,18,1], [8,17,1], [11,21,5], [13,18,1], [7,18,1], [21,12,1], [14,12,1], [12,12,1], + [13,16,5], [11,16,5], [11,12,1], [11,12,1], [8,17,1], [14,12,1], [12,12,1], [17,12,1], + [13,12,1], [12,16,5], [12,12,1], [8,12,1], [10,16,5], [15,17,6], [15,6,-12], [16,4,-12] + ], + cmsy10: [ + [17,2,-5], [5,4,-4], [16,12,0], [11,12,0], [18,14,1], [12,12,0], [18,16,0], [18,16,4], + [18,16,2], [18,16,2], [18,16,2], [18,16,2], [18,16,2], [23,24,6], [11,10,-1], [11,10,-1], + [18,12,0], [18,12,0], [17,20,4], [17,20,4], [17,20,4], [17,20,4], [17,20,4], [17,20,4], + [18,6,-3], [18,11,-1], [17,14,1], [17,14,1], [23,16,2], [23,16,2], [17,14,1], [17,14,1], + [23,10,-1], [23,10,-1], [11,22,5], [11,22,5], [23,10,-1], [23,22,5], [23,22,5], [18,12,0], + [23,14,1], [23,14,1], [14,22,5], [14,22,5], [24,14,1], [23,22,5], [23,22,5], [18,12,1], + [7,13,-1], [23,12,1], [14,14,1], [14,14,1], [20,18,0], [20,18,6], [16,24,6], [3,10,-1], + [14,18,1], [12,17,0], [15,7,-2], [11,21,2], [18,19,1], [17,18,1], [18,16,0], [18,16,0], + [14,17,0], [20,20,2], [16,18,1], [13,18,1], [19,17,0], [14,18,1], [20,18,1], [15,20,3], + [20,19,2], [17,17,0], [21,20,3], [18,18,1], [16,18,1], [27,19,2], [25,21,2], [19,18,1], + [18,19,2], [19,20,3], [21,18,1], [16,18,1], [20,18,0], [18,18,1], [16,19,2], [25,19,2], + [20,17,0], [18,21,4], [19,17,0], [15,16,1], [15,16,1], [15,16,1], [15,16,1], [15,16,1], + [14,17,0], [14,17,0], [11,24,6], [7,24,6], [11,24,6], [7,24,6], [11,24,6], [11,24,6], + [8,24,6], [7,24,6], [4,24,6], [9,24,6], [11,26,7], [14,26,7], [11,24,6], [6,16,2], + [21,25,24], [18,17,0], [19,18,1], [12,24,6], [15,15,0], [15,15,0], [18,20,4], [17,20,4], + [9,22,5], [10,23,6], [10,22,5], [14,22,5], [18,22,4], [18,22,4], [18,19,1], [18,22,4] + ], + cmex10: [ + [10,29,28], [8,29,28], [10,29,28], [6,29,28], [11,29,28], [7,29,28], [11,29,28], [7,29,28], + [12,29,28], [12,29,28], [10,29,28], [9,29,28], [5,16,15], [10,16,15], [13,29,28], [13,29,28], + [14,44,43], [10,44,43], [17,58,57], [13,58,57], [13,58,57], [7,58,57], [14,58,57], [8,58,57], + [14,58,57], [8,58,57], [15,58,57], [15,58,57], [16,58,57], [15,58,57], [24,58,57], [24,58,57], + [19,73,72], [14,73,72], [14,73,72], [8,73,72], [16,73,72], [9,73,72], [16,73,72], [9,73,72], + [16,73,72], [16,73,72], [17,73,72], [16,73,72], [30,73,72], [30,73,72], [19,44,43], [19,44,43], + [21,44,43], [14,44,43], [16,44,43], [9,44,43], [16,44,43], [9,44,43], [10,16,15], [9,16,15], + [18,23,22], [13,23,22], [18,23,22], [13,23,22], [13,45,44], [18,45,44], [13,9,8], [9,16,15], + [21,45,43], [14,45,43], [10,16,15], [14,16,15], [13,44,43], [12,44,43], [19,25,24], [26,35,34], + [15,28,27], [23,55,54], [26,25,24], [35,35,34], [26,25,24], [35,35,34], [26,25,24], [35,35,34], + [24,25,24], [22,25,24], [15,28,27], [19,25,24], [19,25,24], [19,25,24], [19,25,24], [19,25,24], + [34,35,34], [30,35,34], [23,55,54], [26,35,34], [26,35,34], [26,35,34], [26,35,34], [26,35,34], + [22,25,24], [30,35,34], [15,5,-13], [26,6,-13], [36,6,-13], [14,4,-14], [24,4,-14], [35,4,-14], + [11,44,43], [6,44,43], [13,44,43], [8,44,43], [13,44,43], [8,44,43], [14,44,43], [14,44,43], + [25,29,28], [25,44,43], [25,58,57], [25,73,72], [18,45,44], [18,16,15], [26,15,14], [13,16,15], + [14,16,15], [14,16,15], [13,9,6], [13,9,6], [13,9,0], [13,9,0], [18,16,15], [18,16,15] + ], + cmbx10: [ + [16,17,0], [22,17,0], [20,18,1], [19,17,0], [18,17,0], [21,17,0], [19,17,0], [20,17,0], + [19,17,0], [20,17,0], [19,17,0], [18,17,0], [15,17,0], [15,17,0], [23,17,0], [23,17,0], + [7,11,0], [9,16,5], [9,5,-12], [11,5,-12], [11,4,-12], [12,5,-12], [12,2,-13], [14,5,-12], + [11,6,5], [14,18,1], [20,12,1], [21,12,1], [14,17,3], [25,17,0], [28,18,1], [20,20,2], + [8,4,-6], [7,17,0], [12,9,-8], [22,22,5], [13,20,2], [22,20,2], [21,18,1], [7,9,-8], + [10,24,6], [9,24,6], [12,11,-7], [20,20,4], [6,9,5], [8,3,-4], [6,4,0], [13,24,6], + [13,17,1], [12,16,0], [13,16,0], [13,17,1], [14,16,0], [13,17,1], [13,17,1], [14,18,1], + [13,17,1], [13,17,1], [6,11,0], [6,16,5], [7,17,5], [20,8,-2], [12,17,5], [12,17,0], + [20,18,1], [20,17,0], [19,17,0], [19,18,1], [20,17,0], [18,17,0], [17,17,0], [21,18,1], + [21,17,0], [10,17,0], [13,18,1], [21,17,0], [16,17,0], [26,17,0], [21,17,0], [20,18,1], + [18,17,0], [20,22,5], [21,18,1], [14,18,1], [19,17,0], [21,18,1], [21,18,1], [28,18,1], + [21,17,0], [21,17,0], [16,17,0], [8,24,6], [14,9,-8], [5,24,6], [11,5,-12], [6,5,-12], + [6,9,-8], [14,12,1], [15,18,1], [12,12,1], [15,18,1], [12,12,1], [11,17,0], [14,16,5], + [15,17,0], [7,17,0], [9,22,5], [15,17,0], [8,17,0], [23,11,0], [15,11,0], [14,12,1], + [15,16,5], [15,16,5], [11,11,0], [10,12,1], [10,17,1], [15,12,1], [14,12,1], [20,12,1], + [15,11,0], [14,16,5], [12,11,0], [14,2,-6], [28,2,-6], [12,6,-12], [12,3,-14], [12,4,-13] + ], + cmti10: [ + [17,17,0], [19,18,0], [19,18,1], [16,18,0], [19,17,0], [21,17,0], [19,17,0], [20,17,0], + [18,17,0], [20,17,0], [19,17,0], [20,22,5], [16,22,5], [17,22,5], [23,22,5], [24,22,5], + [8,12,1], [9,16,5], [11,5,-12], [14,5,-12], [13,4,-12], [14,5,-12], [14,2,-13], [17,6,-12], + [9,6,5], [15,22,5], [18,12,1], [18,12,1], [14,16,3], [23,17,0], [26,18,1], [20,20,2], + [9,4,-6], [9,18,0], [13,8,-9], [20,22,5], [17,18,1], [21,20,2], [20,19,1], [9,8,-9], + [13,24,6], [10,24,6], [14,11,-7], [19,16,2], [6,8,5], [9,2,-4], [6,3,0], [15,24,6], + [14,17,1], [12,16,0], [14,17,1], [14,17,1], [12,21,5], [14,17,1], [14,17,1], [15,17,1], + [14,17,1], [14,17,1], [8,11,0], [8,16,5], [8,18,6], [19,6,-3], [11,18,6], [14,18,0], + [19,18,1], [17,18,0], [18,17,0], [20,18,1], [19,17,0], [18,17,0], [18,17,0], [20,18,1], + [21,17,0], [13,17,0], [15,18,1], [21,17,0], [15,17,0], [25,17,0], [21,17,0], [19,18,1], + [18,17,0], [19,22,5], [18,18,1], [16,18,1], [20,17,0], [21,18,1], [21,18,1], [27,18,1], + [20,17,0], [21,17,0], [17,17,0], [11,24,6], [15,8,-9], [10,24,6], [13,5,-12], [9,4,-13], + [9,8,-9], [13,12,1], [12,18,1], [12,12,1], [14,18,1], [12,12,1], [12,22,5], [12,16,5], + [13,18,1], [8,17,1], [10,21,5], [13,18,1], [8,18,1], [21,12,1], [15,12,1], [13,12,1], + [13,16,5], [12,16,5], [12,12,1], [11,12,1], [9,17,1], [14,12,1], [12,12,1], [17,12,1], + [13,12,1], [13,16,5], [12,12,1], [14,1,-6], [25,1,-6], [14,5,-12], [14,4,-13], [14,4,-13] + ] +}); + +jsMath.Img.AddFont(207,{ + cmr10: [ + [17,20,0], [23,21,0], [21,22,1], [20,21,0], [19,20,0], [21,20,0], [20,20,0], [21,21,0], + [20,20,0], [21,20,0], [20,21,0], [19,21,0], [16,21,0], [16,21,0], [24,21,0], [24,21,0], + [8,13,0], [9,19,6], [9,7,-14], [12,7,-14], [12,5,-14], [12,6,-15], [13,2,-16], [14,6,-15], + [11,7,6], [14,22,1], [21,14,1], [22,14,1], [14,19,3], [26,20,0], [29,22,1], [21,24,2], + [8,4,-8], [6,21,0], [11,10,-11], [23,27,6], [13,24,2], [23,24,2], [22,22,1], [6,10,-11], + [10,30,8], [9,30,8], [13,13,-9], [21,20,3], [6,10,6], [8,3,-5], [6,4,0], [13,30,8], + [14,21,1], [13,20,0], [14,20,0], [14,21,1], [14,20,0], [14,21,1], [14,21,1], [15,21,1], + [14,21,1], [14,21,1], [6,13,0], [6,19,6], [6,22,7], [21,8,-3], [13,21,6], [13,21,0], + [21,22,1], [21,21,0], [19,20,0], [20,22,1], [21,20,0], [19,20,0], [18,20,0], [22,22,1], + [21,20,0], [10,20,0], [14,21,1], [22,20,0], [17,20,0], [26,20,0], [21,20,0], [21,22,1], + [19,20,0], [22,27,6], [22,21,1], [15,22,1], [20,20,0], [21,21,1], [22,21,1], [30,21,1], + [22,20,0], [22,20,0], [17,20,0], [8,30,8], [14,10,-11], [5,30,8], [12,6,-15], [6,4,-16], + [6,10,-11], [15,14,1], [16,22,1], [13,14,1], [16,22,1], [13,14,1], [11,21,0], [15,20,6], + [16,21,0], [8,20,0], [9,26,6], [15,21,0], [8,21,0], [24,13,0], [16,13,0], [14,14,1], + [16,19,6], [16,19,6], [11,13,0], [11,14,1], [10,19,1], [16,14,1], [15,14,1], [21,14,1], + [15,13,0], [15,19,6], [12,13,0], [15,2,-7], [29,2,-7], [13,7,-14], [13,4,-16], [12,4,-16] + ], + cmmi10: [ + [21,20,0], [23,21,0], [22,22,1], [20,21,0], [23,20,0], [26,20,0], [24,20,0], [21,21,0], + [19,20,0], [21,20,0], [23,21,0], [18,14,1], [18,27,6], [16,20,7], [14,22,1], [11,14,1], + [14,27,6], [15,20,7], [14,22,1], [10,14,1], [16,14,1], [16,22,1], [17,20,7], [16,13,0], + [13,27,6], [17,14,1], [15,20,7], [17,14,1], [15,14,1], [16,14,1], [17,27,6], [18,19,6], + [19,27,6], [18,14,1], [13,15,1], [17,22,1], [24,14,1], [15,19,6], [12,17,4], [18,20,7], + [28,9,-6], [28,9,1], [28,9,-6], [28,9,1], [7,8,-6], [7,8,-6], [14,16,1], [14,16,1], + [14,15,1], [13,14,0], [14,14,0], [14,21,7], [14,20,6], [14,21,7], [14,21,1], [15,21,7], + [14,21,1], [14,21,7], [6,4,0], [6,10,6], [21,18,2], [13,30,8], [21,18,2], [15,15,0], + [17,22,1], [21,21,0], [22,20,0], [23,22,1], [24,20,0], [23,20,0], [22,20,0], [23,22,1], + [26,20,0], [15,20,0], [19,21,1], [26,20,0], [19,20,0], [31,20,0], [26,20,0], [22,22,1], + [22,20,0], [22,27,6], [22,21,1], [19,22,1], [21,20,0], [23,21,1], [23,21,1], [31,21,1], + [25,20,0], [23,20,0], [21,20,0], [10,23,1], [9,29,7], [10,28,7], [28,8,-3], [28,9,-3], + [12,22,1], [15,14,1], [13,22,1], [13,14,1], [15,22,1], [13,14,1], [17,27,6], [14,19,6], + [16,22,1], [9,21,1], [13,26,6], [15,22,1], [8,22,1], [25,14,1], [17,14,1], [14,14,1], + [16,19,6], [14,19,6], [13,14,1], [13,14,1], [10,20,1], [16,14,1], [14,14,1], [21,14,1], + [16,14,1], [15,19,6], [14,14,1], [9,14,1], [12,19,6], [18,21,7], [19,7,-14], [19,5,-15] + ], + cmsy10: [ + [21,2,-6], [6,4,-5], [19,15,0], [13,14,0], [21,17,1], [15,15,0], [21,20,0], [21,20,5], + [21,20,3], [21,20,3], [21,20,3], [21,20,3], [21,20,3], [28,28,7], [13,12,-1], [13,12,-1], + [21,15,0], [21,13,-1], [21,23,4], [21,23,4], [21,23,4], [21,23,4], [21,23,4], [21,23,4], + [21,8,-3], [21,13,-1], [21,18,2], [21,18,2], [28,19,2], [28,19,2], [21,18,2], [21,18,2], + [28,11,-2], [28,11,-2], [13,27,6], [13,27,6], [28,11,-2], [28,27,6], [28,27,6], [21,13,-1], + [28,17,1], [28,17,1], [17,27,6], [17,27,6], [28,17,1], [28,27,6], [28,27,6], [21,14,1], + [8,16,-1], [28,14,1], [17,18,2], [17,18,2], [25,21,0], [25,22,7], [19,28,7], [4,12,-1], + [17,22,1], [15,21,0], [18,9,-2], [14,26,3], [21,22,1], [21,22,1], [21,20,0], [21,20,0], + [17,21,0], [24,23,2], [20,22,1], [16,22,1], [23,20,0], [17,22,1], [25,21,1], [18,25,4], + [24,22,2], [20,20,0], [25,24,4], [22,22,1], [20,22,1], [33,23,2], [30,25,2], [23,22,1], + [22,22,2], [23,25,4], [25,21,1], [19,22,1], [24,21,0], [21,21,1], [20,22,2], [31,22,2], + [24,20,0], [21,24,4], [23,20,0], [18,19,1], [18,19,1], [18,19,1], [18,19,1], [18,19,1], + [17,21,0], [17,21,0], [13,30,8], [8,30,8], [13,30,8], [8,30,8], [13,30,8], [13,30,8], + [10,30,8], [9,30,8], [5,30,8], [11,30,8], [13,31,8], [17,31,8], [13,30,8], [7,20,3], + [25,30,28], [21,20,0], [23,21,1], [14,28,7], [18,18,0], [18,18,0], [21,23,4], [21,23,4], + [11,27,6], [12,28,7], [12,27,6], [17,27,6], [22,26,4], [21,27,5], [21,22,1], [21,26,4] + ], + cmex10: [ + [12,36,34], [9,36,34], [12,36,34], [7,36,34], [14,36,34], [8,36,34], [14,36,34], [8,36,34], + [14,36,34], [14,36,34], [12,36,34], [11,36,34], [6,20,19], [12,20,19], [16,36,34], [16,36,34], + [17,54,52], [13,54,52], [21,71,69], [16,71,69], [15,71,69], [9,71,69], [17,71,69], [10,71,69], + [17,71,69], [10,71,69], [18,71,69], [18,71,69], [19,71,69], [19,71,69], [29,71,69], [29,71,69], + [22,88,86], [17,88,86], [17,88,86], [9,88,86], [19,88,86], [11,88,86], [19,88,86], [11,88,86], + [20,88,86], [20,88,86], [21,88,86], [20,88,86], [36,88,86], [36,88,86], [22,54,52], [22,54,52], + [25,54,52], [17,54,52], [20,54,52], [10,54,52], [20,54,52], [10,54,52], [12,19,18], [10,19,18], + [21,28,27], [15,28,27], [21,28,27], [15,28,27], [15,54,53], [21,54,53], [15,10,9], [11,19,18], + [25,54,52], [17,54,52], [12,19,18], [17,19,18], [16,54,52], [15,54,52], [23,30,29], [31,42,41], + [18,34,33], [28,66,65], [31,30,29], [43,42,41], [31,30,29], [43,42,41], [31,30,29], [43,42,41], + [29,30,29], [26,30,29], [18,34,33], [23,30,29], [23,30,29], [23,30,29], [23,30,29], [23,30,29], + [41,42,41], [36,42,41], [28,66,65], [31,42,41], [31,42,41], [31,42,41], [31,42,41], [31,42,41], + [26,30,29], [36,42,41], [18,6,-16], [31,7,-16], [43,7,-16], [17,4,-17], [29,4,-18], [42,4,-18], + [14,54,52], [8,54,52], [15,54,52], [9,54,52], [15,54,52], [9,54,52], [16,54,52], [16,54,52], + [30,36,34], [30,54,52], [30,71,69], [30,88,86], [22,54,53], [22,19,18], [32,19,17], [16,19,18], + [17,19,18], [17,19,18], [15,11,7], [15,11,7], [15,10,0], [15,10,0], [21,19,18], [21,19,18] + ], + cmbx10: [ + [19,20,0], [27,21,0], [25,22,1], [23,21,0], [21,20,0], [25,20,0], [23,20,0], [25,21,0], + [23,20,0], [25,20,0], [23,21,0], [22,21,0], [18,21,0], [18,21,0], [27,21,0], [27,21,0], + [9,14,0], [10,20,6], [10,7,-14], [14,7,-14], [13,4,-15], [14,7,-14], [15,2,-16], [17,6,-15], + [13,7,6], [17,22,1], [24,15,1], [25,15,1], [16,21,4], [30,20,0], [33,22,1], [25,24,2], + [10,4,-8], [8,21,0], [14,12,-9], [26,27,6], [15,24,2], [26,24,2], [25,22,1], [8,12,-9], + [12,30,8], [10,30,8], [15,14,-8], [25,23,4], [8,11,6], [10,3,-5], [7,5,0], [15,30,8], + [16,20,1], [15,19,0], [15,19,0], [16,20,1], [16,20,0], [15,20,1], [16,20,1], [17,21,1], + [16,20,1], [16,20,1], [7,13,0], [7,19,6], [8,21,6], [25,9,-3], [14,21,6], [14,21,0], + [25,22,1], [24,21,0], [22,20,0], [23,22,1], [24,20,0], [21,20,0], [20,20,0], [25,22,1], + [25,20,0], [12,20,0], [16,21,1], [25,20,0], [19,20,0], [31,20,0], [25,20,0], [24,22,1], + [21,20,0], [24,27,6], [25,21,1], [17,22,1], [22,20,0], [25,21,1], [25,21,1], [34,21,1], + [25,20,0], [25,20,0], [19,20,0], [9,30,8], [17,12,-9], [6,30,8], [13,6,-15], [7,6,-15], + [7,12,-9], [17,15,1], [18,22,1], [14,15,1], [18,22,1], [15,15,1], [13,21,0], [17,20,6], + [18,21,0], [9,21,0], [10,27,6], [18,21,0], [9,21,0], [28,14,0], [18,14,0], [16,15,1], + [18,20,6], [18,20,6], [13,14,0], [13,15,1], [12,20,1], [18,15,1], [17,14,1], [24,14,1], + [17,13,0], [17,19,6], [14,13,0], [17,2,-7], [34,2,-7], [15,7,-14], [14,4,-17], [14,6,-15] + ], + cmti10: [ + [21,20,0], [22,21,0], [23,22,1], [19,21,0], [22,20,0], [25,20,0], [23,20,0], [25,21,0], + [22,20,0], [24,20,0], [23,21,0], [23,27,6], [19,27,6], [20,27,6], [28,27,6], [29,27,6], + [10,14,1], [12,19,6], [13,7,-14], [16,7,-14], [16,5,-14], [17,6,-15], [17,2,-16], [20,6,-15], + [10,7,6], [18,27,6], [21,14,1], [21,14,1], [16,20,4], [28,20,0], [31,22,1], [24,24,2], + [10,4,-8], [11,21,0], [15,10,-11], [25,27,6], [21,22,1], [25,24,2], [24,22,1], [11,10,-11], + [15,30,8], [12,30,8], [17,13,-9], [22,19,2], [7,10,6], [10,3,-5], [7,4,0], [18,30,8], + [17,21,1], [14,20,0], [16,21,1], [17,21,1], [14,26,6], [17,21,1], [17,21,1], [19,21,1], + [17,21,1], [17,21,1], [9,13,0], [9,19,6], [10,22,7], [23,8,-3], [13,22,7], [16,21,0], + [23,22,1], [21,21,0], [22,20,0], [24,22,1], [23,20,0], [22,20,0], [22,20,0], [24,22,1], + [25,20,0], [15,20,0], [19,21,1], [25,20,0], [19,20,0], [30,20,0], [25,20,0], [23,22,1], + [22,20,0], [23,27,6], [21,21,1], [19,22,1], [24,20,0], [25,21,1], [26,21,1], [33,21,1], + [24,20,0], [26,20,0], [21,20,0], [13,30,8], [18,10,-11], [12,30,8], [16,6,-15], [11,4,-16], + [11,10,-11], [16,14,1], [14,22,1], [14,14,1], [17,22,1], [14,14,1], [15,27,6], [15,19,6], + [16,22,1], [10,21,1], [13,26,6], [15,22,1], [9,22,1], [25,14,1], [17,14,1], [15,14,1], + [15,19,6], [15,19,6], [15,14,1], [13,14,1], [11,20,1], [17,14,1], [15,14,1], [21,14,1], + [16,14,1], [15,19,6], [14,14,1], [16,2,-7], [31,2,-7], [17,7,-14], [17,4,-16], [16,4,-16] + ] +}); + +jsMath.Img.AddFont(249,{ + cmr10: [ + [20,24,0], [27,25,0], [25,25,1], [23,25,0], [22,24,0], [25,24,0], [23,24,0], [25,24,0], + [23,24,0], [25,24,0], [24,24,0], [22,24,0], [18,24,0], [18,24,0], [28,24,0], [28,24,0], + [9,16,0], [10,23,7], [10,7,-17], [14,7,-17], [13,5,-17], [14,7,-17], [15,2,-19], [16,7,-18], + [13,8,7], [17,25,1], [24,17,1], [26,17,1], [16,23,4], [30,24,0], [34,25,1], [25,28,2], + [9,5,-9], [7,25,0], [12,11,-13], [27,31,7], [16,28,2], [27,28,2], [25,26,1], [7,11,-13], + [12,35,9], [10,35,9], [15,16,-10], [25,23,3], [7,11,7], [10,3,-6], [7,4,0], [16,35,9], + [16,24,1], [15,23,0], [16,23,0], [16,24,1], [17,24,0], [16,24,1], [16,24,1], [17,24,1], + [16,24,1], [16,24,1], [7,15,0], [7,22,7], [7,25,8], [25,9,-4], [15,24,7], [15,24,0], + [25,25,1], [25,25,0], [23,24,0], [23,25,1], [25,24,0], [23,24,0], [21,24,0], [25,25,1], + [25,24,0], [12,24,0], [16,25,1], [26,24,0], [20,24,0], [30,24,0], [25,24,0], [25,25,1], + [22,24,0], [25,31,7], [25,25,1], [17,25,1], [24,24,0], [25,25,1], [25,25,1], [35,25,1], + [25,24,0], [26,24,0], [20,24,0], [9,35,9], [16,11,-13], [6,35,9], [14,6,-18], [7,4,-19], + [7,11,-13], [17,17,1], [18,25,1], [15,17,1], [18,25,1], [15,17,1], [13,24,0], [17,23,7], + [19,24,0], [9,23,0], [10,30,7], [18,24,0], [9,24,0], [28,16,0], [19,16,0], [17,17,1], + [18,23,7], [18,23,7], [13,16,0], [13,17,1], [12,22,1], [19,17,1], [18,16,1], [24,16,1], + [18,15,0], [18,22,7], [14,15,0], [17,2,-8], [34,2,-8], [15,7,-17], [15,4,-19], [14,4,-19] + ], + cmmi10: [ + [25,24,0], [27,25,0], [26,25,1], [23,25,0], [27,24,0], [30,24,0], [28,24,0], [24,24,0], + [22,24,0], [24,24,0], [27,24,0], [21,17,1], [21,31,7], [19,24,8], [16,26,1], [13,16,1], + [17,31,7], [17,24,8], [16,25,1], [12,17,1], [19,17,1], [19,25,1], [20,24,8], [18,16,0], + [16,31,7], [20,16,1], [18,24,8], [20,16,1], [18,16,1], [18,17,1], [20,31,7], [21,23,7], + [22,31,7], [21,17,1], [15,17,1], [20,25,1], [28,16,1], [18,23,7], [14,20,4], [22,24,8], + [33,11,-7], [33,11,1], [33,11,-7], [33,11,1], [8,9,-7], [8,9,-7], [17,19,1], [17,19,1], + [16,17,1], [15,16,0], [16,16,0], [16,24,8], [17,23,7], [16,24,8], [16,24,1], [17,24,8], + [16,24,1], [16,24,8], [7,4,0], [7,11,7], [24,21,2], [16,35,9], [24,21,2], [17,17,0], + [20,26,1], [25,25,0], [26,24,0], [26,25,1], [28,24,0], [27,24,0], [26,24,0], [26,25,1], + [30,24,0], [17,24,0], [22,25,1], [31,24,0], [22,24,0], [36,24,0], [30,24,0], [26,25,1], + [26,24,0], [26,31,7], [26,25,1], [22,25,1], [24,24,0], [26,25,1], [27,25,1], [36,25,1], + [29,24,0], [26,24,0], [25,24,0], [12,27,1], [11,33,8], [12,33,8], [33,9,-4], [33,9,-4], + [14,25,1], [17,17,1], [15,25,1], [15,17,1], [18,25,1], [15,17,1], [19,31,7], [17,23,7], + [19,25,1], [10,24,1], [15,30,7], [18,25,1], [9,25,1], [29,17,1], [20,17,1], [16,17,1], + [19,23,7], [16,23,7], [15,17,1], [15,17,1], [12,23,1], [19,17,1], [16,17,1], [24,17,1], + [18,17,1], [17,23,7], [16,17,1], [10,17,1], [14,23,7], [22,24,8], [22,8,-17], [23,5,-18] + ], + cmsy10: [ + [24,3,-7], [7,5,-6], [22,17,0], [15,15,-1], [25,21,2], [17,17,0], [25,23,0], [25,23,6], + [25,23,3], [25,23,3], [25,23,3], [25,23,3], [25,23,3], [33,33,8], [16,15,-1], [16,15,-1], + [25,17,0], [25,15,-1], [24,27,5], [24,27,5], [24,27,5], [24,27,5], [24,27,5], [24,27,5], + [25,9,-4], [25,16,-1], [24,21,2], [24,21,2], [33,23,3], [33,23,3], [24,21,2], [24,21,2], + [33,13,-2], [33,13,-2], [15,31,7], [15,31,7], [33,13,-2], [33,31,7], [33,31,7], [25,15,-1], + [33,19,1], [33,19,1], [20,31,7], [20,31,7], [33,19,1], [33,31,7], [33,31,7], [25,17,1], + [9,18,-1], [33,17,1], [20,21,2], [20,21,2], [29,25,0], [29,25,8], [22,33,8], [5,13,-2], + [19,25,1], [17,24,0], [21,10,-3], [16,30,3], [25,26,1], [24,25,1], [25,23,0], [25,23,0], + [19,24,0], [28,27,2], [23,25,1], [19,25,1], [27,24,0], [20,25,1], [29,26,2], [21,29,5], + [28,26,2], [23,24,0], [29,29,5], [25,25,1], [23,25,1], [38,26,2], [35,29,2], [27,25,1], + [25,26,2], [27,29,5], [29,25,1], [22,25,1], [28,25,0], [25,25,1], [23,26,2], [36,26,2], + [28,24,0], [25,29,5], [27,24,0], [21,22,1], [21,22,1], [21,22,1], [21,22,1], [21,22,1], + [19,24,0], [19,24,0], [15,35,9], [10,35,9], [15,35,9], [10,35,9], [15,35,9], [15,35,9], + [12,35,9], [10,35,9], [6,35,9], [13,35,9], [15,37,10], [20,37,10], [16,35,9], [8,23,3], + [29,35,33], [25,24,0], [27,26,2], [17,33,8], [21,21,0], [21,21,0], [25,27,5], [24,27,5], + [13,31,7], [14,32,8], [14,31,7], [20,31,7], [26,30,5], [25,31,6], [25,27,2], [25,30,5] + ], + cmex10: [ + [15,42,40], [11,42,40], [14,42,40], [8,42,40], [16,42,40], [10,42,40], [16,42,40], [10,42,40], + [16,42,40], [16,42,40], [14,42,40], [13,42,40], [7,23,22], [14,23,22], [18,42,40], [18,42,40], + [20,62,60], [15,62,60], [24,83,81], [18,83,81], [18,83,81], [10,83,81], [20,83,81], [12,83,81], + [20,83,81], [12,83,81], [22,83,81], [22,83,81], [23,83,81], [22,83,81], [34,83,81], [34,83,81], + [26,103,101], [19,103,101], [20,103,101], [11,103,101], [22,103,101], [13,103,101], [22,103,101], [13,103,101], + [23,103,101], [23,103,101], [24,103,101], [23,103,101], [42,103,101], [42,103,101], [26,62,60], [26,62,60], + [29,63,61], [20,63,61], [23,62,60], [12,62,60], [23,62,60], [12,62,60], [14,22,21], [12,22,21], + [25,32,31], [18,32,31], [25,32,31], [18,32,31], [18,63,62], [25,63,62], [18,12,11], [13,22,21], + [29,62,60], [20,62,60], [14,22,21], [20,22,21], [18,62,60], [17,62,60], [27,35,34], [36,49,48], + [21,39,38], [33,77,76], [36,35,34], [50,49,48], [36,35,34], [50,49,48], [36,35,34], [50,49,48], + [34,35,34], [31,35,34], [21,39,38], [27,35,34], [27,35,34], [27,35,34], [27,35,34], [27,35,34], + [48,49,48], [42,49,48], [33,77,76], [36,49,48], [36,49,48], [36,49,48], [36,49,48], [36,49,48], + [31,35,34], [42,49,48], [21,7,-19], [36,8,-19], [51,8,-19], [19,5,-20], [34,5,-21], [50,5,-21], + [16,62,60], [9,62,60], [18,62,60], [11,62,60], [18,62,60], [11,62,60], [19,62,60], [19,62,60], + [35,42,40], [35,62,60], [35,83,81], [35,103,101], [26,63,62], [26,23,22], [37,22,20], [18,22,21], + [19,22,21], [19,22,21], [17,13,8], [18,13,8], [17,12,0], [18,12,0], [25,22,21], [25,22,21] + ], + cmbx10: [ + [22,24,0], [31,24,0], [29,25,1], [27,24,0], [25,23,0], [30,24,0], [27,24,0], [29,24,0], + [27,24,0], [29,24,0], [27,24,0], [26,24,0], [21,24,0], [21,24,0], [32,24,0], [32,24,0], + [10,16,0], [12,23,7], [12,7,-17], [16,7,-17], [15,6,-17], [16,7,-17], [17,3,-18], [19,6,-18], + [15,8,7], [20,25,1], [28,17,1], [30,17,1], [19,23,4], [35,24,0], [39,25,1], [29,29,3], + [11,5,-9], [9,24,0], [16,13,-11], [31,31,7], [18,28,2], [31,28,2], [29,25,1], [9,13,-11], + [13,35,9], [12,35,9], [17,16,-10], [29,27,5], [9,13,7], [11,5,-5], [9,6,0], [18,35,9], + [18,24,1], [17,23,0], [18,23,0], [18,24,1], [19,23,0], [18,24,1], [18,24,1], [19,24,1], + [18,24,1], [18,24,1], [9,16,0], [9,23,7], [9,24,7], [29,11,-3], [17,24,7], [17,24,0], + [29,25,1], [29,24,0], [26,24,0], [27,25,1], [28,24,0], [25,24,0], [23,24,0], [29,25,1], + [30,24,0], [14,24,0], [18,25,1], [29,24,0], [22,24,0], [36,24,0], [30,24,0], [28,25,1], + [25,24,0], [28,31,7], [30,25,1], [20,25,1], [26,23,0], [29,25,1], [29,25,1], [40,25,1], + [29,24,0], [29,24,0], [22,24,0], [10,35,9], [20,13,-11], [7,35,9], [16,7,-17], [9,6,-18], + [9,13,-11], [19,17,1], [21,25,1], [17,17,1], [21,25,1], [17,17,1], [15,24,0], [19,23,7], + [21,24,0], [10,24,0], [12,31,7], [20,24,0], [10,24,0], [32,16,0], [21,16,0], [19,17,1], + [21,23,7], [21,23,7], [16,16,0], [15,17,1], [13,23,1], [21,17,1], [20,17,1], [28,17,1], + [20,16,0], [20,23,7], [16,16,0], [20,2,-8], [40,2,-8], [17,8,-17], [17,5,-19], [17,6,-18] + ], + cmti10: [ + [25,24,0], [26,25,0], [27,25,1], [22,25,0], [26,24,0], [29,24,0], [27,24,0], [29,24,0], + [25,24,0], [29,24,0], [26,24,0], [27,31,7], [22,31,7], [23,31,7], [33,31,7], [34,31,7], + [12,17,1], [13,23,7], [15,7,-17], [19,7,-17], [19,5,-17], [20,7,-17], [20,2,-19], [23,7,-18], + [12,8,7], [21,31,7], [25,17,1], [25,17,1], [19,23,4], [33,24,0], [36,25,1], [28,29,3], + [12,5,-9], [13,25,0], [18,11,-13], [29,31,7], [24,25,1], [29,28,2], [28,26,1], [13,11,-13], + [18,35,9], [13,35,9], [20,16,-10], [26,21,2], [8,11,7], [12,3,-6], [8,4,0], [21,35,9], + [19,24,1], [16,23,0], [19,24,1], [20,24,1], [17,30,7], [20,24,1], [20,24,1], [22,24,1], + [19,24,1], [19,24,1], [11,15,0], [11,22,7], [11,25,8], [27,9,-4], [16,25,8], [19,25,0], + [27,25,1], [24,25,0], [25,24,0], [28,25,1], [27,24,0], [26,24,0], [25,24,0], [28,25,1], + [29,24,0], [18,24,0], [22,25,1], [30,24,0], [22,24,0], [35,24,0], [29,24,0], [27,25,1], + [25,24,0], [27,31,7], [25,25,1], [22,25,1], [28,24,0], [29,25,1], [30,25,1], [39,25,1], + [29,24,0], [30,24,0], [24,24,0], [16,35,9], [21,11,-13], [14,35,9], [18,6,-18], [13,4,-19], + [13,11,-13], [19,17,1], [16,25,1], [16,17,1], [20,25,1], [16,17,1], [17,31,7], [17,23,7], + [19,25,1], [12,24,1], [15,30,7], [18,25,1], [11,25,1], [29,17,1], [20,17,1], [18,17,1], + [18,23,7], [17,23,7], [17,17,1], [15,17,1], [13,23,1], [20,17,1], [17,17,1], [24,17,1], + [18,17,1], [18,23,7], [16,17,1], [19,2,-8], [36,2,-8], [20,7,-17], [20,4,-19], [19,4,-19] + ] +}); + +jsMath.Img.AddFont(298,{ + cmr10: [ + [24,28,0], [33,30,0], [30,30,1], [28,30,0], [26,28,0], [30,28,0], [28,28,0], [30,29,0], + [28,28,0], [30,28,0], [28,29,0], [26,29,0], [22,29,0], [22,29,0], [33,29,0], [33,29,0], + [11,19,0], [11,28,9], [13,9,-20], [17,9,-20], [16,6,-21], [17,8,-21], [18,3,-22], [20,8,-22], + [16,10,9], [20,30,1], [29,20,1], [31,20,1], [20,27,5], [36,28,0], [41,30,1], [30,34,3], + [11,6,-11], [8,30,0], [15,13,-16], [32,37,8], [19,34,3], [32,34,3], [30,31,1], [9,13,-16], + [14,42,11], [12,42,11], [18,18,-13], [30,28,4], [9,13,8], [12,4,-7], [8,5,0], [19,42,11], + [19,29,1], [18,28,0], [19,28,0], [19,29,1], [20,28,0], [19,29,1], [19,29,1], [20,29,1], + [19,29,1], [19,29,1], [8,18,0], [8,26,8], [8,30,9], [30,11,-5], [18,30,9], [18,29,0], + [30,30,1], [30,30,0], [27,28,0], [28,30,1], [29,28,0], [27,28,0], [26,28,0], [31,30,1], + [30,28,0], [14,28,0], [20,29,1], [31,28,0], [24,28,0], [37,28,0], [30,28,0], [30,30,1], + [26,28,0], [30,37,8], [31,29,1], [21,30,1], [29,28,0], [30,29,1], [30,29,1], [42,29,1], + [30,28,0], [31,28,0], [23,28,0], [11,42,11], [20,13,-16], [7,42,11], [16,7,-22], [8,5,-23], + [8,13,-16], [21,20,1], [22,30,1], [18,20,1], [22,30,1], [18,20,1], [15,29,0], [20,28,9], + [22,29,0], [11,28,0], [11,37,9], [21,29,0], [11,29,0], [34,19,0], [22,19,0], [20,20,1], + [22,27,8], [22,27,8], [15,19,0], [15,20,1], [14,27,1], [22,20,1], [21,19,1], [29,19,1], + [22,18,0], [21,27,9], [17,18,0], [21,2,-10], [41,2,-10], [18,8,-21], [18,5,-23], [17,5,-23] + ], + cmmi10: [ + [30,28,0], [33,30,0], [31,30,1], [28,30,0], [32,28,0], [37,28,0], [34,28,0], [29,29,0], + [27,28,0], [29,28,0], [33,29,0], [25,20,1], [25,37,8], [23,28,9], [19,31,1], [16,19,1], + [20,38,9], [21,28,9], [19,30,1], [14,20,1], [23,20,1], [23,30,1], [24,28,9], [22,19,0], + [19,38,9], [24,19,1], [21,28,9], [24,19,1], [21,19,1], [22,20,1], [24,38,9], [25,28,9], + [27,38,9], [25,20,1], [18,20,1], [23,30,1], [34,19,1], [21,27,8], [17,24,5], [26,28,9], + [39,12,-9], [39,13,1], [39,12,-9], [39,13,1], [10,11,-9], [10,11,-9], [20,22,1], [20,22,1], + [19,20,1], [18,19,0], [19,19,0], [19,28,9], [20,28,8], [19,28,9], [19,29,1], [20,28,9], + [19,29,1], [19,28,9], [8,5,0], [9,13,8], [29,25,2], [19,42,11], [29,25,2], [21,20,0], + [24,31,1], [30,30,0], [31,28,0], [32,30,1], [33,28,0], [32,28,0], [31,28,0], [32,30,1], + [37,28,0], [21,28,0], [26,29,1], [37,28,0], [27,28,0], [43,28,0], [37,28,0], [31,30,1], + [31,28,0], [31,37,8], [31,29,1], [27,30,1], [29,28,0], [32,29,1], [32,29,1], [43,29,1], + [35,28,0], [32,28,0], [30,28,0], [14,32,1], [13,39,9], [14,39,9], [39,11,-5], [39,11,-5], + [17,30,1], [21,20,1], [18,30,1], [18,20,1], [22,30,1], [18,20,1], [23,38,9], [20,28,9], + [23,30,1], [13,29,1], [18,37,9], [21,30,1], [11,30,1], [35,20,1], [24,20,1], [20,20,1], + [23,27,8], [19,27,8], [18,20,1], [18,20,1], [14,27,1], [23,20,1], [20,20,1], [29,20,1], + [22,20,1], [21,28,9], [20,20,1], [13,20,1], [16,28,9], [26,28,9], [26,9,-21], [27,6,-22] + ], + cmsy10: [ + [29,3,-9], [8,5,-8], [26,21,0], [18,19,-1], [30,24,2], [21,21,0], [30,28,0], [30,28,7], + [30,28,4], [30,28,4], [30,28,4], [30,28,4], [30,28,4], [39,39,9], [19,17,-2], [19,17,-2], + [30,20,0], [30,19,-1], [29,33,6], [29,33,6], [29,33,6], [29,33,6], [29,33,6], [29,33,6], + [30,11,-5], [30,18,-2], [29,25,2], [29,25,2], [39,27,3], [39,27,3], [29,25,2], [29,25,2], + [39,16,-2], [39,16,-2], [18,37,8], [18,37,8], [39,16,-2], [39,37,8], [39,38,9], [30,19,-1], + [39,24,2], [39,24,2], [24,37,8], [24,37,8], [40,24,2], [39,37,8], [39,38,9], [30,20,1], + [11,22,-1], [39,20,1], [24,25,2], [24,25,2], [34,30,0], [34,30,9], [27,39,9], [6,16,-2], + [23,30,1], [21,29,0], [26,12,-3], [19,36,4], [30,31,1], [29,30,1], [30,28,0], [30,28,0], + [23,29,0], [33,33,3], [28,30,1], [22,30,1], [32,28,0], [24,30,1], [34,30,2], [25,34,5], + [34,30,2], [28,28,0], [35,33,5], [31,30,1], [27,30,1], [46,32,3], [43,35,3], [32,30,1], + [31,31,3], [33,35,6], [35,29,1], [27,30,1], [33,30,0], [30,30,2], [28,30,2], [43,30,2], + [34,28,0], [30,34,6], [32,28,0], [26,26,1], [26,26,1], [26,26,1], [26,26,1], [26,26,1], + [23,29,0], [23,29,0], [18,42,11], [12,42,11], [18,42,11], [12,42,11], [18,42,11], [18,42,11], + [14,42,11], [12,42,11], [7,42,11], [16,42,11], [18,44,12], [24,44,12], [19,42,11], [10,28,4], + [35,42,40], [30,28,0], [33,30,2], [20,39,9], [25,25,0], [25,25,0], [30,33,6], [29,33,6], + [16,38,9], [16,38,9], [16,38,9], [24,37,8], [31,36,6], [30,37,7], [30,32,2], [30,36,6] + ], + cmex10: [ + [17,50,48], [13,50,48], [17,50,48], [9,50,48], [19,50,48], [12,50,48], [19,50,48], [12,50,48], + [20,50,48], [20,50,48], [17,50,48], [16,50,48], [8,27,26], [17,27,26], [22,50,48], [22,50,48], + [23,75,73], [18,75,73], [29,99,97], [22,99,97], [22,99,97], [12,99,97], [24,99,97], [14,99,97], + [24,99,97], [14,99,97], [26,99,97], [26,99,97], [27,99,97], [26,99,97], [41,99,97], [41,99,97], + [32,124,122], [23,124,122], [24,124,122], [13,124,122], [26,124,122], [15,124,122], [26,124,122], [15,124,122], + [28,124,122], [28,124,122], [29,124,122], [28,124,122], [51,124,122], [51,124,122], [31,75,73], [31,75,73], + [35,75,73], [24,75,73], [28,75,73], [14,75,73], [28,75,73], [14,75,73], [17,26,25], [14,26,25], + [30,39,38], [21,39,38], [30,38,37], [21,38,37], [21,76,75], [30,76,75], [21,14,13], [15,26,25], + [35,76,73], [24,76,73], [17,27,26], [24,27,26], [22,75,73], [21,75,73], [32,42,41], [44,59,58], + [25,47,46], [39,93,92], [44,42,41], [60,59,58], [44,42,41], [60,59,58], [44,42,41], [60,59,58], + [41,42,41], [37,42,41], [25,47,46], [32,42,41], [32,42,41], [32,42,41], [32,42,41], [32,42,41], + [57,59,58], [51,59,58], [39,93,92], [44,59,58], [44,59,58], [44,59,58], [44,59,58], [44,59,58], + [37,42,41], [51,59,58], [24,8,-23], [43,9,-23], [61,9,-23], [23,6,-24], [41,6,-25], [60,6,-25], + [19,75,73], [11,75,73], [21,75,73], [13,75,73], [21,75,73], [13,75,73], [23,75,73], [23,75,73], + [42,50,48], [42,75,73], [42,99,97], [42,124,122], [31,75,74], [31,27,26], [45,26,24], [22,26,25], + [23,26,25], [23,26,25], [20,14,9], [21,14,9], [20,14,0], [21,14,0], [30,26,25], [30,26,25] + ], + cmbx10: [ + [27,28,0], [37,29,0], [34,30,1], [32,29,0], [30,28,0], [36,28,0], [32,29,0], [34,29,0], + [32,29,0], [34,29,0], [32,29,0], [31,29,0], [25,29,0], [25,29,0], [38,29,0], [38,29,0], + [12,19,0], [14,28,9], [14,9,-20], [19,9,-20], [19,6,-21], [20,9,-20], [21,3,-22], [23,8,-21], + [19,10,9], [24,30,1], [33,20,1], [36,20,1], [23,28,5], [42,29,0], [47,30,1], [34,34,3], + [14,6,-11], [11,29,0], [19,15,-14], [37,37,8], [21,34,3], [37,34,3], [35,30,1], [11,15,-14], + [16,42,11], [14,42,11], [21,19,-12], [34,32,6], [11,15,8], [14,5,-7], [10,7,0], [21,42,11], + [22,28,1], [21,27,0], [22,27,0], [22,28,1], [23,27,0], [22,28,1], [22,28,1], [23,29,1], + [22,28,1], [22,28,1], [10,19,0], [10,27,8], [11,30,9], [34,13,-4], [20,30,9], [20,29,0], + [34,30,1], [34,29,0], [31,29,0], [32,30,1], [34,29,0], [30,28,0], [28,28,0], [35,30,1], + [36,29,0], [17,29,0], [22,30,1], [35,29,0], [27,29,0], [44,29,0], [36,29,0], [33,30,1], + [30,29,0], [33,37,8], [36,30,1], [24,30,1], [32,28,0], [35,30,1], [35,30,1], [48,30,1], + [35,29,0], [35,29,0], [27,29,0], [13,42,11], [24,15,-14], [8,42,11], [19,8,-21], [10,7,-22], + [10,15,-14], [23,20,1], [25,30,1], [20,20,1], [25,30,1], [21,20,1], [18,29,0], [23,28,9], + [26,29,0], [12,29,0], [14,38,9], [25,29,0], [13,29,0], [39,19,0], [26,19,0], [23,20,1], + [25,27,8], [25,27,8], [19,19,0], [18,20,1], [16,28,1], [26,20,1], [24,20,1], [33,20,1], + [24,19,0], [24,28,9], [19,19,0], [24,2,-10], [48,2,-10], [21,9,-21], [20,5,-24], [20,7,-22] + ], + cmti10: [ + [29,28,0], [31,30,0], [33,30,1], [27,30,0], [31,28,0], [35,28,0], [33,28,0], [35,29,0], + [30,28,0], [34,28,0], [32,29,0], [34,38,9], [27,38,9], [29,38,9], [40,38,9], [41,38,9], + [14,20,1], [16,28,9], [18,9,-20], [23,9,-20], [23,6,-20], [24,8,-21], [24,3,-22], [28,8,-22], + [14,9,8], [25,38,9], [30,20,1], [30,20,1], [23,28,5], [39,28,0], [44,30,1], [34,34,3], + [15,6,-11], [16,30,0], [21,13,-16], [34,37,8], [29,30,1], [35,34,3], [33,31,1], [16,13,-16], + [22,42,11], [16,42,11], [24,18,-13], [31,26,3], [10,13,8], [14,3,-7], [10,5,0], [26,42,11], + [23,29,1], [19,28,0], [23,29,1], [24,29,1], [20,36,8], [24,29,1], [24,29,1], [26,29,1], + [23,29,1], [23,29,1], [13,18,0], [13,26,8], [14,30,9], [32,11,-5], [19,30,9], [23,30,0], + [33,30,1], [29,30,0], [31,28,0], [34,30,1], [32,28,0], [31,28,0], [31,28,0], [34,30,1], + [35,28,0], [21,28,0], [26,29,1], [36,28,0], [26,28,0], [42,28,0], [35,28,0], [33,30,1], + [30,28,0], [33,37,8], [30,29,1], [26,30,1], [34,28,0], [35,29,1], [36,29,1], [47,29,1], + [34,28,0], [36,28,0], [29,28,0], [19,42,11], [26,13,-16], [16,42,11], [22,8,-21], [15,5,-23], + [15,13,-16], [22,20,1], [19,30,1], [20,20,1], [23,30,1], [20,20,1], [21,38,9], [20,28,9], + [22,30,1], [14,28,1], [17,36,9], [21,30,1], [13,30,1], [35,20,1], [25,20,1], [21,20,1], + [21,27,8], [21,27,8], [21,20,1], [18,20,1], [16,27,1], [23,20,1], [21,20,1], [29,20,1], + [22,20,1], [22,28,9], [20,20,1], [23,2,-10], [43,2,-10], [24,9,-20], [24,5,-23], [23,5,-23] + ] +}); + +jsMath.Img.AddFont(358,{ + cmr10: [ + [29,34,0], [39,36,0], [36,37,2], [33,36,0], [31,34,0], [36,34,0], [33,34,0], [36,35,0], + [33,34,0], [36,34,0], [34,35,0], [31,35,0], [26,35,0], [26,35,0], [40,35,0], [40,35,0], + [13,22,0], [13,33,11], [15,11,-24], [20,11,-24], [19,7,-25], [20,9,-25], [22,2,-27], [24,10,-26], + [18,11,10], [24,36,1], [34,23,1], [37,23,1], [23,32,5], [43,34,0], [49,37,2], [36,40,3], + [13,7,-13], [10,36,0], [17,15,-19], [39,44,10], [22,40,3], [39,40,3], [36,38,2], [11,15,-19], + [17,50,13], [15,50,13], [22,22,-15], [36,34,5], [10,16,10], [14,3,-9], [10,6,0], [22,50,13], + [23,35,2], [21,33,0], [22,33,0], [23,35,2], [24,34,0], [22,35,2], [23,35,2], [24,36,2], + [23,35,2], [23,35,2], [10,22,0], [10,32,10], [10,36,11], [36,12,-6], [21,36,11], [21,35,0], + [36,36,1], [36,36,0], [32,34,0], [33,37,2], [35,34,0], [32,34,0], [30,34,0], [37,37,2], + [36,34,0], [17,34,0], [23,36,2], [37,34,0], [29,34,0], [44,34,0], [36,34,0], [36,37,2], + [31,34,0], [36,45,10], [36,36,2], [25,37,2], [34,34,0], [36,36,2], [36,36,2], [50,36,2], + [36,34,0], [37,34,0], [28,34,0], [13,50,13], [23,15,-19], [8,50,13], [19,8,-26], [10,6,-27], + [10,15,-19], [25,23,1], [26,35,1], [21,23,1], [26,35,1], [21,23,1], [18,35,0], [24,34,11], + [27,34,0], [13,33,0], [13,44,11], [26,34,0], [13,34,0], [40,22,0], [27,22,0], [24,23,1], + [26,32,10], [26,32,10], [18,22,0], [18,23,1], [17,32,1], [27,23,1], [25,23,1], [35,23,1], + [26,22,0], [25,33,11], [20,22,0], [25,2,-12], [49,2,-12], [21,10,-25], [21,5,-28], [20,6,-27] + ], + cmmi10: [ + [36,34,0], [39,36,0], [37,37,2], [33,36,0], [39,34,0], [44,34,0], [40,34,0], [35,35,0], + [32,34,0], [34,34,0], [39,35,0], [30,23,1], [29,45,10], [27,33,11], [23,36,1], [19,23,1], + [24,46,11], [25,33,11], [23,36,1], [16,23,1], [27,23,1], [27,35,1], [29,33,11], [26,22,0], + [22,46,11], [28,23,1], [25,33,11], [28,23,1], [26,23,1], [26,23,1], [29,45,11], [30,33,11], + [32,45,11], [30,23,1], [22,25,2], [28,36,1], [41,23,1], [25,32,10], [21,28,6], [31,33,11], + [47,15,-11], [47,15,1], [47,15,-11], [47,15,1], [11,12,-11], [11,12,-11], [24,26,1], [24,26,1], + [23,25,2], [21,23,0], [22,23,0], [23,34,11], [24,33,10], [22,34,11], [23,35,2], [24,34,11], + [23,35,2], [23,34,11], [10,6,0], [10,16,10], [34,29,2], [22,50,13], [34,29,2], [25,24,0], + [28,38,2], [36,36,0], [38,34,0], [38,37,2], [40,34,0], [38,34,0], [37,34,0], [38,37,2], + [44,34,0], [25,34,0], [32,36,2], [44,34,0], [32,34,0], [52,34,0], [44,34,0], [37,37,2], + [37,34,0], [37,45,10], [37,36,2], [32,37,2], [35,34,0], [38,36,2], [38,36,2], [52,36,2], + [42,34,0], [38,34,0], [36,34,0], [17,39,2], [16,47,11], [17,47,11], [47,13,-6], [47,13,-6], + [20,36,1], [25,23,1], [21,35,1], [22,23,1], [26,35,1], [22,23,1], [28,46,11], [24,33,11], + [27,35,1], [15,34,1], [21,44,11], [25,35,1], [13,35,1], [42,23,1], [28,23,1], [23,23,1], + [27,32,10], [23,32,10], [22,23,1], [21,23,1], [17,32,1], [27,23,1], [23,23,1], [34,23,1], + [26,23,1], [25,33,11], [23,23,1], [15,23,1], [19,33,11], [31,34,11], [31,10,-25], [32,7,-26] + ], + cmsy10: [ + [34,3,-11], [10,6,-9], [31,25,0], [22,22,-1], [36,28,2], [24,24,0], [36,33,0], [36,34,9], + [36,34,5], [36,34,5], [36,34,5], [36,34,5], [36,34,5], [47,47,11], [22,20,-2], [22,20,-2], + [36,24,0], [36,22,-1], [34,39,7], [34,39,7], [34,39,7], [34,39,7], [34,39,7], [34,39,7], + [36,12,-6], [36,22,-2], [34,29,2], [34,29,2], [47,32,4], [47,32,4], [34,29,2], [34,29,2], + [47,18,-3], [47,18,-3], [21,44,10], [21,44,10], [47,18,-3], [47,45,10], [47,44,10], [36,22,-1], + [47,28,2], [47,28,2], [29,44,10], [29,44,10], [48,28,2], [47,45,10], [47,44,10], [36,23,1], + [13,26,-2], [47,23,1], [29,29,2], [29,29,2], [41,36,0], [41,36,11], [32,47,11], [7,19,-3], + [28,36,2], [25,34,0], [30,14,-4], [23,42,4], [35,38,2], [34,36,1], [36,33,0], [36,33,0], + [28,34,0], [40,39,3], [33,37,2], [27,37,2], [38,34,0], [28,37,2], [41,36,2], [30,41,6], + [41,37,3], [34,34,0], [42,40,6], [36,37,2], [33,37,2], [55,38,3], [50,41,3], [39,37,2], + [36,37,3], [39,42,7], [42,36,2], [32,37,2], [40,36,0], [35,36,2], [33,37,3], [51,37,3], + [40,34,0], [36,41,7], [38,34,0], [30,32,2], [30,32,2], [30,32,2], [30,32,2], [30,32,2], + [28,34,0], [28,34,0], [21,50,13], [14,50,13], [21,50,13], [14,50,13], [21,50,13], [21,50,13], + [17,50,13], [14,50,13], [8,50,13], [18,50,13], [21,52,14], [29,52,14], [22,50,13], [11,34,5], + [42,50,48], [35,34,0], [39,36,2], [24,47,11], [30,30,0], [30,30,0], [35,39,7], [34,39,7], + [19,46,11], [19,46,11], [19,46,11], [29,44,10], [37,43,7], [36,44,8], [36,38,2], [36,43,7] + ], + cmex10: [ + [21,59,57], [15,59,57], [20,59,57], [11,59,57], [22,59,57], [14,59,57], [22,59,57], [14,59,57], + [23,59,57], [23,59,57], [20,59,57], [19,59,57], [10,33,31], [21,33,31], [26,59,57], [26,59,57], + [28,89,87], [21,89,87], [35,118,116], [26,118,116], [26,118,116], [14,118,116], [28,118,116], [17,118,116], + [28,118,116], [17,118,116], [31,118,116], [31,118,116], [32,118,116], [31,118,116], [49,118,116], [49,118,116], + [38,147,145], [28,147,145], [28,147,145], [16,147,145], [31,147,145], [18,147,145], [31,147,145], [18,147,145], + [33,147,145], [33,147,145], [35,148,146], [33,148,146], [60,147,145], [60,147,145], [37,89,87], [37,89,87], + [42,89,87], [29,89,87], [33,89,87], [17,89,87], [33,89,87], [17,89,87], [20,31,30], [17,31,30], + [36,46,45], [25,46,45], [36,46,45], [25,46,45], [25,90,89], [36,90,89], [25,17,16], [18,31,30], + [42,90,87], [29,90,87], [20,31,30], [29,31,30], [26,89,87], [25,89,87], [39,50,49], [52,70,69], + [30,56,55], [47,110,109], [52,50,49], [72,70,69], [52,50,49], [72,70,69], [52,50,49], [72,70,69], + [49,50,49], [44,50,49], [30,56,55], [39,50,49], [39,50,49], [39,50,49], [39,50,49], [39,50,49], + [68,70,69], [60,70,69], [47,110,109], [52,70,69], [52,70,69], [52,70,69], [52,70,69], [52,70,69], + [44,50,49], [60,70,69], [29,10,-27], [51,10,-28], [72,10,-28], [28,7,-29], [49,7,-30], [71,7,-30], + [23,89,87], [12,89,87], [25,89,87], [15,89,87], [25,89,87], [15,89,87], [27,89,87], [27,89,87], + [50,59,57], [50,89,87], [50,118,116], [50,148,146], [37,90,89], [37,32,31], [53,31,29], [26,31,30], + [28,31,30], [28,31,30], [25,17,11], [25,17,11], [25,17,0], [25,17,0], [36,31,30], [36,31,30] + ], + cmbx10: [ + [32,34,0], [45,35,0], [41,36,1], [38,35,0], [36,34,0], [43,34,0], [38,34,0], [41,35,0], + [38,34,0], [41,34,0], [39,35,0], [37,35,0], [30,35,0], [30,35,0], [46,35,0], [46,35,0], + [15,23,0], [17,33,10], [17,11,-24], [23,11,-24], [22,7,-25], [23,10,-24], [25,3,-27], [28,9,-26], + [22,11,10], [28,36,1], [40,24,1], [43,24,1], [27,34,6], [50,34,0], [56,36,1], [41,40,3], + [16,7,-13], [13,35,0], [23,18,-16], [44,44,10], [25,40,3], [44,40,3], [41,36,1], [13,18,-16], + [19,50,13], [17,50,13], [25,22,-15], [41,39,7], [13,18,10], [16,6,-8], [12,8,0], [25,50,13], + [26,34,1], [25,33,0], [26,33,0], [26,34,1], [27,33,0], [26,34,1], [26,34,1], [28,35,1], + [26,34,1], [26,34,1], [12,22,0], [12,32,10], [13,36,11], [41,15,-5], [24,35,10], [24,35,0], + [41,36,1], [41,35,0], [37,34,0], [38,36,1], [41,34,0], [36,34,0], [34,34,0], [42,36,1], + [43,34,0], [20,34,0], [26,35,1], [42,34,0], [32,34,0], [52,34,0], [43,34,0], [40,36,1], + [36,34,0], [40,45,10], [43,35,1], [29,36,1], [38,34,0], [42,35,1], [42,35,1], [58,35,1], + [41,34,0], [42,34,0], [32,34,0], [15,50,13], [28,18,-16], [10,50,13], [22,9,-25], [12,9,-26], + [12,18,-16], [28,24,1], [30,35,1], [24,24,1], [30,35,1], [25,24,1], [22,35,0], [28,33,10], + [31,34,0], [15,35,0], [17,45,10], [29,34,0], [15,34,0], [46,23,0], [31,23,0], [27,24,1], + [30,33,10], [30,33,10], [22,23,0], [21,24,1], [19,33,1], [31,24,1], [29,23,1], [40,23,1], + [29,22,0], [29,32,10], [23,22,0], [29,3,-12], [57,3,-12], [25,10,-25], [24,6,-28], [24,9,-26] + ], + cmti10: [ + [35,34,0], [37,36,0], [39,37,2], [32,36,0], [37,34,0], [42,34,0], [39,34,0], [41,35,0], + [36,34,0], [41,34,0], [38,35,0], [40,46,11], [32,46,11], [34,46,11], [47,46,11], [49,46,11], + [17,23,1], [18,33,11], [22,11,-24], [27,11,-24], [27,7,-24], [28,9,-25], [28,2,-27], [33,10,-26], + [17,11,10], [30,46,11], [36,23,1], [36,23,1], [27,33,6], [47,34,0], [52,37,2], [41,40,3], + [17,7,-13], [19,36,0], [26,15,-19], [41,44,10], [35,36,1], [42,40,3], [40,38,2], [19,15,-19], + [26,50,13], [19,50,13], [29,22,-15], [37,31,3], [11,16,10], [17,3,-9], [11,6,0], [31,50,13], + [28,35,2], [23,33,0], [27,35,2], [28,35,2], [24,43,10], [28,35,2], [28,35,2], [31,35,2], + [28,35,2], [28,35,2], [15,22,0], [15,32,10], [16,36,11], [39,12,-6], [22,36,11], [27,36,0], + [39,36,1], [34,36,0], [36,34,0], [40,37,2], [38,34,0], [37,34,0], [36,34,0], [40,37,2], + [42,34,0], [25,34,0], [31,36,2], [43,34,0], [31,34,0], [50,34,0], [42,34,0], [39,37,2], + [36,34,0], [39,45,10], [36,36,2], [31,37,2], [40,34,0], [42,36,2], [43,36,2], [56,36,2], + [41,34,0], [43,34,0], [35,34,0], [22,50,13], [30,15,-19], [19,50,13], [26,8,-26], [18,6,-27], + [18,15,-19], [27,23,1], [23,35,1], [24,23,1], [28,35,1], [23,23,1], [25,46,11], [24,33,11], + [27,35,1], [17,34,1], [20,44,11], [25,35,1], [15,35,1], [42,23,1], [29,23,1], [25,23,1], + [25,32,10], [25,32,10], [24,23,1], [21,23,1], [19,32,1], [28,23,1], [25,23,1], [35,23,1], + [26,23,1], [26,33,11], [23,23,1], [27,2,-12], [51,2,-12], [29,11,-24], [29,6,-27], [27,6,-27] + ] +}); + +jsMath.Img.AddFont(430,{ + cmr10: [ + [35,41,0], [47,43,0], [43,44,2], [39,43,0], [37,40,0], [43,41,0], [40,41,0], [43,42,0], + [40,41,0], [43,41,0], [40,42,0], [38,42,0], [32,42,0], [32,42,0], [48,42,0], [48,42,0], + [15,27,0], [16,40,13], [18,12,-30], [24,12,-30], [23,8,-30], [24,11,-30], [26,3,-32], [28,12,-31], + [22,13,12], [28,43,1], [41,28,1], [45,28,1], [28,39,7], [52,41,0], [59,44,2], [43,48,4], + [16,8,-16], [12,43,0], [21,18,-23], [46,53,12], [27,49,4], [46,49,4], [43,45,2], [13,18,-23], + [20,60,15], [18,60,15], [26,27,-18], [43,40,5], [12,19,12], [17,4,-11], [12,7,0], [27,60,15], + [28,42,2], [25,40,0], [27,40,0], [27,42,2], [28,40,0], [27,42,2], [27,42,2], [29,42,2], + [27,42,2], [27,42,2], [12,26,0], [12,38,12], [12,43,13], [43,15,-7], [25,43,13], [25,42,0], + [43,43,1], [43,43,0], [39,41,0], [40,44,2], [42,41,0], [39,41,0], [36,41,0], [44,44,2], + [43,41,0], [20,41,0], [28,43,2], [44,41,0], [35,41,0], [52,41,0], [43,41,0], [43,44,2], + [37,41,0], [43,54,12], [44,43,2], [30,44,2], [41,40,0], [43,43,2], [44,43,2], [60,43,2], + [43,41,0], [44,41,0], [34,41,0], [16,60,15], [28,18,-23], [10,60,15], [23,10,-31], [12,7,-33], + [12,18,-23], [30,28,1], [31,42,1], [25,28,1], [32,42,1], [25,28,1], [22,42,0], [29,40,13], + [32,41,0], [15,40,0], [16,53,13], [31,41,0], [16,41,0], [48,27,0], [32,27,0], [28,28,1], + [31,39,12], [32,39,12], [22,27,0], [22,28,1], [20,38,1], [32,28,1], [30,27,1], [42,27,1], + [31,26,0], [30,39,13], [24,26,0], [30,2,-15], [59,2,-15], [25,12,-30], [25,7,-33], [24,7,-33] + ], + cmmi10: [ + [43,41,0], [47,43,0], [44,44,2], [40,43,0], [46,40,0], [52,41,0], [48,41,0], [42,42,0], + [38,41,0], [41,41,0], [47,42,0], [36,28,1], [35,54,12], [33,40,13], [27,43,1], [23,27,1], + [28,55,13], [30,40,13], [27,43,1], [20,28,1], [33,28,1], [33,42,1], [34,40,13], [31,27,0], + [27,55,13], [34,27,1], [30,40,13], [34,27,1], [31,27,1], [31,28,1], [34,54,13], [36,40,13], + [38,54,13], [36,28,1], [26,29,2], [34,43,1], [49,27,1], [30,39,12], [25,34,7], [37,40,13], + [56,18,-13], [56,17,1], [56,18,-13], [56,17,1], [14,15,-13], [14,15,-13], [28,31,1], [28,31,1], + [28,29,2], [25,27,0], [27,27,0], [27,40,13], [28,40,12], [27,40,13], [27,42,2], [29,41,13], + [27,42,2], [27,40,13], [12,7,0], [12,19,12], [41,35,3], [27,60,15], [41,35,3], [30,29,0], + [34,45,2], [43,43,0], [45,41,0], [45,44,2], [48,41,0], [46,41,0], [45,41,0], [45,44,2], + [52,41,0], [30,41,0], [38,43,2], [53,41,0], [38,41,0], [62,41,0], [52,41,0], [44,44,2], + [45,41,0], [44,54,12], [45,43,2], [39,44,2], [42,40,0], [45,43,2], [46,43,2], [62,43,2], + [51,41,0], [45,41,0], [43,41,0], [20,47,2], [19,56,13], [20,56,13], [56,15,-7], [56,16,-7], + [24,43,1], [30,28,1], [25,42,1], [26,28,1], [31,42,1], [26,28,1], [33,55,13], [28,40,13], + [33,42,1], [18,40,1], [25,52,13], [30,42,1], [16,42,1], [51,28,1], [34,28,1], [28,28,1], + [31,39,12], [27,39,12], [26,28,1], [25,28,1], [20,38,1], [33,28,1], [28,28,1], [41,28,1], + [32,28,1], [29,40,13], [28,28,1], [18,28,1], [23,40,13], [37,40,13], [37,13,-30], [39,9,-31] + ], + cmsy10: [ + [41,3,-13], [12,7,-11], [38,29,0], [26,26,-2], [43,34,2], [29,29,0], [43,40,0], [43,40,10], + [43,40,5], [43,40,5], [43,40,5], [43,40,5], [43,40,5], [56,56,13], [27,24,-3], [27,24,-3], + [43,29,0], [43,26,-2], [41,47,9], [41,47,9], [41,47,9], [41,47,9], [41,47,9], [41,47,9], + [43,15,-7], [43,26,-3], [41,35,3], [41,35,3], [56,38,4], [56,38,4], [41,35,3], [41,35,3], + [56,22,-4], [56,22,-4], [26,53,12], [26,53,12], [56,22,-4], [56,54,12], [56,53,12], [43,26,-2], + [56,33,2], [56,33,2], [35,53,12], [35,53,12], [57,33,2], [56,54,12], [56,53,12], [43,28,1], + [16,31,-2], [56,28,1], [35,35,3], [35,35,3], [49,43,0], [49,43,13], [38,56,13], [8,23,-3], + [33,43,2], [30,41,0], [36,16,-5], [27,51,5], [43,45,2], [41,43,1], [43,40,0], [43,40,0], + [33,41,0], [48,46,3], [40,44,2], [32,44,2], [46,41,0], [34,44,2], [49,43,2], [36,50,8], + [49,44,3], [40,41,0], [50,49,8], [44,44,2], [39,44,2], [66,45,3], [60,49,3], [46,44,2], + [44,44,3], [47,50,8], [50,43,2], [38,44,2], [48,43,0], [42,43,2], [39,44,3], [62,44,3], + [48,41,0], [43,49,8], [46,41,0], [36,38,2], [36,38,2], [36,38,2], [36,38,2], [36,38,2], + [33,41,0], [33,41,0], [25,60,15], [16,60,15], [25,60,15], [16,60,15], [26,60,15], [26,60,15], + [20,60,15], [17,60,15], [10,60,15], [22,60,15], [26,63,17], [35,63,17], [27,60,15], [14,40,5], + [51,60,57], [43,41,0], [47,43,2], [28,56,13], [36,36,0], [36,36,0], [43,47,9], [41,47,9], + [23,55,13], [23,55,13], [23,55,13], [35,53,12], [45,51,8], [43,53,10], [43,45,2], [43,51,8] + ], + cmex10: [ + [25,72,69], [18,72,69], [24,72,69], [13,72,69], [27,72,69], [16,72,69], [27,72,69], [16,72,69], + [28,72,69], [28,72,69], [24,72,69], [22,72,69], [12,39,37], [25,39,37], [31,72,69], [31,72,69], + [34,107,104], [25,107,104], [42,143,140], [32,143,140], [31,143,140], [17,143,140], [34,143,140], [20,143,140], + [34,143,140], [20,143,140], [37,143,140], [37,143,140], [39,143,140], [37,143,140], [59,143,140], [59,143,140], + [45,178,175], [33,178,175], [34,178,175], [19,178,175], [37,178,175], [22,178,175], [37,178,175], [22,178,175], + [39,178,175], [39,178,175], [42,178,175], [40,178,175], [73,178,175], [73,178,175], [45,107,104], [45,107,104], + [50,108,105], [35,108,105], [39,107,104], [21,107,104], [39,107,104], [21,107,104], [24,37,36], [21,37,36], + [43,55,54], [30,55,54], [43,55,54], [30,55,54], [30,108,107], [43,108,107], [30,20,19], [21,37,36], + [50,107,104], [35,107,104], [24,37,36], [35,37,36], [31,107,104], [30,107,104], [46,60,59], [63,84,83], + [36,67,66], [56,133,132], [63,60,59], [86,84,83], [63,60,59], [86,84,83], [63,60,59], [86,84,83], + [59,60,59], [53,60,59], [36,67,66], [46,60,59], [46,60,59], [46,60,59], [46,60,59], [46,60,59], + [82,84,83], [73,84,83], [56,133,132], [63,84,83], [63,84,83], [63,84,83], [63,84,83], [63,84,83], + [53,60,59], [73,84,83], [35,11,-33], [61,13,-33], [87,13,-33], [33,8,-35], [59,9,-36], [86,9,-36], + [27,107,104], [15,107,104], [31,107,104], [18,107,104], [31,107,104], [18,107,104], [33,107,104], [33,107,104], + [61,72,69], [61,107,104], [61,143,140], [61,178,175], [44,109,107], [44,39,37], [64,38,35], [31,37,36], + [33,37,36], [33,37,36], [30,21,13], [29,21,13], [30,20,0], [29,20,0], [43,37,36], [43,37,36] + ], + cmbx10: [ + [38,41,0], [54,42,0], [49,43,1], [46,42,0], [43,40,0], [51,41,0], [46,41,0], [49,42,0], + [46,41,0], [49,41,0], [46,42,0], [45,42,0], [36,42,0], [36,42,0], [55,42,0], [55,42,0], + [17,27,0], [20,39,12], [20,12,-30], [27,12,-30], [27,9,-30], [28,12,-29], [30,4,-32], [33,11,-31], + [26,13,12], [34,43,1], [48,28,1], [51,28,1], [32,40,7], [60,41,0], [68,43,1], [49,49,4], + [19,8,-16], [15,42,0], [28,21,-20], [53,53,12], [31,49,4], [53,49,4], [50,43,1], [15,21,-20], + [23,60,15], [20,60,15], [30,27,-18], [49,46,8], [15,22,12], [19,6,-10], [14,10,0], [31,60,15], + [32,40,1], [30,39,0], [31,39,0], [32,40,1], [32,39,0], [31,40,1], [32,40,1], [33,41,1], + [32,40,1], [32,40,1], [14,27,0], [15,39,12], [15,43,13], [49,18,-6], [29,42,12], [29,42,0], + [49,43,1], [49,42,0], [45,41,0], [46,43,1], [49,41,0], [43,41,0], [40,41,0], [50,43,1], + [51,41,0], [24,41,0], [32,42,1], [51,41,0], [38,41,0], [63,41,0], [51,41,0], [48,43,1], + [43,41,0], [48,54,12], [51,42,1], [34,43,1], [45,40,0], [50,42,1], [50,42,1], [69,42,1], + [50,41,0], [51,41,0], [39,41,0], [18,60,15], [34,21,-20], [12,60,15], [27,10,-31], [14,10,-31], + [14,21,-20], [33,28,1], [36,42,1], [29,28,1], [36,42,1], [30,28,1], [26,42,0], [33,39,12], + [37,41,0], [17,41,0], [20,53,12], [35,41,0], [18,41,0], [56,27,0], [37,27,0], [32,28,1], + [36,39,12], [36,39,12], [27,27,0], [25,28,1], [23,39,1], [37,28,1], [35,28,1], [48,28,1], + [35,27,0], [35,39,12], [28,27,0], [34,3,-15], [68,3,-15], [29,12,-30], [29,7,-34], [28,9,-32] + ], + cmti10: [ + [42,41,0], [45,43,0], [47,44,2], [38,43,0], [45,40,0], [51,41,0], [47,41,0], [50,42,0], + [44,41,0], [49,41,0], [45,42,0], [47,55,13], [38,55,13], [40,55,13], [57,55,13], [58,55,13], + [20,28,1], [22,40,13], [26,13,-29], [33,13,-29], [32,9,-29], [34,11,-30], [34,3,-32], [40,12,-31], + [20,13,12], [37,55,13], [43,28,1], [43,28,1], [33,39,7], [57,41,0], [63,44,2], [49,48,4], + [21,8,-16], [23,43,0], [31,18,-23], [49,53,12], [42,43,1], [50,49,4], [48,45,2], [22,18,-23], + [31,60,15], [23,60,15], [35,27,-18], [45,37,4], [14,19,12], [20,4,-11], [14,7,0], [37,60,15], + [33,42,2], [28,40,0], [33,42,2], [34,42,2], [28,52,12], [34,42,2], [34,42,2], [37,42,2], + [33,42,2], [33,42,2], [18,26,0], [18,38,12], [19,43,13], [46,15,-7], [27,43,13], [33,43,0], + [47,43,1], [41,43,0], [44,41,0], [48,44,2], [46,41,0], [44,41,0], [44,41,0], [48,44,2], + [51,41,0], [30,41,0], [37,43,2], [51,41,0], [37,41,0], [60,41,0], [51,41,0], [47,44,2], + [44,41,0], [47,54,12], [43,43,2], [38,44,2], [48,40,0], [51,43,2], [52,43,2], [67,43,2], + [49,41,0], [52,41,0], [42,41,0], [27,60,15], [36,18,-23], [23,60,15], [31,10,-31], [22,7,-33], + [22,18,-23], [32,28,1], [28,42,1], [28,28,1], [34,42,1], [28,28,1], [29,55,13], [29,40,13], + [32,42,1], [20,40,1], [25,52,13], [30,42,1], [19,42,1], [50,28,1], [35,28,1], [31,28,1], + [31,39,12], [30,39,12], [29,28,1], [25,28,1], [22,38,1], [34,28,1], [30,28,1], [42,28,1], + [31,28,1], [31,40,13], [28,28,1], [33,2,-15], [62,2,-15], [34,13,-29], [34,7,-33], [33,7,-33] + ] +}); diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/font.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/font.js new file mode 100644 index 0000000..51f0a2f --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/font.js @@ -0,0 +1,1677 @@ +jsMath.Img.AddFont(50,{ + cmr10: [ + [4,5,0], [6,5,0], [5,6,1], [5,5,0], [5,5,0], [5,5,0], [5,5,0], [5,5,0], + [5,5,0], [5,5,0], [5,5,0], [5,5,0], [4,5,0], [4,5,0], [6,5,0], [6,5,0], + [2,3,0], [3,5,2,1], [2,2,-3], [2,2,-3,-1], [2,2,-3,-1], [3,2,-3], [3,2,-3], [2,2,-3,-2], + [2,2,2,-1], [4,5,0], [5,4,0], [6,4,0], [4,5,1], [6,5,0], [7,6,1], [5,6,1], + [2,1,-2], [2,5,0], [3,2,-3], [6,7,2], [4,6,1], [6,7,1], [5,6,1], [2,2,-3], + [3,7,2], [2,7,2], [3,4,-2], [5,5,1], [2,2,1], [2,1,-1], [2,1,0], [3,7,2], + [4,6,1], [3,5,0], [4,5,0], [4,6,1], [4,5,0], [4,6,1], [4,6,1], [4,6,1], + [4,6,1], [4,6,1], [2,3,0], [2,4,1], [2,6,2], [5,3,0], [3,6,2], [3,5,0], + [5,5,0], [5,5,0], [5,5,0], [5,6,1], [5,5,0], [5,5,0], [5,5,0], [5,6,1], + [5,5,0], [3,5,0], [3,6,1], [5,5,0], [4,5,0], [6,5,0], [5,5,0], [5,6,1], + [5,5,0], [5,7,2], [5,6,1], [4,6,1], [5,5,0], [5,6,1], [5,5,0], [7,5,0], + [7,5,0,2], [5,5,0], [4,5,0], [2,8,2], [3,3,-2,-1], [2,8,2], [2,1,-4,-1], [2,1,-4], + [2,3,-2], [4,4,0], [4,5,0], [3,4,0], [4,5,0], [3,4,0], [3,5,0], [4,5,2], + [4,5,0], [2,5,0], [3,7,2,1], [4,5,0], [2,5,0], [6,3,0], [4,3,0], [4,4,0], + [4,5,2], [4,5,2], [3,3,0], [3,4,0], [3,5,0], [4,3,0], [4,3,0], [5,3,0], + [4,3,0], [4,5,2], [3,3,0], [4,1,-1], [7,1,-1], [2,2,-3,-1], [3,1,-4], [3,1,-4], + [3,11,20,28,37,45,54,63,71,80,88,97,105,114,122,131], + [9,17,26,34,42,51,59,67], + [141,73] + ], + cmmi10: [ + [5,5,0], [6,5,0], [6,6,1], [5,5,0], [6,5,0], [6,5,0], [6,5,0], [5,5,0], + [5,5,0], [5,5,0], [6,5,0], [5,3,0], [4,6,1], [4,5,2], [3,5,0], [3,3,0], + [4,7,2], [4,5,2], [4,5,0], [3,3,0], [4,3,0], [4,5,0], [4,5,2], [4,3,0], + [3,7,2], [4,3,0], [4,5,2], [4,3,0], [4,3,0], [4,3,0], [4,7,2], [4,5,2], + [5,7,2], [5,3,0], [3,5,1], [4,5,0], [6,3,0], [4,5,2], [3,4,1], [5,5,2], + [7,3,-1], [9,2,0,2], [7,3,-1], [9,2,0,2], [4,3,-1,2], [2,3,-1], [4,4,0], [4,4,0], + [4,5,1], [3,3,0], [4,4,0], [4,6,2], [4,6,2], [3,5,2], [4,6,1], [4,5,2], + [4,6,1], [4,6,2], [2,1,0], [2,2,1], [5,5,1], [3,7,2], [5,5,1], [4,4,0], + [4,6,1], [5,5,0], [6,5,0], [6,6,1], [6,5,0], [6,5,0], [6,5,0], [6,6,1], + [6,5,0], [4,5,0], [5,6,1], [6,5,0], [5,5,0], [7,5,0], [8,5,0,2], [6,6,1], + [6,5,0], [6,7,2], [6,6,1], [5,6,1], [5,5,0], [6,6,1], [6,5,0], [7,5,0], + [8,5,0,2], [6,5,0], [5,5,0], [3,5,0], [3,7,2], [3,7,2], [7,2,-1], [9,2,-1,2], + [3,5,0], [4,3,0], [3,5,0], [3,3,0], [4,5,0], [3,3,0], [4,7,2], [4,5,2], + [4,5,0], [2,5,0], [3,7,2], [4,5,0], [2,5,0], [6,3,0], [4,3,0], [4,3,0], + [4,5,2], [3,5,2], [3,3,0], [3,3,0], [3,5,0], [4,3,0], [4,3,0], [5,3,0], + [4,3,0], [4,5,2], [3,3,0], [2,3,0], [3,5,2], [5,5,2], [4,2,-3,-1], [3,1,-4,-2], + [3,11,19,28,36,44,53,61,69,77,86,94,102,111,119,127], + [9,17,26,34,42,51,59,67], + [137,73] + ], + cmsy10: [ + [5,1,-1], [2,1,-1], [4,4,0,-1], [3,4,0], [5,5,1], [4,4,0], [5,5,0], [5,5,1], + [5,5,1], [5,5,1], [5,5,1], [5,5,1], [5,5,1], [7,7,2], [3,4,0], [3,4,0], + [5,4,0], [5,4,0], [5,6,1], [5,6,1], [5,6,1], [5,6,1], [5,6,1], [5,6,1], + [5,2,-1], [5,4,0], [5,5,1], [5,5,1], [7,5,1], [7,5,1], [5,5,1], [5,5,1], + [7,3,0], [7,3,0], [3,7,2], [3,7,2], [7,3,0], [7,7,2], [7,7,2], [5,4,0], + [7,4,0], [7,4,0], [4,7,2], [4,7,2], [7,4,0], [7,7,2], [7,7,2], [5,3,0], + [2,4,0], [7,3,0], [4,5,1], [4,5,1], [6,5,0], [6,6,2], [4,7,2,-1], [1,3,0], + [4,5,0], [4,5,0], [5,3,0], [4,7,1], [5,6,1], [5,5,0], [5,5,0], [5,5,0], + [4,5,0], [6,6,1], [5,6,1], [4,6,1], [6,5,0], [4,6,1], [6,6,1], [5,6,1], + [6,6,1], [5,5,0], [6,6,1], [5,6,1], [5,6,1], [8,6,1], [9,7,1,2], [6,6,1], + [6,6,1], [6,6,1], [6,6,1], [5,6,1], [6,5,0], [6,6,1,1], [5,6,1], [8,6,1], + [6,5,0], [5,6,1], [6,5,0], [5,5,1], [5,5,0], [5,5,1], [5,4,0], [5,4,0], + [4,5,0], [4,5,0], [2,8,2,-1], [2,8,2], [2,8,2,-1], [2,8,2], [3,8,2], [3,8,2], + [3,8,2], [2,8,2], [2,7,2], [3,8,2], [3,8,2], [4,8,2], [3,8,2], [2,5,1], + [6,8,7], [5,5,0], [6,6,1], [4,7,2], [5,4,0], [5,5,0], [5,6,1], [5,6,1], + [3,7,2], [3,7,2], [3,7,2], [4,7,2], [6,6,1], [5,6,1], [5,6,1], [5,6,1], + [3,13,23,33,43,53,63,73,83,93,103,113,123,133,142,152], + [9,24,38,52,66,80,95,109], + [164,121] + ], + cmex10: [ + [6,9,8,3], [3,9,8], [2,10,9,-1], [2,10,9], [2,10,9,-1], [2,10,9], [2,9,8,-1], [2,9,8], + [2,9,8,-1], [2,9,8,-1], [3,9,8], [3,9,8], [1,5,5,-1], [2,5,5,-1], [4,9,8], [4,9,8], + [7,14,13,3], [3,14,13], [4,18,17,-1], [4,18,17], [3,18,17,-1], [2,18,17], [3,18,17,-1], [3,18,17], + [3,18,17,-1], [3,18,17], [4,18,17,-1], [4,18,17,-1], [4,18,17,-1], [5,18,17], [7,18,17], [7,18,17], + [9,22,21,3], [4,22,21], [3,22,21,-1], [3,22,21], [4,22,21,-1], [3,22,21], [4,22,21,-1], [3,22,21], + [4,22,21,-1], [4,22,21,-1], [4,22,21,-1], [5,22,21], [9,22,21], [9,22,21], [6,14,13], [6,14,13], + [9,14,13,3], [5,14,13], [3,14,13,-2], [3,14,13], [3,14,13,-2], [3,14,13], [1,5,5,-2], [2,5,5,-1], + [3,7,7,-2], [3,7,7,-1], [3,7,7,-2], [3,7,7,-1], [3,13,13,-1], [3,13,13,-2], [2,3,3,-2], [1,5,5,-2], + [9,14,13,3], [5,14,13], [1,5,5,-2], [2,5,5,-3], [4,14,13], [4,14,13], [6,7,7], [8,10,10], + [5,8,8], [7,16,16], [8,7,7], [11,10,10], [11,7,7,3], [11,10,10], [11,7,7,3], [11,10,10], + [10,8,7,3], [7,7,7], [5,8,8], [6,7,7], [6,7,7], [6,7,7], [6,7,7], [6,7,7], + [10,10,10], [9,10,10], [7,16,16], [8,10,10], [8,10,10], [8,10,10], [8,10,10], [8,10,10], + [10,8,7,3], [9,10,10], [4,1,-4], [7,2,-4], [10,2,-4], [4,1,-4], [7,2,-4], [10,2,-4], + [6,19,13,3], [2,14,13], [3,14,13,-1], [3,14,13], [3,14,13,-1], [3,14,13], [3,14,13,-1], [3,14,13,-1], + [10,9,8,3], [6,13,13,-1], [6,17,17,-1], [6,21,21,-1], [5,13,13,-1], [2,5,5,-4], [4,5,4,-4], [3,5,5,-1], + [3,5,5,-1], [4,4,4], [5,3,2,1], [4,3,2], [4,3,0], [4,3,0], [5,5,5], [5,4,4], + [3,16,28,41,53,66,78,91,103,116,129,141,154,166,179,191], + [11,42,72,103,134,165,196,226], + [205,256] + ], + cmbx10: [ + [5,5,0], [7,5,0], [6,5,0], [6,5,0], [5,5,0], [6,5,0], [6,5,0], [6,5,0], + [6,5,0], [6,5,0], [6,5,0], [6,5,0], [5,5,0], [5,5,0], [7,5,0], [7,5,0], + [2,4,0], [3,6,2,1], [3,2,-3], [3,2,-3,-1], [2,2,-3,-1], [4,2,-3], [4,2,-3], [2,2,-3,-2], + [2,2,2,-1], [4,5,0], [6,4,0], [6,4,0], [4,5,1], [7,5,0], [8,6,1], [6,6,1], + [3,1,-2], [2,5,0], [4,3,-2], [7,7,2], [4,6,1], [7,7,1], [6,5,0], [2,3,-2], + [3,8,2], [3,8,2], [4,4,-2], [6,6,1], [2,2,1], [3,1,-1], [2,1,0], [4,8,2], + [4,5,0], [4,5,0], [4,5,0], [4,5,0], [4,5,0], [4,5,0], [4,5,0], [4,5,0], + [4,5,0], [4,5,0], [2,3,0], [2,4,1], [2,6,2], [6,3,0], [4,6,2], [4,5,0], + [6,5,0], [6,5,0], [6,5,0], [6,5,0], [6,5,0], [5,5,0], [5,5,0], [6,5,0], + [6,5,0], [3,5,0], [4,6,1], [6,5,0], [5,5,0], [8,5,0], [6,5,0], [6,5,0], + [5,5,0], [6,7,2], [6,5,0], [4,5,0], [6,5,0], [6,5,0], [6,5,0], [8,5,0], + [6,5,0], [6,5,0], [5,5,0], [2,8,2], [3,3,-2,-1], [2,8,2], [2,2,-3,-1], [2,2,-3], + [2,3,-2], [4,4,0], [5,5,0], [4,4,0], [5,5,0], [4,4,0], [3,5,0], [4,6,2], + [5,5,0], [2,5,0], [3,7,2,1], [4,5,0], [2,5,0], [7,4,0], [5,4,0], [4,4,0], + [5,6,2], [5,6,2], [3,4,0], [3,4,0], [3,5,0], [5,4,0], [4,4,0], [6,4,0], + [4,4,0], [4,6,2], [4,4,0], [4,1,-1], [8,1,-1], [3,2,-3,-1], [4,1,-4], [4,2,-3], + [3,13,23,33,42,52,62,72,82,92,102,111,121,131,141,151], + [9,17,26,34,42,51,59,67], + [162,73] + ], + cmti10: [ + [5,5,0], [6,5,0], [5,6,1,-1], [5,5,0], [6,5,0], [6,5,0], [6,5,0], [5,5,0,-1], + [5,5,0,-1], [5,5,0,-1], [6,5,0], [6,7,2], [5,7,2], [5,7,2], [7,7,2], [9,7,2,2], + [3,3,0], [4,5,2,1], [1,2,-3,-2], [2,2,-3,-2], [2,2,-3,-2], [2,2,-3,-2], [2,2,-3,-2], [2,2,-3,-3], + [2,2,2,-1], [4,7,2], [5,3,0], [5,3,0], [4,5,1], [7,5,0], [6,6,1,-1], [8,6,1,2], + [3,1,-2], [3,5,0], [3,2,-3,-1], [5,7,2,-1], [5,5,0], [5,7,1,-1], [6,6,1], [2,2,-3,-1], + [3,7,2,-1], [3,7,2], [3,3,-2,-1], [5,5,1,-1], [2,3,2], [3,1,-1], [2,1,0], [5,8,2], + [4,6,1], [3,5,0,-1], [4,6,1], [4,6,1], [4,7,2], [4,6,1], [4,6,1], [4,5,0,-1], + [4,6,1], [4,6,1], [2,3,0], [2,5,2], [3,6,2], [5,3,0,-1], [3,6,2], [3,5,0,-1], + [5,5,0,-1], [5,5,0], [6,5,0], [5,6,1,-1], [6,5,0], [6,5,0], [6,5,0], [5,6,1,-1], + [6,5,0], [4,5,0], [5,6,1], [6,5,0], [5,5,0], [7,5,0], [6,5,0], [5,6,1,-1], + [5,5,0], [5,7,2,-1], [5,6,1], [5,6,1], [5,5,0,-1], [5,6,1,-1], [5,5,0,-1], [7,5,0,-1], + [8,5,0,2], [5,5,0,-1], [5,5,0], [3,8,2], [2,3,-2,-2], [3,8,2], [2,1,-4,-2], [2,1,-4,-1], + [2,3,-2,-1], [4,3,0], [4,5,0], [4,3,0], [4,5,0], [4,3,0], [4,7,2], [4,5,2], + [4,5,0], [3,5,0], [4,7,2,1], [4,5,0], [2,5,0], [6,3,0], [4,3,0], [4,3,0], + [4,5,2], [4,5,2], [4,3,0], [3,3,0], [3,5,0], [4,3,0], [4,3,0], [5,3,0], + [4,3,0], [4,5,2], [3,3,0], [3,1,-1,-1], [6,1,-1,-1], [6,4,-1,2], [2,1,-4,-2], [2,1,-4,-2], + [3,11,20,28,37,45,54,62,71,79,88,96,105,113,122,130], + [9,17,26,34,42,51,59,67], + [140,73] + ] +}); + +jsMath.Img.AddFont(60,{ + cmr10: [ + [5,6,0], [7,6,0], [6,7,1], [6,6,0], [5,6,0], [6,6,0], [6,6,0], [6,6,0], + [6,6,0], [6,6,0], [6,6,0], [5,6,0], [4,6,0], [4,6,0], [7,6,0], [7,6,0], + [2,4,0], [3,6,2,1], [2,2,-4,-1], [2,2,-4,-1], [2,1,-4,-1], [4,2,-4], [4,1,-4], [2,2,-4,-2], + [2,2,2,-1], [4,6,0], [6,5,1], [6,4,0], [4,5,1], [7,6,0], [8,7,1], [6,7,1], + [2,1,-2], [2,6,0], [3,3,-3], [6,8,2], [4,7,1], [7,7,1], [6,7,1], [2,3,-3], + [3,8,2], [3,8,2], [4,4,-2], [6,6,1], [2,3,2], [3,1,-1], [2,1,0], [4,8,2], + [4,7,1], [4,6,0], [4,6,0], [4,7,1], [4,6,0], [4,7,1], [4,7,1], [4,7,1], + [4,7,1], [4,7,1], [2,4,0], [2,6,2], [2,6,2], [6,2,-1], [4,6,2], [4,6,0], + [6,7,1], [6,6,0], [6,6,0], [6,7,1], [6,6,0], [6,6,0], [5,6,0], [6,7,1], + [6,6,0], [3,6,0], [4,7,1], [6,6,0], [5,6,0], [7,6,0], [6,6,0], [6,7,1], + [5,6,0], [6,8,2], [6,7,1], [4,7,1], [6,6,0], [6,7,1], [6,6,0], [8,6,0], + [6,6,0], [6,6,0], [5,6,0], [2,8,2], [3,3,-3,-1], [2,8,2], [2,2,-4,-1], [2,2,-4], + [2,3,-3], [4,5,1], [5,7,1], [4,4,0], [4,6,0], [4,4,0], [3,6,0], [4,6,2], + [5,6,0], [2,6,0], [3,8,2,1], [4,6,0], [2,6,0], [7,4,0], [5,4,0], [4,4,0], + [5,6,2], [4,6,2], [3,4,0], [3,5,1], [3,5,0], [5,4,0], [4,4,0], [6,4,0], + [4,4,0], [4,6,2], [4,4,0], [4,1,-2], [8,1,-2], [3,2,-4,-1], [4,2,-4], [2,2,-4,-1], + [3,14,24,34,44,55,65,75,85,95,106,116,126,136,147,157], + [11,21,31,41,51,61,71,81], + [169,87] + ], + cmmi10: [ + [6,6,0], [7,6,0], [6,7,1], [6,6,0], [7,6,0], [7,6,0], [7,6,0], [6,6,0], + [5,6,0], [6,6,0], [7,6,0], [5,5,1], [5,8,2], [5,6,2], [4,6,0], [3,4,0], + [4,8,2], [4,6,2], [4,6,0], [3,4,0], [5,4,0], [5,6,0], [5,6,2], [5,4,0], + [4,8,2], [5,4,0], [4,6,2], [5,5,1], [4,4,0], [5,4,0], [5,8,2], [5,6,2], + [5,8,2], [5,4,0], [4,5,1], [5,6,0], [7,4,0], [4,6,2], [4,5,1], [5,6,2], + [8,3,-1], [8,3,0], [8,3,-1], [8,3,0], [2,3,-1], [2,3,-1], [4,4,0], [4,4,0], + [4,5,1], [3,4,0,-1], [4,4,0], [4,6,2], [4,6,2], [4,6,2], [4,7,1], [4,6,2], + [4,7,1], [4,6,2], [2,1,0], [2,3,2], [6,6,1], [4,8,2], [6,6,1], [4,4,0], + [5,7,1], [6,6,0], [6,6,0], [6,7,1], [7,6,0], [6,6,0], [6,6,0], [6,7,1], + [7,6,0], [4,6,0], [5,7,1], [7,6,0], [5,6,0], [9,6,0], [9,6,0,2], [6,7,1], + [6,6,0], [6,8,2], [6,7,1], [6,7,1], [6,6,0], [6,7,1], [6,6,0], [9,6,0], + [9,6,0,2], [6,6,0], [6,6,0], [3,6,0], [3,8,2], [3,8,2], [8,2,-1], [8,2,-1], + [4,6,0], [4,4,0], [4,6,0], [4,5,1], [4,6,0], [4,4,0], [5,8,2], [4,6,2], + [5,6,0], [3,6,0], [3,8,2], [4,6,0], [2,6,0], [7,4,0], [5,4,0], [4,5,1], + [4,6,2], [4,6,2], [4,4,0], [4,5,1], [3,5,0], [5,4,0], [4,4,0], [6,4,0], + [5,4,0], [4,6,2], [4,4,0], [3,4,0], [3,6,2], [5,6,2], [4,2,-4,-1], [4,2,-4,-2], + [3,13,23,33,43,53,63,73,83,93,103,113,123,133,143,153], + [11,21,31,41,51,61,71,81], + [164,87] + ], + cmsy10: [ + [5,2,-1,-1], [2,2,-1], [4,4,0,-1], [4,4,0], [6,6,1], [4,4,0], [6,6,0], [6,6,2], + [6,6,1], [6,6,1], [6,6,1], [6,6,1], [6,6,1], [8,8,2], [4,4,0], [4,4,0], + [6,4,0], [6,4,0], [6,8,2], [6,8,2], [6,7,2], [6,7,2], [6,7,2], [6,7,2], + [6,2,-1], [6,4,0], [6,6,1], [6,6,1], [8,6,1], [8,6,1], [5,6,1,-1], [6,6,1], + [8,4,0], [8,4,0], [4,8,2], [4,8,2], [8,4,0], [8,8,2], [8,8,2], [6,4,0], + [8,6,1], [8,6,1], [5,8,2], [5,8,2], [8,6,1], [8,8,2], [8,8,2], [6,4,0], + [2,5,0], [8,4,0], [5,6,1], [5,6,1], [7,6,0], [7,6,2], [4,8,2,-1], [1,4,0], + [5,6,0], [4,6,0], [5,3,0], [4,7,1], [6,7,1], [6,7,1], [6,6,0], [6,6,0], + [5,6,0], [7,7,1], [6,7,1], [5,7,1], [7,6,0], [5,7,1], [7,7,1], [5,7,1], + [7,7,1], [5,6,0], [7,7,1], [6,7,1], [5,7,1], [9,7,1], [9,8,1,1], [7,7,1], + [6,7,1], [6,7,1,-1], [7,7,1], [6,7,1], [7,6,0], [7,7,1,1], [6,7,1], [9,7,1], + [7,6,0], [6,7,1], [6,6,0], [5,6,1], [5,5,0], [5,6,1], [5,5,0], [5,5,0], + [5,6,0], [5,6,0], [3,8,2,-1], [3,8,2], [3,8,2,-1], [3,8,2], [3,8,2,-1], [3,8,2], + [2,8,2,-1], [3,8,2], [1,8,2,-1], [2,8,2,-1], [4,8,2], [5,8,2], [4,8,2], [2,6,1], + [7,9,8], [6,6,0], [7,7,1], [4,8,2], [5,5,0], [5,5,0], [6,8,2], [6,8,2], + [3,8,2], [3,8,2], [3,8,2], [5,8,2], [6,7,1], [6,8,2], [6,7,1], [6,7,1], + [3,15,27,39,51,63,75,87,99,111,123,135,147,159,171,183], + [11,28,45,62,80,97,114,131], + [196,145] + ], + cmex10: [ + [3,10,9,-1], [3,11,10], [2,11,10,-1], [2,11,10], [3,11,10,-1], [3,10,10], [3,11,10,-1], [3,10,9], + [3,11,10,-1], [3,11,10,-1], [3,9,9], [3,11,10], [1,5,5,-1], [3,5,5,-1], [4,10,10], [4,10,9], + [4,15,14,-1], [4,15,14], [5,20,19,-1], [5,20,19], [2,20,19,-2], [3,20,19], [3,20,19,-2], [3,20,19], + [3,20,19,-2], [3,20,19], [4,20,19,-1], [4,20,19,-1], [5,20,19,-1], [5,20,19], [8,20,19], [8,20,19], + [5,25,24,-1], [5,25,24], [3,25,24,-2], [3,25,24], [3,25,24,-2], [3,25,24], [3,25,24,-2], [3,25,24], + [5,25,24,-1], [5,25,24,-1], [5,25,24,-1], [5,25,24,-1], [10,25,24], [10,25,24], [6,15,14], [6,15,14], + [5,16,15,-2], [5,16,15], [4,15,14,-2], [3,15,14], [4,16,15,-2], [3,16,15], [2,5,5,-2], [1,5,5,-2], + [3,8,8,-3], [3,8,8,-1], [3,9,8,-3], [3,9,8,-1], [3,16,15,-1], [3,16,15,-3], [1,4,3,-3], [1,5,5,-2], + [5,15,14,-2], [5,15,14], [2,5,5,-2], [2,5,5,-3], [4,15,14,-1], [4,15,14], [7,8,8], [9,12,12], + [5,9,9], [8,18,18], [9,8,8], [12,12,12], [9,8,8], [12,12,12], [9,8,8], [12,12,12], + [8,8,8], [7,8,8], [5,9,9], [7,8,8], [7,8,8], [7,8,8], [7,8,8], [7,8,8], + [11,12,12], [10,12,12], [8,18,18], [9,12,12], [9,12,12], [9,12,12], [9,12,12], [9,12,12], + [7,8,8], [10,12,12], [5,2,-4], [8,2,-4], [12,3,-4], [5,1,-5], [8,1,-5], [12,1,-5], + [3,16,15,-1], [2,16,15], [3,15,15,-1], [3,16,15], [3,15,14,-1], [3,15,14], [4,15,14,-1], [4,15,14,-1], + [7,10,10,-1], [7,14,14,-1], [7,19,19,-1], [7,24,24,-1], [5,15,15,-1], [1,5,5,-5], [4,6,5,-5], [3,5,5,-2], + [4,5,5,-1], [4,5,5,-1], [5,3,2,1], [5,3,2,1], [5,3,0,1], [5,3,0,1], [6,5,5], [6,5,5], + [4,19,34,49,64,79,94,109,124,139,154,169,184,199,215,230], + [13,50,87,124,161,198,235,272], + [246,308] + ], + cmbx10: [ + [5,6,0], [7,6,0], [7,7,1], [6,6,0], [6,6,0], [7,6,0], [6,6,0], [7,6,0], + [7,6,0], [7,6,0], [7,6,0], [6,6,0], [5,6,0], [5,6,0], [8,6,0], [8,6,0], + [3,4,0], [4,6,2,1], [2,2,-4,-1], [2,2,-4,-2], [3,2,-4,-1], [3,2,-4,-1], [4,1,-4], [3,2,-4,-2], + [3,2,2,-1], [5,6,0], [7,4,0], [7,4,0], [5,6,1], [8,6,0], [9,7,1], [7,7,1], + [3,2,-2], [2,6,0], [4,4,-2], [7,8,2], [4,7,1], [8,7,1], [7,7,1], [2,3,-3], + [3,8,2], [3,8,2], [4,4,-2], [7,6,1], [2,4,2], [3,2,-1], [2,2,0], [4,8,2], + [5,6,0], [4,6,0], [5,6,0], [5,7,1], [5,6,0], [5,6,0], [5,7,1], [5,6,0], + [5,7,1], [5,6,0], [2,4,0], [2,6,2], [2,6,2], [7,4,0], [4,6,2], [4,6,0], + [7,6,0], [7,6,0], [6,6,0], [7,7,1], [7,6,0], [6,6,0], [6,6,0], [7,7,1], + [7,6,0], [4,6,0], [5,7,1], [7,6,0], [6,6,0], [9,6,0], [7,6,0], [7,7,1], + [6,6,0], [7,8,2], [7,7,1], [5,7,1], [6,6,0], [7,7,1], [7,6,0], [10,6,0], + [7,6,0], [7,6,0], [6,6,0], [2,8,2,-1], [4,4,-2,-1], [2,8,2], [3,2,-4,-1], [2,2,-4], + [2,4,-2], [5,4,0], [5,6,0], [4,4,0], [5,6,0], [4,4,0], [4,6,0], [5,6,2], + [5,6,0], [3,6,0], [4,8,2,1], [5,6,0], [3,6,0], [8,4,0], [5,4,0], [5,4,0], + [5,6,2], [5,6,2], [4,4,0], [4,4,0], [3,5,0], [5,4,0], [5,4,0], [7,4,0], + [5,4,0], [5,6,2], [4,4,0], [5,1,-2], [9,1,-2], [3,2,-4,-1], [3,2,-4,-1], [3,2,-4,-1], + [3,15,27,39,51,63,75,86,98,110,122,134,146,157,169,181], + [11,21,31,41,51,61,71,81], + [194,87] + ], + cmti10: [ + [6,6,0], [6,6,0], [6,7,1,-1], [5,6,0], [6,6,0], [7,6,0], [7,6,0], [6,6,0,-1], + [5,6,0,-1], [6,6,0,-1], [6,6,0], [7,8,2,1], [6,8,2,1], [6,8,2,1], [9,8,2,1], [9,8,2,1], + [3,4,0], [4,6,2,1], [2,2,-4,-2], [3,2,-4,-2], [3,1,-4,-2], [3,2,-4,-2], [3,1,-4,-2], [3,2,-4,-3], + [2,2,2,-1], [6,8,2,1], [6,4,0], [6,4,0], [4,5,1], [8,6,0], [8,7,1,-1], [9,7,1,2], + [3,1,-2], [2,6,0,-1], [3,3,-3,-1], [6,8,2,-1], [6,6,0], [6,7,1,-1], [6,7,1,-1], [1,3,-3,-2], + [3,8,2,-1], [3,8,2], [4,4,-2,-1], [5,6,1,-1], [2,3,2], [3,1,-1], [1,1,0,-1], [5,8,2], + [4,7,1,-1], [3,6,0,-1], [5,7,1], [5,7,1], [4,8,2], [5,7,1], [4,7,1,-1], [4,7,1,-1], + [5,7,1], [5,7,1], [2,4,0,-1], [3,6,2], [3,6,2], [6,2,-1,-1], [4,6,2], [4,6,0,-1], + [6,7,1,-1], [6,6,0], [6,6,0], [6,7,1,-1], [7,6,0], [6,6,0], [6,6,0], [6,7,1,-1], + [7,6,0], [4,6,0], [5,7,1], [7,6,0], [5,6,0], [8,6,0], [7,6,0], [6,7,1,-1], + [6,6,0], [6,8,2,-1], [6,7,1], [5,7,1], [6,6,0,-1], [6,7,1,-1], [6,6,0,-1], [8,6,0,-1], + [9,6,0,2], [6,6,0,-1], [6,6,0], [4,8,2], [3,3,-3,-2], [3,8,2], [2,2,-4,-2], [1,2,-4,-2], + [2,3,-3,-1], [5,4,0], [3,6,0,-1], [4,4,0], [5,6,0], [4,4,0], [5,8,2,1], [4,6,2], + [5,6,0], [3,6,0], [4,8,2,1], [4,6,0], [3,6,0], [7,4,0], [5,4,0], [4,4,0], + [4,6,2], [4,6,2], [4,4,0], [4,5,1], [3,5,0], [5,4,0], [4,4,0], [6,4,0], + [4,4,0], [4,6,2], [4,4,0], [4,1,-2,-1], [7,1,-2,-1], [3,2,-4,-2], [3,2,-4,-2], [3,2,-4,-2], + [3,14,24,34,44,54,64,75,85,95,105,115,126,136,146,156], + [11,21,31,41,51,61,71,81], + [168,87] + ] +}); + +jsMath.Img.AddFont(70,{ + cmr10: [ + [6,7,0], [8,7,0], [8,8,1], [7,7,0], [7,7,0], [7,7,0], [7,7,0], [8,7,0], + [7,7,0], [7,7,0], [7,7,0], [7,7,0], [6,7,0], [6,7,0], [8,7,0], [8,7,0], + [3,5,0], [4,7,2,1], [2,2,-5,-1], [2,2,-5,-2], [3,2,-5,-1], [3,2,-5,-1], [5,1,-5], [3,3,-5,-2], + [3,2,2,-1], [5,7,0], [7,6,1], [8,6,1], [5,7,1], [9,7,0], [10,8,1], [8,9,1], + [3,2,-2], [2,8,0], [4,3,-4], [8,9,2], [5,9,1], [8,9,1], [8,9,1], [2,3,-4], + [3,10,2,-1], [3,10,2], [5,5,-3], [8,7,1], [2,3,2], [3,2,-1], [2,1,0], [5,10,2], + [5,8,1], [3,7,0,-1], [5,7,0], [5,8,1], [5,7,0], [5,8,1], [5,8,1], [5,8,1], + [5,10,1], [5,10,1], [2,5,0], [2,7,2], [2,7,2], [8,3,-1], [5,7,2], [5,9,0], + [8,8,1], [7,7,0], [7,7,0], [7,8,1], [7,7,0], [7,7,0], [6,7,0], [8,8,1], + [7,7,0], [4,7,0], [5,8,1], [8,7,0], [6,7,0], [9,7,0], [7,7,0], [8,8,1], + [7,7,0], [8,9,2], [8,8,1], [5,8,1], [7,7,0], [7,8,1], [8,8,1], [10,8,1], + [10,7,0,2], [8,7,0], [6,7,0], [2,10,2,-1], [4,3,-4,-1], [2,10,2], [3,2,-5,-1], [2,2,-5], + [2,3,-4], [5,5,0], [6,7,0], [4,6,1], [6,8,1], [5,6,1], [4,7,0], [5,7,2], + [6,7,0], [3,7,0], [4,9,2,1], [5,9,0], [3,7,0], [8,9,0], [6,5,0], [5,6,1], + [6,7,2], [6,7,2], [4,5,0], [4,5,0], [4,7,1], [6,6,1], [5,5,0], [7,5,0], + [5,5,0], [5,7,2], [4,5,0], [5,1,-2], [10,1,-2], [4,2,-5,-1], [3,2,-5,-1], [3,2,-5,-1], + [4,16,28,40,52,64,76,88,99,111,123,135,147,159,171,183], + [13,24,36,47,59,71,82,94], + [197,102] + ], + cmmi10: [ + [8,7,0], [8,7,0], [8,8,1], [7,7,0], [8,7,0], [9,7,0], [8,7,0], [7,7,0], + [7,7,0], [7,7,0], [8,7,0], [6,6,1], [6,9,2], [6,7,2], [5,8,0], [4,6,1], + [5,9,2], [5,7,2], [5,8,1], [4,6,1], [6,6,1], [6,7,0], [6,7,2], [6,5,0], + [5,9,2], [6,5,0], [5,7,2], [6,5,0], [5,5,0], [6,6,1], [6,9,2], [6,7,2], + [7,9,2], [6,6,1], [5,6,1], [6,8,1], [8,5,0], [5,7,2], [4,6,1], [7,7,2], + [10,3,-2], [12,3,0,2], [10,3,-2], [10,3,0], [5,3,-2,2], [3,3,-2], [5,5,0], [5,5,0], + [5,6,1], [3,5,0,-1], [5,5,0], [5,7,2], [5,7,2], [5,7,2], [5,8,1], [5,7,2], + [5,8,1], [5,7,2], [2,1,0], [2,3,2], [6,7,1,-1], [5,10,2], [6,7,1,-1], [5,5,0], + [6,9,1], [7,7,0], [8,7,0], [8,8,1], [8,7,0], [8,7,0], [8,7,0], [8,8,1], + [9,7,0], [5,7,0], [7,8,1], [9,7,0], [7,7,0], [11,7,0], [11,7,0,2], [8,8,1], + [8,7,0], [8,9,2], [8,8,1], [7,8,1], [7,7,0], [8,8,1], [8,8,1], [11,8,1], + [11,7,0,2], [8,7,0], [8,7,0], [4,9,1], [4,9,2], [4,9,2], [10,3,-1], [12,3,-1,2], + [4,7,0], [5,6,1], [5,8,1], [5,5,0], [6,8,1], [5,5,0], [6,9,2], [5,7,2], + [6,7,0], [3,7,0], [4,9,2], [5,7,0], [3,7,0], [9,5,0], [6,6,1], [5,5,0], + [6,7,2,1], [5,7,2], [5,5,0], [5,5,0], [4,8,1], [6,6,1], [5,6,1], [7,6,1], + [6,6,1], [5,7,2], [5,5,0], [3,5,0], [5,7,2,1], [7,7,2], [5,2,-5,-2], [5,2,-5,-2], + [4,15,27,39,50,62,74,85,97,108,120,132,143,155,167,178], + [13,24,36,47,59,71,82,94], + [191,102] + ], + cmsy10: [ + [6,1,-2,-1], [2,1,-2], [6,5,0,-1], [5,5,0], [8,7,1], [5,5,0], [8,7,0], [8,7,2], + [8,7,1], [8,7,1], [8,7,1], [8,7,1], [8,7,1], [10,11,3], [5,5,0], [5,5,0], + [8,5,0], [8,5,0], [7,9,2], [6,9,2,-1], [6,9,2,-1], [6,9,2,-1], [6,9,2,-1], [7,9,2], + [8,3,-1], [8,5,0], [7,7,1], [6,7,1,-1], [10,7,1], [10,7,1], [6,7,1,-1], [6,7,1,-1], + [10,5,0], [10,5,0], [5,9,2], [5,9,2], [10,5,0], [10,9,2], [10,9,2], [8,5,0], + [10,5,0], [10,5,0], [6,9,2], [6,9,2], [10,7,1], [10,9,2], [10,9,2], [8,6,1], + [3,6,0], [10,6,1], [6,7,1], [5,7,1,-1], [9,7,0], [9,7,2], [6,9,2,-1], [2,5,0], + [6,8,1], [5,7,0], [7,3,-1], [5,9,1], [7,9,1], [7,8,1], [8,7,0], [8,7,0], + [6,7,0], [8,9,1], [7,8,1], [6,8,1], [8,7,0], [6,8,1], [9,8,1], [6,9,2], + [8,8,1], [7,7,0], [9,9,2], [8,8,1], [7,8,1], [11,8,1], [13,9,1,3], [8,8,1], + [8,8,1], [7,9,2,-1], [9,8,1], [7,8,1], [8,8,0], [8,8,1,1], [7,8,1], [11,8,1], + [8,7,0], [8,9,2], [8,7,0], [7,7,1], [7,7,1], [7,7,1], [6,7,1], [6,7,1], + [6,7,0], [6,7,0], [4,11,3,-1], [3,11,3], [4,11,3,-1], [3,11,3], [3,11,3,-1], [3,11,3,-1], + [3,11,3,-1], [3,11,3], [1,11,3,-1], [3,11,3,-1], [3,11,3,-1], [6,11,3], [5,11,3], [3,7,1], + [9,11,10], [7,7,0], [8,8,1], [5,11,3], [6,6,0], [6,6,0], [7,9,2], [7,9,2], + [4,9,2], [4,9,2], [4,9,2], [6,9,2], [8,10,2], [8,10,2], [8,9,1], [8,10,2], + [4,18,32,46,60,74,88,102,116,130,144,158,172,186,199,213], + [13,33,53,73,93,113,133,152], + [229,169] + ], + cmex10: [ + [3,13,12,-1], [3,13,12], [2,13,12,-2], [3,13,12], [3,13,12,-2], [3,13,12], [3,13,12,-2], [3,13,12], + [4,13,12,-1], [4,13,12,-1], [3,13,12,-1], [4,13,12], [1,8,7,-1], [4,8,7,-1], [6,13,12], [6,13,12], + [5,19,18,-1], [5,19,18], [5,25,24,-2], [6,25,24], [4,25,24,-2], [3,25,24], [4,25,24,-2], [4,25,24], + [4,25,24,-2], [4,25,24], [6,25,24,-1], [6,25,24,-1], [6,25,24,-1], [6,25,24,-1], [10,25,24], [10,25,24], + [6,31,30,-2], [6,31,30], [4,31,30,-2], [4,31,30], [5,31,30,-2], [4,31,30], [5,31,30,-2], [4,31,30], + [6,31,30,-1], [6,31,30,-1], [6,31,30,-1], [6,31,30,-1], [13,31,30], [13,31,30], [8,19,18], [8,19,18], + [7,19,18,-2], [6,19,18], [4,19,18,-3], [4,19,18], [4,19,18,-3], [4,19,18], [1,6,6,-3], [2,6,6,-2], + [5,10,10,-3], [4,10,10,-1], [5,10,9,-3], [4,10,9,-1], [4,20,19,-1], [4,20,19,-3], [2,5,4,-3], [1,6,6,-3], + [7,19,18,-2], [6,19,18], [2,8,7,-2], [2,8,7,-4], [5,19,18,-1], [4,19,18,-1], [8,10,10], [11,14,14], + [6,12,12], [10,23,23], [11,10,10], [15,14,14], [14,10,10,3], [15,14,14], [14,10,10,3], [15,14,14], + [10,10,10], [9,10,10], [6,12,12], [8,10,10], [8,10,10], [8,10,10], [8,10,10], [8,10,10], + [14,14,14], [13,14,14], [10,23,23], [11,14,14], [11,14,14], [11,14,14], [11,14,14], [11,14,14], + [9,10,10], [13,14,14], [6,3,-5], [10,3,-5], [15,3,-5], [9,3,-5,3], [10,2,-6], [15,2,-6], + [3,19,18,-2], [3,19,18], [3,19,18,-2], [3,19,18], [3,19,18,-2], [3,19,18], [5,19,18,-1], [5,19,18,-1], + [10,13,12,-1], [10,19,18,-1], [10,25,24,-1], [10,31,30,-1], [7,19,18,-1], [1,7,6,-7], [4,7,6,-7], [4,6,6,-2], + [5,6,6,-1], [5,6,6,-1], [6,4,2,1], [6,5,3,1], [6,4,0,1], [6,4,0,1], [8,6,6], [8,6,6], + [4,22,39,57,75,92,110,127,145,162,180,198,215,233,250,268], + [15,58,101,145,188,231,274,317], + [287,359] + ], + cmbx10: [ + [7,7,0], [9,7,0], [9,8,1], [8,7,0], [8,7,0], [9,7,0], [8,7,0], [9,7,0], + [8,7,0], [9,7,0], [8,7,0], [8,7,0], [6,7,0], [6,7,0], [10,7,0], [10,7,0], + [3,5,0], [4,7,2,1], [3,2,-5,-1], [3,2,-5,-2], [4,2,-5,-1], [4,2,-5,-1], [5,2,-5], [3,2,-5,-3], + [4,2,2,-1], [6,7,0], [8,5,0], [9,5,0], [6,7,1], [10,7,0], [11,8,1], [12,9,1,3], + [4,2,-2], [2,7,0,-1], [5,4,-3], [9,9,2], [5,9,1], [9,9,1], [9,8,1], [3,4,-3], + [3,10,2,-1], [4,10,2], [5,5,-3], [9,9,2], [3,4,2], [4,2,-1], [3,2,0], [5,10,2], + [6,8,1], [5,7,0], [6,7,0], [6,8,1], [6,7,0], [6,8,1], [6,8,1], [6,7,0], + [6,10,1], [6,10,1], [3,5,0], [3,7,2], [2,7,2,-1], [9,3,-1], [5,7,2], [5,9,0], + [9,7,0], [9,7,0], [8,7,0], [8,8,1], [9,7,0], [8,7,0], [7,7,0], [9,8,1], + [9,7,0], [4,7,0], [6,8,1], [9,7,0], [7,7,0], [11,7,0], [9,7,0], [8,8,1], + [8,7,0], [8,9,2], [9,8,1], [6,8,1], [8,7,0], [9,8,1], [9,7,0], [12,7,0], + [12,7,0,3], [9,7,0], [7,7,0], [2,10,2,-1], [5,4,-3,-1], [2,10,2], [4,2,-5,-1], [3,2,-5], + [3,4,-3], [6,5,0], [6,7,0], [5,5,0], [6,7,0], [5,5,0], [5,7,0], [6,7,2], + [7,7,0], [3,7,0], [4,9,2,1], [6,9,0], [3,7,0], [10,9,0], [7,5,0], [6,5,0], + [6,7,2], [6,7,2], [5,5,0], [5,5,0], [4,7,0], [7,5,0], [6,5,0], [8,5,0], + [6,5,0], [6,7,2], [5,5,0], [6,1,-2], [12,1,-2], [8,5,-2,3], [4,2,-5,-1], [4,2,-5,-1], + [4,18,32,46,59,73,87,101,115,128,142,156,170,184,198,211], + [13,24,36,47,59,71,82,94], + [227,102] + ], + cmti10: [ + [7,7,0], [8,7,0], [7,8,1,-1], [7,7,0], [8,7,0], [9,7,0], [7,7,0,-1], [7,7,0,-2], + [7,7,0,-1], [6,7,0,-2], [7,7,0,-1], [9,9,2,1], [7,9,2,1], [8,9,2,1], [11,9,2,1], [11,9,2,1], + [3,5,0,-1], [5,7,2,1], [2,2,-5,-3], [3,2,-5,-3], [3,2,-5,-3], [4,2,-5,-2], [4,1,-5,-2], [3,3,-5,-4], + [3,2,2,-1], [7,9,2,1], [7,6,1,-1], [7,6,1,-1], [6,7,1], [10,7,0], [10,8,1,-1], [10,9,1,2], + [3,2,-2,-1], [3,8,0,-1], [4,3,-4,-2], [8,9,2,-1], [6,8,1,-1], [8,9,1,-1], [7,9,1,-1], [2,3,-4,-2], + [4,10,2,-1], [4,10,2], [4,5,-3,-2], [7,7,1,-1], [3,3,2], [3,2,-1,-1], [2,1,0,-1], [6,10,2], + [5,8,1,-1], [4,7,0,-1], [5,8,1,-1], [5,8,1,-1], [5,9,2], [5,8,1,-1], [5,8,1,-1], [6,8,1,-1], + [5,10,1,-1], [6,10,1], [2,5,0,-1], [3,7,2], [4,7,2], [7,3,-1,-1], [5,7,2], [6,9,0], + [7,8,1,-1], [7,7,0], [8,7,0], [7,8,1,-1], [8,7,0], [8,7,0], [8,7,0], [7,8,1,-1], + [9,7,0], [5,7,0], [6,8,1,-1], [9,7,0], [7,7,0], [10,7,0], [9,7,0], [7,8,1,-1], + [8,7,0], [7,9,2,-1], [8,8,1], [7,8,1], [7,7,0,-1], [7,8,1,-2], [7,8,1,-2], [9,8,1,-2], + [11,7,0,2], [7,7,0,-2], [7,7,0], [5,10,2], [4,3,-4,-2], [3,10,2,-1], [4,2,-5,-2], [2,2,-5,-2], + [2,3,-4,-2], [5,6,1,-1], [4,8,1,-1], [4,6,1,-1], [5,8,1,-1], [4,6,1,-1], [6,9,2,1], [5,7,2], + [6,7,0], [3,7,0,-1], [5,9,2,1], [5,9,0], [2,7,0,-1], [9,9,0], [5,5,0,-1], [4,6,1,-1], + [5,7,2], [4,7,2,-1], [4,5,0,-1], [5,5,0], [3,7,0,-1], [5,6,1,-1], [4,6,1,-1], [6,6,1,-1], + [6,6,1], [4,7,2,-1], [5,5,0], [5,1,-2,-1], [10,1,-2,-1], [8,5,-2,2], [4,2,-5,-2], [4,2,-5,-2], + [4,16,28,40,51,63,75,87,99,111,123,135,146,158,170,182], + [13,24,36,47,59,71,82,94], + [195,102] + ] +}); + +jsMath.Img.AddFont(85,{ + cmr10: [ + [7,9,0], [10,9,0], [9,10,1], [8,9,0], [8,9,0], [9,9,0], [8,9,0], [9,9,0], + [8,9,0], [9,9,0], [8,9,0], [8,9,0], [7,9,0], [7,9,0], [10,9,0], [10,9,0], + [3,6,0], [4,9,3,1], [3,3,-6,-1], [3,3,-6,-2], [4,2,-6,-1], [4,3,-6,-1], [4,2,-6,-1], [3,3,-6,-3], + [4,3,3,-1], [6,10,1], [9,7,1], [9,7,1], [6,8,1], [11,9,0], [12,10,1], [12,10,1,3], + [3,2,-3], [2,9,0,-1], [5,5,-4], [10,12,3], [6,10,1], [10,10,1], [9,10,1], [2,5,-4,-1], + [3,12,3,-1], [4,12,3], [6,5,-4], [9,8,1], [2,5,3,-1], [4,1,-2], [2,2,0,-1], [6,12,3], + [6,9,1], [4,8,0,-1], [6,8,0], [6,9,1], [6,8,0], [6,9,1], [6,9,1], [6,9,1], + [6,9,1], [6,9,1], [2,6,0,-1], [2,9,3,-1], [2,9,3,-1], [9,4,-1], [5,9,3], [5,9,0], + [9,10,1], [9,9,0], [8,9,0], [8,10,1], [9,9,0], [8,9,0], [8,9,0], [9,10,1], + [9,9,0], [4,9,0], [6,10,1], [9,9,0], [7,9,0], [11,9,0], [9,9,0], [9,10,1], + [8,9,0], [9,12,3], [9,10,1], [6,10,1], [9,9,0], [9,10,1], [9,10,1], [12,10,1], + [9,9,0], [9,9,0], [7,9,0], [2,12,3,-1], [5,5,-4,-1], [2,12,3], [4,2,-6,-1], [2,2,-6,-1], + [3,5,-4], [6,7,1], [7,10,1], [5,7,1], [7,10,1], [5,7,1], [5,9,0], [6,9,3], + [7,9,0], [3,8,0], [4,11,3,1], [6,9,0], [3,9,0], [10,6,0], [7,6,0], [6,7,1], + [7,9,3], [7,9,3], [5,6,0], [5,7,1], [4,9,1], [7,7,1], [6,6,0], [9,6,0], + [7,6,0], [6,9,3], [5,6,0], [6,1,-3], [12,1,-3], [8,6,-3,3], [4,1,-7,-1], [4,2,-6,-1], + [5,19,34,48,63,77,92,106,121,135,150,164,179,193,208,222], + [16,30,45,59,73,87,101,115], + [239,125] + ], + cmmi10: [ + [9,9,0], [10,9,0], [9,10,1], [8,9,0], [10,9,0], [11,9,0], [10,9,0], [9,9,0], + [8,9,0], [9,9,0], [9,9,0,-1], [8,7,1], [7,12,3], [7,9,3], [6,10,1], [5,7,1], + [6,12,3], [6,9,3], [6,9,0], [4,7,1], [7,7,1], [7,10,1], [7,9,3], [7,6,0], + [6,12,3], [7,6,0], [6,9,3], [7,7,1], [6,7,1], [7,7,1], [7,12,3], [7,9,3], + [8,12,3], [8,7,1], [5,7,1], [7,10,1], [10,7,1], [6,9,3], [5,8,2], [8,9,3], + [12,4,-2], [15,4,0,3], [15,4,-2,3], [15,4,0,3], [6,4,-2,3], [3,4,-2], [6,6,0], [6,6,0], + [6,7,1], [4,6,0,-1], [6,6,0], [6,9,3], [6,9,3], [6,9,3], [6,9,1], [6,9,3], + [6,9,1], [6,9,3], [2,2,0,-1], [2,5,3,-1], [8,8,1,-1], [6,12,3], [8,8,1,-1], [6,6,0], + [7,10,1], [9,9,0], [9,9,0], [9,10,1], [10,9,0], [10,9,0], [9,9,0], [9,10,1], + [11,9,0], [6,9,0], [8,10,1], [11,9,0], [8,9,0], [12,9,0], [14,9,0,3], [9,10,1], + [9,9,0], [9,12,3], [9,10,1], [8,10,1], [9,9,0], [9,10,1], [8,10,1,-1], [12,10,1], + [13,9,0,3], [9,9,0], [9,9,0], [4,10,1], [3,12,3,-1], [4,12,3], [12,4,-1], [15,4,-1,3], + [5,10,1], [6,7,1], [5,10,1], [6,7,1], [6,10,1], [5,7,1], [7,12,3], [6,9,3], + [7,9,0], [4,8,0], [6,11,3,1], [6,10,1], [3,10,1], [11,7,1], [7,7,1], [6,7,1], + [7,9,3,1], [6,9,3], [6,6,0], [5,7,1], [4,9,1], [7,7,1], [6,7,1], [9,7,1], + [7,7,1], [6,9,3], [6,7,1], [4,6,0], [6,9,3,1], [8,9,3], [6,3,-6,-2], [5,2,-6,-3], + [5,19,33,47,61,75,89,104,118,132,146,160,174,188,202,216], + [16,30,45,59,73,87,101,115], + [232,125] + ], + cmsy10: [ + [8,2,-2,-1], [2,2,-2,-1], [7,6,0,-1], [6,6,0], [9,8,1], [6,6,0], [9,8,0], [9,8,2], + [9,8,1], [9,8,1], [9,8,1], [9,8,1], [9,8,1], [12,12,3], [6,6,0], [6,6,0], + [9,6,0], [9,6,0], [8,10,2,-1], [8,10,2,-1], [8,10,2,-1], [8,10,2,-1], [8,10,2,-1], [8,10,2,-1], + [9,4,-1], [9,6,0], [8,8,1,-1], [8,8,1,-1], [12,8,1], [12,8,1], [8,8,1,-1], [8,8,1,-1], + [11,4,-1,-1], [11,4,-1], [4,11,3,-1], [4,11,2,-1], [10,4,-1,-1], [12,12,3], [12,12,3], [9,6,0], + [11,8,1,-1], [11,8,1], [7,12,3], [7,12,3], [12,8,1], [12,12,3], [12,12,3], [9,7,1], + [3,7,0], [12,7,1], [6,8,1,-1], [6,8,1,-1], [10,9,0], [10,9,3], [7,12,3,-1], [2,6,0], + [7,10,1], [6,9,0], [8,4,-1], [6,11,1], [9,10,1], [9,10,1], [9,8,0], [9,8,0], + [7,9,0], [10,10,1], [8,10,1], [7,10,1], [10,9,0], [7,10,1], [10,10,1], [8,11,2], + [10,10,1], [9,9,0,1], [10,11,2], [9,10,1], [8,10,1], [14,10,1], [13,11,1,1], [10,10,1], + [9,10,1], [9,11,2,-1], [10,10,1], [8,10,1], [10,9,0], [10,10,1,1], [8,10,1], [13,10,1], + [10,9,0], [9,11,2], [9,9,0], [8,8,1], [8,9,1], [8,8,1], [8,8,1], [8,7,0], + [7,9,0], [7,9,0], [3,12,3,-2], [4,12,3], [3,12,3,-2], [4,12,3], [4,12,3,-1], [4,12,3,-1], + [3,12,3,-1], [4,12,3], [1,12,3,-1], [4,12,3,-1], [4,12,3,-1], [7,14,4], [6,12,3], [3,8,1], + [10,13,12,-1], [9,9,0], [10,10,1], [6,12,3], [8,7,0], [8,8,0], [8,10,2,-1], [9,10,2], + [5,12,3], [5,12,3], [5,12,3], [7,12,3], [9,11,2], [9,11,2], [9,10,1], [9,11,2], + [5,22,39,56,73,90,107,124,141,157,174,191,208,225,242,259], + [17,41,65,90,114,138,162,186], + [278,206] + ], + cmex10: [ + [4,15,14,-1], [4,15,14], [3,15,14,-2], [3,15,14], [4,15,14,-2], [4,15,14], [4,15,14,-2], [4,15,14], + [5,15,14,-1], [5,15,14,-1], [4,15,14,-1], [4,15,14,-1], [2,8,8,-1], [4,9,8,-1], [7,15,14], [7,15,14], + [5,22,21,-2], [5,22,21], [7,30,29,-2], [7,30,29], [4,30,29,-3], [4,30,29], [4,30,29,-3], [4,30,29], + [4,30,29,-3], [4,30,29], [7,30,29,-1], [7,30,29,-1], [7,30,29,-1], [7,30,29,-1], [12,30,29], [12,30,29], + [7,37,36,-2], [7,37,36], [4,37,36,-3], [4,37,36], [5,37,36,-3], [5,37,36], [5,37,36,-3], [5,37,36], + [7,37,36,-1], [7,37,36,-1], [8,37,36,-1], [7,37,36,-1], [15,37,36], [15,37,36], [9,22,21], [9,22,21], + [7,23,22,-3], [7,23,22], [5,23,22,-3], [5,23,22], [5,23,22,-3], [5,23,22], [2,8,8,-3], [2,8,8,-3], + [5,11,11,-4], [4,11,11,-2], [5,12,11,-4], [4,12,11,-2], [4,23,22,-2], [5,23,22,-4], [2,5,4,-4], [2,7,7,-3], + [7,22,21,-3], [7,22,21], [2,9,8,-3], [2,9,8,-5], [6,22,21,-1], [5,22,21,-1], [10,12,12], [13,17,17], + [8,14,14], [12,27,27], [13,12,12], [18,17,17], [13,12,12], [18,17,17], [13,12,12], [18,17,17], + [12,12,12], [11,12,12], [8,14,14], [10,12,12], [10,12,12], [10,12,12], [10,12,12], [10,12,12], + [17,17,17], [15,17,17], [12,27,27], [13,17,17], [13,17,17], [13,17,17], [13,17,17], [13,17,17], + [11,12,12], [15,17,17], [7,3,-6], [12,3,-7], [18,3,-7], [7,2,-7], [12,2,-7], [18,2,-7], + [4,23,22,-2], [3,23,22], [4,23,22,-2], [4,23,22], [4,22,21,-2], [4,23,22], [6,22,21,-1], [6,22,21,-1], + [12,15,14,-1], [12,22,21,-1], [12,30,29,-1], [12,37,36,-1], [8,23,22,-1], [1,9,8,-8], [5,8,7,-8], [4,8,8,-3], + [6,7,7,-1], [6,7,7,-1], [7,5,3,1], [7,5,3,1], [7,4,0,1], [7,4,0,1], [9,8,8], [9,7,7], + [5,27,48,69,91,112,133,155,176,197,219,240,261,283,304,325], + [19,72,124,177,229,281,334,386], + [349,437] + ], + cmbx10: [ + [8,9,0], [11,9,0], [10,10,1], [10,9,0], [9,9,0], [11,9,0], [10,9,0], [10,9,0], + [10,9,0], [10,9,0], [10,9,0], [9,9,0], [8,9,0], [8,9,0], [11,9,0], [11,9,0], + [4,6,0], [5,9,3,1], [3,3,-6,-1], [3,3,-6,-3], [5,2,-6,-1], [5,3,-6,-1], [5,2,-6,-1], [4,3,-6,-3], + [5,3,3,-1], [7,9,0], [10,7,1], [11,7,1], [7,9,2], [12,9,0], [13,10,1,-1], [10,10,1], + [4,2,-3], [2,9,0,-1], [6,5,-4], [11,12,3], [7,10,1], [11,10,1], [10,10,1], [2,5,-4,-1], + [4,12,3,-1], [4,12,3], [5,6,-3,-1], [10,10,2], [2,5,3,-1], [4,2,-2], [2,2,0,-1], [6,12,3], + [7,9,1], [5,8,0,-1], [7,8,0], [7,9,1], [7,8,0], [7,9,1], [7,9,1], [7,9,0], + [7,9,1], [7,9,1], [2,6,0,-1], [2,9,3,-1], [2,9,3,-1], [10,4,-1], [6,9,3], [6,9,0], + [10,10,1], [10,9,0], [9,9,0], [10,10,1], [10,9,0], [9,9,0], [8,9,0], [10,10,1], + [11,9,0], [5,9,0], [7,10,1], [11,9,0], [8,9,0], [13,9,0], [11,9,0], [10,10,1], + [9,9,0], [10,12,3], [11,10,1], [7,10,1], [9,9,0], [10,10,1], [10,9,0], [14,9,0], + [10,9,0], [11,9,0], [8,9,0], [3,12,3,-1], [6,5,-4,-1], [3,12,3], [5,3,-6,-1], [2,3,-6,-1], + [3,5,-4], [7,7,1], [8,9,0], [6,6,0], [8,10,1], [6,7,1], [6,9,0], [7,9,3], + [8,9,0], [4,9,0], [5,12,3,1], [7,9,0], [4,9,0], [12,6,0], [8,6,0], [7,7,1], + [8,9,3], [8,9,3], [6,6,0], [5,7,1], [5,8,0], [8,7,1], [7,6,0], [10,6,0], + [7,6,0], [7,9,3], [6,6,0], [7,1,-3], [14,1,-3], [5,3,-6,-1], [5,2,-7,-1], [5,3,-6,-1], + [5,22,38,55,72,89,106,122,139,156,173,190,206,223,240,257], + [16,30,45,59,73,87,101,115], + [275,125] + ], + cmti10: [ + [9,9,0], [8,9,0,-1], [9,10,1,-1], [8,9,0], [8,9,0,-1], [10,9,0], [9,9,0,-1], [8,9,0,-2], + [8,9,0,-1], [8,9,0,-2], [8,9,0,-1], [10,12,3,1], [9,12,3,1], [9,12,3,1], [12,12,3,1], [13,12,3,1], + [3,7,1,-1], [5,9,3,1], [3,3,-6,-3], [3,3,-6,-4], [4,2,-6,-3], [4,3,-6,-3], [4,2,-6,-3], [3,3,-6,-5], + [3,3,3,-1], [8,12,3,1], [8,7,1,-1], [8,7,1,-1], [6,8,1,-1], [12,9,0], [10,10,1,-2], [13,10,1,3], + [3,2,-3,-1], [4,9,0,-1], [5,5,-4,-2], [9,12,3,-1], [8,10,1,-1], [9,10,1,-1], [9,10,1,-1], [3,5,-4,-2], + [5,12,3,-1], [5,12,3], [5,5,-4,-2], [8,8,1,-1], [2,5,3,-1], [3,1,-2,-1], [2,2,0,-1], [8,12,3], + [6,9,1,-1], [5,8,0,-1], [6,9,1,-1], [6,9,1,-1], [6,11,3], [6,9,1,-1], [6,9,1,-1], [7,9,1,-1], + [6,9,1,-1], [6,9,1,-1], [3,6,0,-1], [3,9,3,-1], [4,9,3], [9,4,-1,-1], [5,9,3,-1], [5,9,0,-2], + [9,10,1,-1], [9,9,0], [9,9,0], [9,10,1,-1], [10,9,0], [9,9,0], [9,9,0], [9,10,1,-1], + [10,9,0], [6,9,0], [7,10,1,-1], [10,9,0], [8,9,0], [12,9,0], [10,9,0], [9,10,1,-1], + [9,9,0], [9,12,3,-1], [9,10,1], [7,10,1,-1], [8,9,0,-2], [8,10,1,-2], [9,10,1,-2], [10,10,1,-2], + [13,9,0,3], [9,9,0,-2], [8,9,0,-1], [5,12,3,-1], [5,5,-4,-3], [6,12,3,1], [4,3,-6,-3], [2,2,-6,-3], + [3,5,-4,-2], [6,7,1,-1], [5,10,1,-1], [5,7,1,-1], [6,10,1,-1], [5,7,1,-1], [7,12,3,1], [6,9,3], + [6,9,0,-1], [3,9,1,-1], [6,11,3,1], [5,10,1,-1], [3,9,0,-1], [9,7,1,-1], [6,7,1,-1], [6,7,1,-1], + [7,9,3], [5,9,3,-1], [5,6,0,-1], [4,7,1,-1], [4,9,1,-1], [6,7,1,-1], [5,7,1,-1], [8,7,1,-1], + [7,7,1], [6,9,3,-1], [6,7,1], [6,1,-3,-1], [11,1,-3,-1], [10,6,-3,3], [4,2,-6,-3], [4,2,-6,-3], + [5,19,34,48,62,77,91,106,120,135,149,163,178,192,207,221], + [16,30,45,59,73,87,101,115], + [237,125] + ] +}); + +jsMath.Img.AddFont(100,{ + cmr10: [ + [9,10,0], [11,10,0], [11,11,1], [10,10,0], [9,10,0], [10,10,0], [10,10,0], [10,10,0], + [10,10,0], [9,10,0,168], [10,10,0], [9,10,0], [8,10,0], [8,10,0], [12,10,0], [12,10,0], + [4,7,0], [4,10,3,1], [3,3,-7,-1], [3,3,-7,-3], [5,2,-7,-1], [5,3,-7,-1], [5,2,-7,-1], [3,3,-7,-4], + [4,3,3,-2], [7,11,1], [10,8,1], [11,8,1], [7,10,2], [13,10,0], [13,11,1,-1], [11,12,1], + [4,2,-4], [2,10,0,-1], [5,5,-5], [11,13,3], [7,12,1], [11,12,1], [11,11,1], [2,5,-5,-1], + [4,15,4,-1], [3,15,4,-1], [5,7,-4,-1], [10,9,1], [2,5,3,-1], [4,2,-2], [2,2,0,-1], [7,15,4], + [7,11,1], [5,10,0,-1], [7,10,0], [7,11,1], [7,10,0], [7,11,1], [7,11,1], [7,11,1], + [7,11,1], [7,11,1], [2,6,0,-1], [2,9,3,-1], [2,10,3,-1], [10,5,-1], [6,10,3], [6,10,0], + [11,11,1], [10,10,0], [10,10,0], [10,11,1], [10,10,0], [9,10,0], [9,10,0], [11,11,1], + [10,10,0], [5,10,0], [7,11,1], [11,10,0], [9,10,0], [13,10,0], [10,10,0], [11,11,1], + [9,10,0], [11,13,3], [11,11,1], [7,11,1], [10,10,0], [10,11,1], [11,11,1], [14,11,1], + [11,10,0], [11,10,0], [8,10,0], [3,15,4,-1], [5,5,-5,-2], [3,15,4], [5,3,-7,-1], [2,2,-8,-1], + [2,5,-5,-1], [7,8,1], [8,11,1], [6,8,1], [8,11,1], [6,8,1], [5,10,0], [7,10,3], + [8,10,0], [4,10,0], [4,13,3,1], [8,10,0], [4,10,0], [12,7,0], [8,7,0], [7,8,1], + [8,10,3], [8,10,3], [5,7,0], [5,8,1], [5,10,1], [8,8,1], [7,6,0], [10,6,0], + [8,6,0], [7,9,3], [6,6,0], [7,1,-3], [14,1,-3], [5,3,-7,-1], [5,2,-8,-1], [5,2,-8,-1], + [6,23,40,57,74,91,108,125,142,159,176,193,210,227,244,262], + [19,36,52,69,85,102,119,135], + [281,146] + ], + cmmi10: [ + [10,10,0], [11,10,0], [11,11,1], [10,10,0], [11,10,0], [13,10,0], [11,10,0,-1], [10,10,0], + [9,10,0], [10,10,0], [10,10,0,-1], [9,8,1], [9,13,3], [8,10,3], [7,11,1], [6,7,1], + [7,13,3], [7,10,3], [7,11,1], [5,8,1], [8,8,1], [8,11,1], [8,9,3], [8,7,0], + [7,13,3], [8,7,1], [7,10,3], [8,7,1], [8,7,1], [8,8,1], [8,13,3], [9,10,3], + [9,13,3], [9,8,1], [6,8,1], [8,11,1], [12,7,1], [6,10,3,-1], [6,9,2], [9,10,3], + [14,4,-3], [14,4,0], [14,4,-3], [17,4,0,3], [3,4,-3], [3,4,-3], [7,7,0], [7,7,0], + [7,8,1], [5,7,0,-1], [7,7,0], [7,10,3], [7,10,3], [7,10,3], [7,11,1], [7,10,3], + [7,11,1], [7,10,3], [2,2,0,-1], [2,5,3,-1], [9,9,1,-1], [7,15,4], [9,9,1,-1], [7,7,0], + [8,11,1], [10,10,0], [11,10,0], [11,11,1], [12,10,0], [11,10,0], [11,10,0], [11,11,1], + [13,10,0], [7,10,0], [8,11,1,-1], [13,10,0], [9,10,0], [15,10,0], [16,10,0,3], [11,11,1], + [11,10,0], [11,13,3], [11,11,1], [9,11,1], [10,10,0], [10,11,1,-1], [11,11,1], [14,11,1], + [15,10,0,3], [11,10,0], [10,10,0], [5,12,1], [4,13,3,-1], [5,13,3], [12,4,-1,-1], [12,4,-2,-1], + [6,11,1], [7,8,1], [6,11,1], [6,8,1], [8,11,1], [6,8,1], [8,13,3], [7,10,3], + [8,11,1], [4,11,1], [7,13,3,1], [7,11,1], [4,11,1], [12,8,1], [8,8,1], [7,8,1], + [8,10,3,1], [7,10,3], [6,8,1], [6,8,1], [5,10,1], [8,8,1], [7,8,1], [10,8,1], + [8,8,1], [7,10,3], [7,8,1], [4,8,1], [6,10,3,1], [8,10,3,-1], [7,3,-7,-2], [6,3,-7,-3], + [6,22,39,55,72,89,105,122,138,155,172,188,205,221,238,255], + [19,36,52,69,85,102,119,135], + [273,146] + ], + cmsy10: [ + [9,1,-3,-1], [2,3,-2,-1], [7,7,0,-2], [5,7,0,-1], [10,9,1], [7,7,0], [10,10,0], [10,10,3], + [11,11,2], [11,11,2], [11,11,2], [11,11,2], [11,11,2], [14,13,3], [7,7,0], [7,7,0], + [10,7,0], [10,7,0], [9,11,2,-1], [9,11,2,-1], [9,11,2,-1], [9,11,2,-1], [9,11,2,-1], [9,11,2,-1], + [11,5,-1], [10,7,0], [9,9,1,-1], [9,9,1,-1], [14,9,1], [14,9,1], [9,9,1,-1], [9,9,1,-1], + [13,5,-1,-1], [13,5,-1], [5,13,3,-1], [5,13,3,-1], [12,5,-1,-1], [14,13,3], [14,13,3], [10,7,0], + [13,9,1,-1], [13,9,1], [8,13,3], [8,13,3], [14,9,1], [14,13,3], [14,13,3], [10,8,1], + [4,8,0], [14,8,1], [7,9,1,-1], [8,9,1,-1], [12,10,0], [12,10,3], [7,13,3,-2], [2,5,-1], + [8,11,1], [7,10,0], [9,4,-1], [7,12,1], [10,11,1], [10,11,1], [9,10,0,-1], [10,10,0], + [8,10,0], [11,11,1], [10,11,1], [8,11,1], [11,10,0], [8,11,1], [12,11,1], [9,12,2], + [12,11,1], [10,10,0,1], [12,12,2], [11,11,1], [9,11,1], [16,11,1], [15,12,1,1], [11,11,1], + [11,11,1], [10,12,2,-1], [12,11,1], [9,11,1], [11,10,0], [11,11,1,1], [10,11,1], [15,11,1], + [12,10,0], [10,12,2], [11,10,0], [9,10,1], [9,10,1], [9,10,1], [8,10,1,-1], [9,10,1], + [8,10,0], [8,10,0], [4,15,4,-2], [4,15,4], [4,15,4,-2], [4,15,4], [5,15,4,-1], [5,15,4,-1], + [4,15,4,-1], [4,15,4], [2,15,4,-1], [5,15,4,-1], [5,15,4,-1], [8,15,4], [7,15,4], [4,11,2], + [11,15,14,-1], [10,10,0], [11,11,1], [7,13,3], [9,9,0], [9,9,0], [9,11,2,-1], [9,11,2,-1], + [5,13,3,-1], [6,13,3], [6,13,3], [8,13,3], [11,13,2], [10,14,3], [11,11,1], [11,13,2], + [6,26,46,66,86,106,125,145,165,185,205,225,245,265,285,305], + [20,48,77,105,134,162,190,219], + [327,243] + ], + cmex10: [ + [4,18,17,-2], [5,18,17], [4,18,17,-2], [3,18,17], [5,18,17,-2], [4,18,17], [5,18,17,-2], [4,18,17], + [6,18,17,-1], [6,18,17,-1], [5,18,17,-1], [5,18,17,-1], [1,10,9,-2], [4,10,9,-2], [8,18,17], [8,17,16], + [6,26,25,-2], [6,26,25], [8,34,33,-2], [8,34,33], [5,34,33,-3], [4,34,33], [5,34,33,-3], [5,34,33], + [5,34,33,-3], [5,34,33], [8,34,33,-1], [8,34,33,-1], [8,34,33,-1], [8,34,33,-1], [14,34,33], [14,34,33], + [8,43,42,-3], [8,43,42], [5,43,42,-3], [5,43,42], [6,43,42,-3], [6,43,42], [6,43,42,-3], [6,43,42], + [8,43,42,-2], [8,43,42,-2], [8,43,42,-2], [9,43,42,-1], [17,43,42], [17,43,42], [11,26,25], [11,26,25], + [8,26,25,-4], [9,26,25], [6,26,25,-4], [5,26,25], [6,26,25,-4], [5,26,25], [2,9,9,-4], [2,9,9,-3], + [5,13,13,-5], [6,13,13,-2], [5,14,13,-5], [6,14,13,-2], [6,27,26,-2], [5,27,26,-5], [3,6,5,-5], [1,9,9,-4], + [8,26,25,-4], [9,26,25], [2,10,9,-4], [3,10,9,-6], [7,26,25,-1], [6,26,25,-1], [11,14,14], [15,20,20], + [9,16,16], [14,31,31], [15,14,14], [21,20,20], [15,14,14], [21,20,20], [15,14,14], [21,20,20], + [14,14,14], [13,14,14], [9,16,16], [11,14,14], [11,14,14], [11,14,14], [11,14,14], [11,14,14], + [20,20,20], [18,20,20], [14,31,31], [15,20,20], [15,20,20], [15,20,20], [15,20,20], [15,20,20], + [13,14,14], [18,20,20], [8,3,-8], [14,3,-8], [21,3,-8], [8,3,-8], [14,3,-8], [20,3,-8], + [4,26,25,-3], [4,26,25], [5,26,25,-3], [5,26,25], [5,26,25,-3], [5,26,25], [7,26,25,-1], [7,26,25,-1], + [14,18,17,-1], [14,26,25,-1], [14,34,33,-1], [14,43,42,-1], [10,26,25,-1], [2,10,9,-9], [6,9,8,-9], [5,9,9,-3], + [7,9,9,-1], [7,9,9,-1], [8,5,3,1], [8,5,3,1], [8,5,0,1], [8,5,0,1], [11,9,9], [11,9,9], + [6,31,56,82,107,132,157,182,207,232,257,282,307,332,358,383], + [23,84,146,208,269,331,392,454], + [410,514] + ], + cmbx10: [ + [9,10,0], [13,10,0], [12,11,1], [11,10,0], [10,10,0], [12,10,0], [10,10,0,-1], [11,10,0,-1], + [11,10,0], [11,10,0,-1], [11,10,0], [11,10,0], [9,10,0], [9,10,0], [13,10,0], [13,10,0], + [4,7,0], [5,10,3,1], [4,3,-7,-1], [4,3,-7,-3], [4,2,-7,-2], [6,3,-7,-1], [6,2,-7,-1], [4,3,-7,-4], + [6,3,3,-1], [8,10,0], [12,8,1], [12,8,1], [8,10,2], [14,10,0], [15,11,1,-1], [12,12,1], + [5,2,-4], [3,10,0,-1], [7,6,-4], [12,13,3,-1], [8,12,1], [13,12,1], [12,11,1], [3,5,-5,-1], + [5,15,4,-1], [4,15,4,-1], [6,7,-4,-1], [11,11,2,-1], [3,6,3,-1], [5,2,-2], [3,3,0,-1], [6,15,4,-1], + [8,11,1], [6,10,0,-1], [8,10,0], [8,11,1], [8,10,0], [8,11,1], [8,11,1], [7,11,1,-1], + [8,11,1], [8,11,1], [3,7,0,-1], [3,10,3,-1], [3,10,3,-1], [11,5,-1,-1], [6,10,3,-1], [6,10,0,-1], + [12,11,1], [12,10,0], [11,10,0], [11,11,1], [12,10,0], [10,10,0], [10,10,0], [12,11,1], + [12,10,0], [6,10,0], [8,11,1], [12,10,0], [9,10,0], [15,10,0], [12,10,0], [12,11,1], + [10,10,0], [12,13,3], [12,11,1], [8,11,1], [11,10,0], [12,11,1], [12,10,0], [17,10,0], + [12,10,0], [12,10,0], [8,10,0,-1], [3,15,4,-1], [6,6,-4,-2], [3,15,4], [4,3,-7,-2], [3,3,-7,-1], + [4,6,-4], [8,7,0], [9,10,0], [7,7,0], [9,11,1], [7,7,0], [7,10,0], [8,10,3], + [9,10,0], [4,10,0], [5,13,3,1], [9,10,0], [5,10,0], [14,7,0], [9,7,0], [8,7,0], + [9,10,3], [9,10,3], [7,7,0], [6,8,1], [6,10,1], [9,7,0], [8,7,0], [12,7,0], + [9,7,0], [8,10,3], [7,7,0], [8,2,-3], [16,2,-3], [5,3,-7,-2], [6,2,-8,-1], [6,3,-7,-1], + [6,26,45,65,85,104,124,144,164,183,203,223,243,262,282,302], + [19,36,52,69,85,102,119,135], + [324,146] + ], + cmti10: [ + [9,10,0,-1], [10,10,0,-1], [9,11,1,-2], [9,10,0], [10,10,0,-1], [11,10,0,-1], [10,10,0,-1], [9,10,0,-3], + [9,10,0,-2], [9,10,0,-3], [10,10,0,-1], [12,13,3,1], [10,13,3,1], [10,13,3,1], [14,13,3,1], [15,13,3,1], + [4,8,1,-1], [6,10,3,1], [2,3,-7,-4], [4,3,-7,-4], [4,2,-7,-4], [4,3,-7,-4], [5,2,-7,-3], [4,3,-7,-6], + [4,3,3,-1], [9,13,3,1], [9,8,1,-1], [9,8,1,-1], [7,10,2,-1], [13,10,0,-1], [13,11,1,-2], [15,12,1,3], + [4,2,-4,-1], [5,10,0,-1], [6,5,-5,-2], [11,13,3,-1], [9,11,1,-1], [10,12,1,-2], [11,11,1,-1], [3,5,-5,-3], + [6,15,4,-2], [6,15,4], [6,7,-4,-2], [9,9,1,-2], [3,5,3,-1], [4,2,-2,-1], [2,2,0,-1], [9,15,4], + [7,11,1,-1], [6,10,0,-1], [7,11,1,-1], [7,11,1,-1], [7,13,3], [7,11,1,-1], [7,11,1,-1], [7,11,1,-2], + [7,11,1,-1], [7,11,1,-1], [4,6,0,-1], [4,9,3,-1], [5,10,3], [10,5,-1,-1], [6,10,3,-1], [6,10,0,-2], + [9,11,1,-2], [9,10,0,-1], [10,10,0,-1], [10,11,1,-2], [10,10,0,-1], [10,10,0,-1], [10,10,0,-1], [10,11,1,-2], + [11,10,0,-1], [7,10,0], [8,11,1,-1], [11,10,0,-1], [8,10,0,-1], [13,10,0,-1], [11,10,0,-1], [9,11,1,-2], + [10,10,0,-1], [9,13,3,-2], [9,11,1,-1], [8,11,1,-1], [10,10,0,-2], [10,11,1,-2], [9,11,1,-3], [12,11,1,-3], + [15,10,0,3], [10,10,0,-3], [9,10,0,-1], [6,15,4,-1], [6,5,-5,-3], [6,15,4,1], [5,3,-7,-3], [2,2,-8,-3], + [3,5,-5,-2], [7,8,1,-1], [6,11,1,-1], [6,8,1,-1], [7,11,1,-1], [6,8,1,-1], [8,13,3,1], [7,10,3], + [7,11,1,-1], [4,11,1,-1], [6,13,3,1], [6,11,1,-1], [4,11,1,-1], [11,8,1,-1], [8,8,1,-1], [7,8,1,-1], + [8,10,3], [6,10,3,-1], [6,8,1,-1], [5,8,1,-1], [5,10,1,-1], [7,8,1,-1], [6,8,1,-1], [9,8,1,-1], + [8,8,1], [7,10,3,-1], [6,8,1,-1], [7,1,-3,-1], [14,1,-3,-1], [11,7,-3,3], [5,2,-8,-3], [5,2,-8,-3], + [6,23,40,56,73,90,107,124,141,158,175,192,209,226,243,260], + [19,36,52,69,85,102,119,135], + [279,146] + ] +}); + +jsMath.Img.AddFont(120,{ + cmr10: [ + [10,12,0], [14,12,0], [12,13,1,-1], [12,13,0], [11,12,0], [13,12,0], [11,12,0,-1], [12,12,0,-1], + [11,12,0,-1], [12,12,0,-1], [12,12,0], [11,12,0], [9,12,0], [9,12,0], [14,12,0], [14,12,0], + [5,8,0], [5,12,4,1], [4,4,-8,-1], [4,4,-8,-3], [5,3,-8,-2], [6,4,-8,-1], [7,1,-9,-1], [4,4,-9,-4], + [5,4,4,-2], [8,13,1], [12,9,1], [13,9,1], [8,11,2], [15,12,0], [16,13,1,-1], [12,14,1,-1], + [5,3,-4], [3,13,0,-1], [6,6,-6], [13,16,4,-1], [7,14,1,-1], [13,14,1,-1], [13,14,1], [3,6,-6,-1], + [5,17,4,-1], [4,17,4,-1], [7,8,-5,-1], [12,12,2,-1], [3,6,4,-1], [5,2,-3], [3,2,0,-1], [7,17,4,-1], + [8,13,1], [7,12,0,-1], [8,12,0], [8,13,1], [8,12,0], [8,13,1], [8,13,1], [8,13,1,-1], + [8,13,1], [8,13,1], [3,8,0,-1], [3,12,4,-1], [3,13,4,-1], [12,5,-2,-1], [6,13,4,-1], [6,12,0,-1], + [12,13,1,-1], [13,13,0], [11,12,0], [11,13,1,-1], [12,12,0], [11,12,0], [11,12,0], [12,13,1,-1], + [13,12,0], [6,12,0], [8,13,1], [13,12,0], [10,12,0], [15,12,0], [13,12,0], [12,13,1,-1], + [11,12,0], [12,16,4,-1], [13,13,1], [8,13,1,-1], [12,12,0], [13,13,1], [13,13,1], [18,13,1], + [13,12,0], [13,12,0], [9,12,0,-1], [3,17,4,-2], [6,6,-6,-2], [3,17,4], [5,3,-9,-2], [3,3,-9,-1], + [3,6,-6,-1], [9,9,1], [9,13,1], [7,9,1], [9,13,1], [7,9,1], [6,12,0], [9,12,4], + [9,12,0], [5,12,0], [5,16,4,1], [9,12,0], [5,12,0], [14,8,0], [9,8,0], [8,9,1], + [9,12,4], [9,12,4], [7,8,0], [7,9,1], [6,12,1], [9,9,1], [9,9,1], [12,9,1], + [9,8,0], [9,12,4], [7,8,0], [9,1,-4], [17,1,-4], [6,4,-8,-2], [6,3,-9,-1], [6,3,-9,-1], + [7,27,48,68,89,109,130,150,171,191,211,232,252,273,293,314], + [22,42,61,81,101,121,141,161], + [337,175] + ], + cmmi10: [ + [13,12,0], [13,13,0,-1], [13,13,1], [12,12,0], [13,12,0,-1], [15,12,0], [13,12,0,-1], [12,12,0], + [11,12,0], [12,12,0], [13,12,0,-1], [11,9,1], [10,16,4], [10,12,4], [8,14,1], [7,9,1], + [8,16,4], [9,12,4], [8,13,1], [5,9,1,-1], [9,9,1,-1], [9,13,1,-1], [10,12,4], [8,8,0,-1], + [8,16,4], [10,9,1], [9,12,4], [10,9,1], [9,9,1], [9,9,1], [10,16,4], [10,12,4], + [11,16,4], [11,9,1], [8,9,1], [10,13,1], [14,9,1], [8,12,4,-1], [7,10,2], [11,12,4], + [15,6,-3,-1], [15,6,1,-1], [15,6,-3,-1], [15,6,1,-1], [3,4,-4,-1], [3,5,-3,-1], [8,9,0], [8,9,0], + [8,9,1], [6,8,0,-1], [8,8,0], [8,12,4], [8,12,4], [8,12,4], [8,13,1], [8,12,4,-1], + [8,13,1], [8,12,4], [3,2,0,-1], [3,6,4,-1], [11,11,1,-1], [7,17,4,-1], [11,11,1,-1], [9,9,0], + [10,14,1], [13,13,0], [13,12,0], [13,13,1], [14,12,0], [13,12,0], [13,12,0], [13,13,1], + [15,12,0], [9,12,0], [10,13,1,-1], [15,12,0], [11,12,0], [18,12,0], [18,12,0,3], [13,13,1], + [13,12,0], [13,16,4], [13,13,1], [10,13,1,-1], [12,12,0], [12,13,1,-1], [12,13,1,-1], [17,13,1,-1], + [18,12,0,3], [13,12,0], [12,12,0,-1], [6,14,1], [5,17,4,-1], [5,16,4,-1], [15,5,-2,-1], [15,5,-2,-1], + [7,13,1], [9,9,1], [7,13,1], [8,9,1], [9,13,1], [8,9,1], [9,16,4,-1], [8,12,4], + [9,13,1,-1], [5,13,1], [8,16,4,1], [8,13,1,-1], [5,13,1], [15,9,1], [10,9,1], [8,9,1], + [10,12,4,1], [8,12,4], [8,9,1], [7,9,1], [6,12,1], [10,9,1], [8,9,1], [12,9,1], + [9,9,1], [9,12,4], [8,9,1], [5,9,1], [8,12,4,1], [10,12,4,-1], [8,4,-8,-3], [7,3,-9,-4], + [7,27,46,66,86,106,126,146,166,186,206,226,246,266,286,306], + [22,42,61,81,101,121,141,161], + [328,175] + ], + cmsy10: [ + [11,2,-3,-1], [3,3,-3,-1], [9,9,0,-2], [7,8,0,-1], [12,10,1,-1], [9,9,0], [12,12,0,-1], [12,12,3,-1], + [12,12,2,-1], [12,12,2,-1], [12,12,2,-1], [12,12,2,-1], [12,12,2,-1], [15,17,4,-1], [7,7,-1,-1], [7,7,-1,-1], + [12,9,0,-1], [12,8,0,-1], [11,14,3,-1], [11,14,3,-1], [11,14,3,-1], [11,14,3,-1], [11,14,3,-1], [11,14,3,-1], + [12,5,-2,-1], [12,8,-1,-1], [11,11,1,-1], [11,11,1,-1], [15,11,1,-1], [15,11,1,-1], [11,11,1,-1], [11,11,1,-1], + [15,7,-1,-1], [15,7,-1,-1], [7,16,4,-1], [7,16,4,-1], [15,7,-1,-1], [15,16,4,-1], [15,16,4,-1], [12,8,0,-1], + [15,10,1,-1], [15,10,1,-1], [10,16,4], [10,16,4], [17,10,1], [15,16,4,-1], [15,16,4,-1], [12,9,1,-1], + [5,10,0], [15,9,1,-1], [9,11,1,-1], [9,11,1,-1], [13,13,0,-1], [13,13,4,-1], [9,17,4,-2], [1,7,-1,-1], + [10,13,1], [8,12,0,-1], [10,5,-1,-1], [8,15,2], [12,14,1], [11,13,1,-1], [12,12,0,-1], [12,12,0,-1], + [9,12,0,-1], [14,14,1], [12,13,1], [9,13,1], [13,12,0], [10,13,1], [14,13,1], [11,14,2], + [14,13,1], [12,12,0,1], [15,14,2], [13,13,1], [11,13,1], [19,13,1], [18,15,1,1], [13,13,1,-1], + [13,13,1], [12,15,3,-2], [14,13,1], [11,13,1], [14,13,0], [13,13,1,1], [12,13,1], [18,13,1], + [14,12,0], [13,15,3], [13,12,0], [10,12,1,-1], [10,12,1,-1], [10,12,1,-1], [10,12,1,-1], [10,12,1,-1], + [9,12,0,-1], [9,12,0,-1], [4,18,5,-3], [5,18,5], [5,18,5,-3], [5,18,5], [7,18,5,-1], [7,18,5,-1], + [5,18,5,-1], [4,18,5,-1], [1,18,5,-2], [5,18,5,-2], [7,18,5,-1], [10,18,5], [7,18,5,-1], [3,12,2,-1], + [14,18,17,-1], [12,12,0], [14,13,1], [7,17,4,-1], [10,11,0,-1], [10,11,0,-1], [11,14,3,-1], [11,14,3,-1], + [6,16,4,-1], [6,16,4,-1], [6,16,4,-1], [9,16,4,-1], [13,16,3], [12,16,3,-1], [12,14,1,-1], [12,16,3,-1], + [7,31,55,79,103,127,151,174,198,222,246,270,294,318,342,366], + [23,57,91,125,159,193,227,261], + [392,290] + ], + cmex10: [ + [5,21,20,-2], [6,21,20], [4,21,20,-3], [4,21,20], [5,21,20,-3], [5,21,20], [5,21,20,-3], [5,21,20], + [6,21,20,-2], [6,21,20,-2], [6,21,20,-1], [6,21,20,-1], [2,12,11,-2], [5,12,11,-2], [8,21,20,-1], [8,21,20,-1], + [7,31,30,-3], [8,31,30], [9,42,41,-3], [9,41,40], [5,42,41,-4], [5,42,41], [6,42,41,-4], [6,42,41], + [6,42,41,-4], [6,42,41], [9,41,40,-2], [9,42,41,-2], [9,41,40,-2], [10,41,40,-1], [16,41,40,-1], [16,41,40,-1], + [9,52,51,-4], [10,52,51], [6,52,51,-4], [6,52,51], [7,52,51,-4], [7,52,51], [7,52,51,-4], [7,52,51], + [10,52,51,-2], [10,52,51,-2], [10,52,51,-2], [11,52,51,-1], [20,52,51,-1], [20,52,51,-1], [12,31,30,-1], [12,31,30,-1], + [10,32,31,-5], [10,32,31], [7,31,30,-5], [6,31,30], [7,31,30,-5], [6,31,30], [2,11,11,-5], [2,11,11,-4], + [7,16,16,-6], [7,16,16,-2], [7,17,16,-6], [6,17,16,-3], [7,32,31,-2], [7,32,31,-6], [3,7,6,-6], [1,11,11,-5], + [10,31,30,-5], [10,31,30], [2,12,11,-5], [2,12,11,-8], [7,31,30,-2], [8,31,30,-1], [13,17,17,-1], [17,24,24,-1], + [10,19,19,-1], [15,38,38,-1], [17,17,17,-1], [24,24,24,-1], [17,17,17,-1], [24,24,24,-1], [17,17,17,-1], [24,24,24,-1], + [16,17,17,-1], [14,17,17,-1], [10,19,19,-1], [13,17,17,-1], [13,17,17,-1], [13,17,17,-1], [13,17,17,-1], [13,17,17,-1], + [23,24,24,-1], [20,24,24,-1], [15,38,38,-1], [17,24,24,-1], [17,24,24,-1], [17,24,24,-1], [17,24,24,-1], [17,24,24,-1], + [14,17,17,-1], [20,24,24,-1], [10,4,-9], [17,4,-9], [25,4,-9], [10,3,-10], [17,3,-10], [25,3,-10], + [5,31,30,-3], [5,31,30], [6,31,30,-3], [6,31,30], [6,31,30,-3], [6,31,30], [8,31,30,-2], [8,31,30,-2], + [16,21,20,-2], [16,31,30,-2], [16,42,41,-2], [16,52,51,-2], [11,32,31,-2], [2,12,11,-11], [8,11,10,-11], [5,11,11,-4], + [9,11,11,-1], [8,10,10,-2], [9,6,4,1], [9,6,4,1], [9,6,0,1], [9,6,0,1], [12,11,11,-1], [12,10,10,-1], + [7,38,68,98,128,158,188,218,248,278,309,339,369,399,429,459], + [26,100,174,248,322,396,470,544], + [492,616] + ], + cmbx10: [ + [11,12,0], [15,12,0,-1], [14,13,1,-1], [13,12,0], [13,12,0], [15,12,0], [12,12,0,-1], [13,12,0,-1], + [12,12,0,-1], [13,12,0,-1], [13,12,0,-1], [13,12,0], [11,12,0], [11,12,0], [16,12,0], [16,12,0], + [5,8,0], [6,12,4,1], [4,4,-8,-2], [4,4,-8,-4], [6,2,-9,-2], [7,4,-8,-1], [8,2,-9,-1], [5,3,-9,-5], + [6,4,4,-2], [10,13,1], [14,9,1], [15,9,1], [10,12,2], [18,12,0], [19,13,1,-1], [14,14,1,-1], + [6,3,-4], [4,12,0,-1], [8,6,-6], [15,16,4,-1], [8,14,1,-1], [15,14,1,-1], [15,13,1], [4,6,-6,-1], + [6,17,4,-1], [5,17,4,-1], [8,8,-5,-1], [13,14,3,-1], [4,7,4,-1], [6,2,-3], [3,3,0,-1], [8,17,4,-1], + [9,13,1], [8,12,0,-1], [8,12,0,-1], [9,13,1], [10,12,0], [8,12,1,-1], [9,13,1], [9,13,1,-1], + [9,13,1], [9,13,1], [3,8,0,-1], [4,12,4,-1], [4,13,4,-1], [13,6,-1,-1], [8,13,4,-1], [8,12,0,-1], + [14,13,1,-1], [14,12,0], [13,12,0], [12,13,1,-1], [14,12,0], [13,12,0], [12,12,0], [14,13,1,-1], + [15,12,0], [7,12,0], [9,13,1], [15,12,0], [11,12,0], [18,12,0], [15,12,0], [13,13,1,-1], + [13,12,0], [13,16,4,-1], [15,13,1], [9,13,1,-1], [13,12,0], [15,13,1], [15,13,1], [20,13,1], + [15,12,0], [15,12,0], [10,12,0,-1], [3,17,4,-2], [8,7,-5,-2], [4,17,4], [6,3,-9,-2], [3,3,-9,-1], + [3,7,-5,-1], [10,9,1], [11,13,1], [8,9,1], [11,13,1], [9,9,1], [8,12,0], [10,12,4], + [11,12,0], [5,12,0], [6,16,4,1], [10,12,0], [5,12,0], [16,8,0], [11,8,0], [10,9,1], + [11,12,4], [11,12,4], [8,8,0], [7,9,1], [7,12,1], [11,9,1], [10,8,0], [14,8,0], + [10,8,0], [10,12,4], [8,8,0], [10,1,-4], [20,1,-4], [7,4,-8,-2], [7,2,-10,-1], [7,3,-9,-1], + [7,31,54,78,102,125,149,173,196,220,244,268,291,315,339,362], + [22,42,61,81,101,121,141,161], + [388,175] + ], + cmti10: [ + [11,12,0,-1], [12,12,0,-1], [12,13,1,-2], [10,13,0,-1], [12,12,0,-1], [14,12,0,-1], [13,12,0,-1], [12,12,0,-3], + [11,12,0,-2], [11,12,0,-3], [12,12,0,-1], [14,16,4,1], [12,16,4,1], [12,16,4,1], [17,16,4,1], [17,16,4,1], + [5,9,1,-1], [7,12,4,1], [3,4,-8,-5], [5,4,-8,-5], [5,3,-8,-4], [6,4,-8,-4], [6,1,-9,-4], [4,4,-9,-8], + [5,4,4,-1], [11,16,4,1], [12,9,1,-1], [12,9,1,-1], [9,11,2,-1], [15,12,0,-1], [16,13,1,-2], [17,14,1,3], + [5,3,-4,-1], [5,13,0,-2], [6,6,-6,-3], [12,16,4,-2], [11,13,1,-1], [13,14,1,-2], [12,14,1,-2], [4,6,-6,-3], + [7,17,4,-2], [7,17,4], [7,8,-5,-3], [11,11,1,-2], [3,6,4,-1], [5,2,-3,-1], [2,2,0,-2], [11,17,4], + [8,13,1,-2], [6,12,0,-2], [9,13,1,-1], [9,13,1,-1], [8,16,4], [9,13,1,-1], [8,13,1,-2], [9,13,1,-2], + [9,13,1,-1], [9,13,1,-1], [4,8,0,-2], [5,12,4,-1], [5,13,4,-1], [12,5,-2,-2], [7,13,4,-1], [7,13,0,-3], + [12,13,1,-2], [11,13,0,-1], [12,12,0,-1], [12,13,1,-2], [13,12,0,-1], [12,12,0,-1], [12,12,0,-1], [12,13,1,-2], + [14,12,0,-1], [8,12,0,-1], [10,13,1,-1], [14,12,0,-1], [10,12,0,-1], [16,12,0,-1], [14,12,0,-1], [12,13,1,-2], + [12,12,0,-1], [12,16,4,-2], [12,13,1,-1], [10,13,1,-1], [11,12,0,-3], [12,13,1,-3], [12,13,1,-3], [16,13,1,-3], + [17,12,0,3], [12,12,0,-3], [11,12,0,-1], [7,17,4,-1], [7,6,-6,-4], [7,17,4,1], [5,3,-9,-4], [3,3,-9,-4], + [3,6,-6,-3], [8,9,1,-1], [6,13,1,-2], [7,9,1,-1], [9,13,1,-1], [6,9,1,-2], [9,16,4,1], [8,12,4,-1], + [8,13,1,-1], [5,12,1,-1], [7,16,4,1], [8,13,1,-1], [5,13,1,-1], [14,9,1,-1], [9,9,1,-1], [8,9,1,-1], + [9,12,4], [8,12,4,-1], [8,9,1,-1], [6,9,1,-1], [6,12,1,-1], [9,9,1,-1], [8,9,1,-1], [11,9,1,-1], + [8,9,1,-1], [8,12,4,-1], [7,9,1,-1], [9,1,-4,-1], [16,1,-4,-2], [13,8,-4,3], [6,3,-9,-4], [6,3,-9,-4], + [7,27,47,68,88,109,129,149,170,190,210,231,251,271,292,312], + [22,42,61,81,101,121,141,161], + [335,175] + ] +}); + +jsMath.Img.AddFont(144,{ + cmr10: [ + [12,14,0], [15,15,0,-1], [14,16,1,-1], [14,15,0], [13,14,0], [15,14,0], [13,14,0,-1], [14,15,0,-1], + [13,14,0,-1], [14,14,0,-1], [13,15,0,-1], [13,15,0], [11,15,0], [11,15,0], [16,15,0], [16,15,0], + [5,9,0], [6,14,5,1], [4,4,-10,-2], [4,4,-10,-4], [6,3,-10,-2], [6,4,-10,-2], [8,1,-11,-1], [5,5,-10,-5], + [6,5,5,-2], [10,16,1], [13,10,1,-1], [15,10,1], [10,13,2], [18,14,0], [19,15,1,-1], [14,16,1,-1], + [6,3,-5], [3,15,0,-1], [7,6,-8], [15,18,4,-1], [8,16,1,-1], [15,17,2,-1], [15,16,1], [4,6,-8,-1], + [5,20,5,-2], [5,20,5,-1], [8,9,-6,-1], [14,14,2,-1], [3,7,4,-1], [6,2,-3], [3,3,0,-1], [8,20,5,-1], + [10,15,1], [8,14,0,-1], [8,14,0,-1], [10,15,1], [10,14,0], [8,15,1,-1], [10,15,1], [9,15,1,-1], + [10,15,1], [10,15,1], [3,9,0,-1], [3,13,4,-1], [3,15,5,-1], [14,6,-2,-1], [8,15,5,-1], [8,15,0,-1], + [14,16,1,-1], [15,15,0], [13,14,0], [13,16,1,-1], [15,14,0], [13,14,0], [13,14,0], [14,16,1,-1], + [15,14,0], [7,14,0], [10,15,1], [15,14,0], [12,14,0], [18,14,0], [15,14,0], [14,16,1,-1], + [13,14,0], [14,19,4,-1], [15,15,1], [9,16,1,-1], [14,14,0], [15,15,1], [15,15,1], [21,15,1], + [15,14,0], [15,14,0], [11,14,0,-1], [4,20,5,-2], [7,7,-7,-3], [4,20,5], [6,3,-11,-2], [3,3,-11,-1], + [3,7,-7,-1], [10,10,1], [11,15,1], [9,10,1], [11,15,1], [9,10,1], [8,15,0], [10,14,5], + [11,14,0], [5,14,0], [6,19,5,1], [11,14,0], [5,14,0], [17,9,0], [11,9,0], [10,10,1], + [11,13,4], [11,13,4], [8,9,0], [8,10,1], [7,14,1], [11,10,1], [11,10,1], [14,10,1], + [11,9,0], [11,13,4], [8,9,0], [10,1,-5], [20,1,-5], [7,4,-10,-2], [8,3,-11,-1], [6,3,-11,-2], + [8,33,57,82,106,131,155,180,205,229,254,278,303,327,352,377], + [26,50,74,98,122,145,169,193], + [404,209] + ], + cmmi10: [ + [15,14,0], [15,15,0,-1], [14,16,1,-1], [14,15,0], [15,14,0,-1], [18,14,0], [15,14,0,-1], [14,14,0], + [13,14,0], [14,14,0], [15,15,0,-1], [12,10,1], [12,18,4], [11,14,5], [9,16,1], [7,10,1,-1], + [10,19,5], [10,14,5], [10,15,1], [6,10,1,-1], [10,10,1,-1], [10,15,1,-1], [12,14,5], [10,9,0,-1], + [9,19,5], [12,10,1], [10,14,5], [12,10,1], [11,10,1], [11,10,1], [11,18,4,-1], [12,14,5], + [13,18,4], [13,10,1], [9,10,1], [12,16,1], [17,10,1], [9,13,4,-1], [9,12,3], [12,14,5,-1], + [18,7,-4,-1], [18,7,1,-1], [18,7,-4,-1], [18,7,1,-1], [4,6,-4,-1], [4,6,-4,-1], [10,10,0], [10,10,0], + [10,10,1], [7,9,0,-2], [8,9,0,-1], [10,14,5], [10,14,4], [8,14,5,-1], [10,15,1], [9,15,5,-1], + [10,15,1], [10,14,5], [3,3,0,-1], [3,7,4,-1], [13,12,1,-1], [8,20,5,-1], [13,12,1,-1], [10,10,0], + [12,16,1], [15,15,0], [16,14,0], [15,16,1,-1], [17,14,0], [16,14,0], [15,14,0], [15,16,1,-1], + [18,14,0], [10,14,0], [12,15,1,-1], [18,14,0], [13,14,0], [21,14,0], [18,14,0], [14,16,1,-1], + [15,14,0], [14,19,4,-1], [15,15,1], [12,16,1,-1], [14,14,0], [15,15,1,-1], [15,15,1,-1], [20,15,1,-1], + [17,14,0], [16,14,0], [14,14,0,-1], [6,16,1,-1], [6,20,5,-1], [6,20,5,-1], [18,6,-2,-1], [18,6,-2,-1], + [8,15,1], [10,10,1], [8,15,1,-1], [9,10,1], [11,15,1], [9,10,1], [10,19,4,-1], [10,14,5], + [10,15,1,-1], [6,15,1], [9,19,5,1], [10,15,1,-1], [6,15,1], [17,10,1], [12,10,1], [10,10,1], + [11,13,4,1], [9,13,4], [9,10,1], [8,10,1,-1], [7,14,1], [11,10,1], [10,10,1], [14,10,1], + [11,10,1], [10,14,5], [9,10,1,-1], [6,10,1], [9,14,5,1], [12,14,5,-1], [10,5,-10,-3], [8,4,-10,-5], + [8,32,56,80,104,128,151,175,199,223,247,271,295,319,343,367], + [26,50,74,98,122,145,169,193], + [393,209] + ], + cmsy10: [ + [13,2,-4,-1], [3,2,-4,-1], [10,10,0,-3], [8,10,0,-1], [14,12,1,-1], [10,10,0], [14,14,0,-1], [14,14,4,-1], + [14,14,2,-1], [14,14,2,-1], [14,14,2,-1], [14,14,2,-1], [14,14,2,-1], [18,20,5,-1], [8,8,-1,-1], [8,8,-1,-1], + [14,10,0,-1], [14,10,0,-1], [13,16,3,-1], [13,16,3,-1], [13,16,3,-1], [13,16,3,-1], [13,16,3,-1], [13,16,3,-1], + [14,6,-2,-1], [14,9,-1,-1], [13,12,1,-1], [13,12,1,-1], [18,14,2,-1], [18,14,2,-1], [13,12,1,-1], [13,12,1,-1], + [18,8,-1,-1], [18,8,-1,-1], [8,18,4,-1], [8,18,4,-1], [18,8,-1,-1], [18,18,4,-1], [18,18,4,-1], [14,10,0,-1], + [18,12,1,-1], [18,12,1,-1], [12,18,4], [12,18,4], [19,12,1], [18,18,4,-1], [18,18,4,-1], [14,10,1,-1], + [6,11,-1], [18,10,1,-1], [11,12,1,-1], [11,12,1,-1], [16,15,0,-1], [16,15,5,-1], [11,20,5,-2], [2,8,-1,-1], + [11,15,1], [9,14,0,-1], [12,7,-1,-1], [9,18,2], [14,16,1,-1], [13,16,1,-1], [14,14,0,-1], [14,14,0,-1], + [11,14,0,-1], [16,16,1], [14,16,1], [11,15,1], [16,14,0], [12,16,1], [17,15,1], [12,18,3], + [17,15,1], [14,14,0,1], [16,17,3,-1], [15,16,1], [13,16,1], [23,15,1], [21,17,1,1], [15,15,1,-1], + [15,15,1], [14,18,3,-2], [17,15,1], [13,16,1], [16,15,0], [15,15,1,1], [14,15,1], [21,15,1], + [16,14,0,-1], [15,17,3], [16,14,0], [12,13,1,-1], [12,13,1,-1], [12,13,1,-1], [11,13,1,-1], [12,13,1,-1], + [10,14,0,-1], [11,14,0,-1], [6,20,5,-3], [6,20,5], [6,20,5,-3], [6,20,5], [8,20,5,-1], [8,20,5,-1], + [5,20,5,-2], [5,20,5,-1], [2,20,5,-2], [6,20,5,-2], [8,22,6,-1], [12,22,6], [8,20,5,-1], [4,14,2,-1], + [16,21,20,-1], [15,14,0], [15,15,1,-1], [9,20,5,-1], [12,12,0,-1], [12,12,0,-1], [14,16,3,-1], [13,16,3,-1], + [7,20,5,-1], [7,19,5,-1], [7,18,4,-1], [11,18,4,-1], [15,18,3], [14,19,4,-1], [14,16,1,-1], [14,18,3,-1], + [8,37,66,95,123,152,181,209,238,267,295,324,353,382,410,439], + [27,68,109,150,191,232,273,314], + [471,348] + ], + cmex10: [ + [6,24,23,-3], [6,24,23,-1], [4,25,24,-4], [5,25,24], [5,25,24,-4], [6,25,24], [5,25,24,-4], [6,25,24], + [8,25,24,-2], [8,25,24,-2], [6,25,24,-2], [7,24,23,-1], [2,14,13,-2], [7,14,13,-2], [10,25,24,-1], [10,24,23,-1], + [9,37,36,-3], [9,37,36], [10,49,48,-4], [11,49,48], [6,49,48,-5], [6,49,48], [7,49,48,-5], [7,49,48], + [7,49,48,-5], [7,49,48], [11,49,48,-2], [11,49,48,-2], [11,49,48,-2], [11,49,48,-2], [19,49,48,-1], [19,49,48,-1], + [11,61,60,-4], [12,61,60], [7,61,60,-5], [7,61,60], [8,61,60,-5], [8,61,60], [8,61,60,-5], [8,61,60], + [12,61,60,-2], [12,61,60,-2], [12,61,60,-2], [12,61,60,-2], [24,61,60,-1], [24,61,60,-1], [14,37,36,-1], [14,37,36,-1], + [12,37,36,-5], [12,37,36], [8,37,36,-6], [7,37,36], [8,37,36,-6], [7,37,36], [2,12,12,-6], [2,12,12,-5], + [8,19,19,-7], [8,19,19,-3], [8,19,18,-7], [8,19,18,-3], [8,38,37,-3], [8,38,37,-7], [4,8,7,-7], [2,12,12,-6], + [12,37,36,-5], [12,37,36], [3,14,13,-5], [3,14,13,-9], [9,36,35,-2], [9,37,36,-1], [15,20,20,-1], [21,28,28,-1], + [12,23,23,-1], [18,45,45,-1], [20,20,20,-1], [28,28,28,-1], [20,20,20,-1], [28,28,28,-1], [20,20,20,-1], [28,28,28,-1], + [19,20,20,-1], [17,20,20,-1], [12,23,23,-1], [15,20,20,-1], [15,20,20,-1], [15,20,20,-1], [15,20,20,-1], [15,20,20,-1], + [27,28,28,-1], [24,28,28,-1], [18,45,45,-1], [21,28,28,-1], [21,28,28,-1], [21,28,28,-1], [20,28,28,-1], [20,28,28,-1], + [17,20,20,-1], [24,28,28,-1], [12,4,-11], [20,5,-11], [29,5,-11], [11,3,-12], [20,3,-12], [29,3,-12], + [5,37,36,-4], [5,37,36], [7,37,36,-4], [6,37,36], [7,37,36,-4], [6,37,36], [9,37,36,-2], [9,37,36,-2], + [19,25,24,-2], [19,37,36,-2], [19,49,48,-2], [19,61,60,-2], [13,37,36,-2], [1,14,13,-14], [8,13,12,-14], [6,12,12,-5], + [9,12,12,-2], [9,12,12,-2], [11,8,5,1], [11,8,5,1], [11,7,0,1], [11,7,0,1], [14,12,12,-1], [14,12,12,-1], + [9,45,81,117,154,190,226,262,298,334,370,406,443,479,515,551], + [31,120,209,297,386,475,564,652], + [591,739] + ], + cmbx10: [ + [13,14,0], [17,14,0,-1], [16,15,1,-1], [16,14,0], [14,14,0,-1], [18,14,0], [15,14,0,-1], [16,14,0,-1], + [15,14,0,-1], [16,14,0,-1], [15,14,0,-1], [15,14,0], [12,14,0], [12,14,0], [19,14,0], [19,14,0], + [5,9,0,-1], [8,13,4,2], [5,4,-10,-2], [5,4,-10,-5], [7,3,-10,-2], [8,4,-10,-2], [9,2,-11,-1], [5,4,-10,-6], + [7,4,4,-2], [12,15,1], [16,10,1], [18,10,1], [11,13,2], [21,14,0], [22,15,1,-1], [16,16,1,-1], + [7,3,-5], [3,15,0,-2], [10,7,-7], [17,18,4,-1], [10,17,2,-1], [17,17,2,-1], [16,15,1,-1], [4,7,-7,-1], + [6,20,5,-2], [6,20,5,-1], [9,9,-6,-1], [16,16,3,-1], [4,8,4,-1], [7,3,-3], [4,4,0,-1], [10,20,5,-1], + [11,15,1], [9,13,0,-1], [10,14,0,-1], [10,15,1,-1], [11,14,0], [10,14,1,-1], [10,15,1,-1], [11,15,1,-1], + [10,15,1,-1], [10,15,1,-1], [4,9,0,-1], [4,13,4,-1], [3,15,5,-2], [16,6,-2,-1], [9,14,4,-1], [9,14,0,-1], + [16,15,1,-1], [17,14,0], [15,14,0], [15,15,1,-1], [17,14,0], [15,14,0], [14,14,0], [16,15,1,-1], + [18,14,0], [8,14,0], [11,15,1], [17,14,0], [13,14,0], [21,14,0], [18,14,0], [15,15,1,-1], + [15,14,0], [16,18,4,-1], [18,15,1], [11,15,1,-1], [16,14,0], [17,15,1], [17,15,1], [24,15,1], + [17,14,0], [17,14,0], [12,14,0,-1], [4,20,5,-2], [10,8,-6,-2], [4,20,5], [7,4,-10,-2], [4,4,-10,-1], + [4,8,-6,-1], [12,10,1], [12,15,1], [10,10,1], [12,15,1], [10,10,1], [9,14,0], [12,13,4], + [13,14,0], [5,14,0,-1], [8,18,4,2], [12,14,0], [5,14,0,-1], [19,9,0], [13,9,0], [11,10,1], + [12,13,4], [12,13,4], [9,9,0], [9,10,1], [8,14,1], [13,10,1], [12,9,0], [17,9,0], + [12,9,0], [12,13,4], [10,9,0], [12,1,-5], [23,1,-5], [7,5,-10,-3], [8,3,-11,-2], [8,3,-11,-2], + [8,37,65,94,122,150,179,207,236,264,293,321,349,378,406,435], + [26,50,74,98,122,145,169,193], + [466,209] + ], + cmti10: [ + [13,14,0,-1], [14,15,0,-1], [13,16,1,-3], [12,15,0,-1], [14,14,0,-1], [16,14,0,-1], [15,14,0,-1], [13,15,0,-4], + [12,14,0,-3], [13,14,0,-4], [14,15,0,-2], [17,19,4,1], [13,19,4,1], [14,19,4,1], [20,20,5,1], [20,20,5,1], + [6,10,1,-1], [8,13,4,1], [4,4,-10,-5], [5,4,-10,-6], [6,3,-10,-5], [7,4,-10,-5], [8,1,-11,-4], [5,5,-10,-9], + [5,4,4,-2], [13,19,4,1], [14,10,1,-1], [13,10,1,-2], [10,13,2,-1], [18,14,0,-1], [18,16,1,-3], [15,17,2,-2], + [5,3,-5,-2], [6,15,0,-2], [8,6,-8,-3], [15,18,4,-2], [13,16,1,-1], [14,17,2,-3], [14,16,1,-2], [4,6,-8,-4], + [8,20,5,-3], [8,20,5], [8,9,-6,-4], [12,13,2,-3], [4,7,4,-1], [6,2,-3,-1], [3,3,0,-2], [13,20,5], + [10,15,1,-2], [8,14,0,-2], [10,15,1,-1], [11,15,1,-1], [9,18,4,-1], [10,15,1,-2], [10,15,1,-2], [10,15,1,-3], + [9,15,1,-2], [9,15,1,-2], [4,9,0,-2], [5,13,4,-1], [6,15,5,-1], [14,6,-2,-2], [8,15,5,-1], [8,15,0,-3], + [13,16,1,-3], [13,15,0,-1], [14,14,0,-1], [14,16,1,-3], [15,14,0,-1], [14,14,0,-1], [14,14,0,-1], [14,16,1,-3], + [16,14,0,-1], [9,14,0,-1], [12,15,1,-1], [17,14,0,-1], [12,14,0,-1], [19,14,0,-1], [16,14,0,-1], [13,16,1,-3], + [14,14,0,-1], [13,19,4,-3], [14,15,1,-1], [12,16,1,-1], [13,14,0,-3], [13,15,1,-4], [14,15,1,-4], [18,15,1,-4], + [21,14,0,4], [14,14,0,-4], [13,14,0,-1], [8,20,5,-1], [8,7,-7,-5], [9,20,5,1], [6,4,-10,-5], [3,3,-11,-5], + [4,6,-8,-4], [9,10,1,-2], [8,15,1,-2], [8,10,1,-2], [10,15,1,-2], [8,10,1,-2], [10,19,4,1], [9,14,5,-1], + [10,15,1,-1], [6,14,1,-1], [9,18,4,1], [9,15,1,-1], [5,15,1,-1], [16,10,1,-1], [11,10,1,-1], [9,10,1,-2], + [11,13,4], [8,13,4,-2], [9,10,1,-1], [8,10,1,-1], [7,14,1,-1], [11,10,1,-1], [9,10,1,-1], [13,10,1,-1], + [10,10,1,-1], [10,13,4,-1], [9,10,1,-1], [9,1,-5,-2], [19,1,-5,-2], [7,4,-10,-5], [7,3,-11,-5], [6,3,-11,-5], + [8,32,57,81,106,130,155,179,204,228,252,277,301,326,350,375], + [26,50,74,98,122,145,169,193], + [402,209] + ] +}); + +jsMath.Img.AddFont(173,{ + cmr10: [ + [14,17,0], [18,18,0,-1], [17,18,1,-1], [16,18,0], [14,17,0,-1], [18,17,0], [15,17,0,-1], [17,17,0,-1], + [15,17,0,-1], [17,17,0,-1], [16,17,0,-1], [15,17,0], [13,17,0], [13,17,0], [20,17,0], [20,17,0], + [6,11,0], [6,16,5,1], [5,5,-12,-2], [5,5,-12,-5], [6,4,-12,-3], [8,5,-12,-2], [10,2,-13,-1], [6,5,-13,-6], + [6,5,5,-3], [12,18,1], [16,12,1,-1], [18,12,1], [12,16,3], [21,17,0], [23,18,1,-1], [17,20,2,-1], + [7,4,-6], [3,18,0,-2], [9,8,-9], [18,22,5,-1], [10,20,2,-1], [18,20,2,-1], [17,19,1,-1], [3,8,-9,-2], + [6,24,6,-2], [6,24,6,-1], [10,11,-7,-1], [17,16,2,-1], [3,8,5,-2], [7,2,-4], [3,3,0,-2], [10,24,6,-1], + [11,17,1], [8,16,0,-2], [10,16,0,-1], [10,17,1,-1], [12,17,0], [10,17,1,-1], [10,17,1,-1], [11,18,1,-1], + [10,17,1,-1], [10,17,1,-1], [3,11,0,-2], [3,16,5,-2], [3,18,6,-2], [17,6,-3,-1], [9,17,5,-1], [9,17,0,-1], + [17,18,1,-1], [18,18,0], [16,17,0], [15,18,1,-1], [17,17,0], [16,17,0], [15,17,0], [17,18,1,-1], + [18,17,0], [8,17,0], [11,18,1,-1], [18,17,0], [14,17,0], [22,17,0], [18,17,0], [17,18,1,-1], + [15,17,0], [17,22,5,-1], [18,18,1], [11,18,1,-1], [17,17,0], [18,18,1], [18,18,1], [25,18,1], + [18,17,0], [18,17,0], [13,17,0,-1], [5,24,6,-2], [9,8,-9,-3], [4,24,6], [6,4,-13,-3], [3,3,-13,-2], + [4,8,-9,-1], [11,12,1,-1], [13,18,1], [10,12,1], [13,18,1], [10,12,1], [9,17,0], [12,16,5], + [13,17,0], [6,16,0], [6,21,5,1], [13,17,0], [7,17,0], [20,11,0], [13,11,0], [12,12,1], + [13,16,5], [13,16,5], [9,11,0], [9,12,1], [8,16,1], [13,12,1], [13,12,1], [17,12,1], + [13,11,0], [13,16,5], [10,11,0], [12,1,-6], [24,1,-6], [7,5,-12,-3], [8,3,-13,-2], [8,3,-13,-2], + [10,39,69,98,128,157,187,216,246,275,305,334,364,393,423,453], + [32,61,90,118,147,176,204,233], + [485,253] + ], + cmmi10: [ + [17,17,0,-1], [18,18,0,-1], [17,18,1,-1], [16,18,0], [18,17,0,-1], [20,17,0,-1], [19,17,0,-1], [17,17,0], + [16,17,0], [17,17,0], [18,17,0,-1], [14,12,1,-1], [15,22,5], [13,16,5], [10,18,1,-1], [8,12,1,-1], + [11,22,5,-1], [12,17,6], [10,18,1,-1], [7,12,1,-1], [12,12,1,-1], [12,18,1,-1], [14,17,6], [12,11,0,-1], + [11,22,5], [14,12,1], [12,17,6], [14,12,1], [13,12,1], [13,12,1], [13,22,5,-1], [15,16,5], + [16,22,5], [15,12,1], [11,12,1], [14,18,1], [20,12,1], [11,16,5,-1], [10,14,3], [14,17,6,-1], + [22,8,-5,-1], [22,8,1,-1], [22,8,-5,-1], [22,8,1,-1], [5,7,-5,-1], [5,7,-5,-1], [12,12,0], [12,12,0], + [10,12,1,-1], [8,11,0,-2], [10,11,0,-1], [10,17,6,-1], [12,17,5], [10,17,6,-1], [10,17,1,-1], [11,17,6,-1], + [10,17,1,-1], [10,17,6,-1], [3,3,0,-2], [3,8,5,-2], [15,14,1,-2], [10,24,6,-1], [15,14,1,-2], [12,12,0], + [13,19,1,-1], [18,18,0], [18,17,0,-1], [18,18,1,-1], [19,17,0,-1], [18,17,0,-1], [17,17,0,-1], [18,18,1,-1], + [20,17,0,-1], [12,17,0], [14,18,1,-1], [21,17,0,-1], [15,17,0,-1], [24,17,0,-1], [20,17,0,-1], [17,18,1,-1], + [18,17,0,-1], [17,22,5,-1], [17,18,1,-1], [15,18,1,-1], [17,17,0], [18,18,1,-1], [18,18,1,-1], [24,18,1,-1], + [25,17,0,4], [18,17,0,-1], [17,17,0,-1], [7,19,1,-1], [7,24,6,-1], [7,24,6,-1], [22,6,-3,-1], [22,7,-3,-1], + [10,18,1], [11,12,1,-1], [9,18,1,-1], [10,12,1,-1], [12,18,1,-1], [10,12,1,-1], [13,22,5,-1], [12,16,5], + [12,18,1,-1], [7,17,1], [11,21,5,1], [12,18,1,-1], [6,18,1,-1], [21,12,1], [14,12,1], [11,12,1,-1], + [13,16,5,1], [10,16,5,-1], [11,12,1], [9,12,1,-1], [8,16,1], [13,12,1], [12,12,1], [17,12,1], + [13,12,1], [12,16,5], [11,12,1,-1], [7,12,1], [10,16,5,1], [14,17,6,-1], [11,5,-12,-4], [10,3,-13,-6], + [10,38,67,96,124,153,182,211,239,268,297,326,354,383,412,440], + [32,61,90,118,147,176,204,233], + [472,253] + ], + cmsy10: [ + [15,2,-5,-2], [3,4,-4,-2], [12,12,0,-3], [10,11,0,-1], [17,14,1,-1], [12,12,0], [17,16,0,-1], [17,16,4,-1], + [17,16,2,-1], [17,16,2,-1], [17,16,2,-1], [17,16,2,-1], [17,16,2,-1], [22,24,6,-1], [10,10,-1,-1], [10,10,-1,-1], + [17,12,0,-1], [17,12,0,-1], [15,20,4,-2], [15,20,4,-2], [15,20,4,-2], [15,20,4,-2], [15,20,4,-2], [15,20,4,-2], + [17,6,-3,-1], [17,11,-1,-1], [15,14,1,-2], [15,14,1,-2], [22,16,2,-1], [22,16,2,-1], [15,14,1,-2], [15,14,1,-2], + [22,10,-1,-1], [22,10,-1,-1], [10,22,5,-1], [10,22,5,-1], [22,10,-1,-1], [22,22,5,-1], [22,22,5,-1], [17,12,0,-1], + [22,14,1,-1], [22,14,1,-1], [14,22,5], [14,22,5], [22,14,1,-1], [22,22,5,-1], [22,22,5,-1], [17,12,1,-1], + [7,13,-1], [22,12,1,-1], [12,14,1,-2], [12,14,1,-2], [19,18,0,-1], [19,18,6,-1], [13,24,6,-3], [2,10,-1,-1], + [14,18,1], [11,17,0,-1], [14,7,-2,-1], [10,21,2,-1], [16,19,1,-1], [16,18,1,-1], [17,16,0,-1], [17,16,0,-1], + [13,17,0,-1], [19,20,2], [16,18,1], [13,18,1], [19,17,0], [14,18,1], [20,18,1], [14,20,3,-1], + [20,19,2], [17,17,0,1], [19,20,3,-1], [18,18,1], [16,18,1], [27,19,2], [25,21,2,1], [18,18,1,-1], + [18,19,2], [17,20,3,-2], [20,18,1], [16,18,1], [19,18,0], [18,18,1,1], [15,18,1,-1], [24,18,1,-1], + [19,17,0,-1], [18,21,4], [18,17,0,-1], [14,16,1,-1], [14,16,1,-1], [14,16,1,-1], [14,16,1,-1], [14,16,1,-1], + [13,17,0,-1], [13,17,0,-1], [6,24,6,-4], [7,24,6], [6,24,6,-4], [7,24,6], [9,24,6,-2], [9,24,6,-1], + [6,24,6,-2], [6,24,6,-1], [2,24,6,-2], [6,24,6,-3], [10,26,7,-1], [14,26,7], [10,24,6,-1], [5,16,2,-1], + [20,24,23,-1], [17,17,0], [18,18,1,-1], [11,24,6,-1], [14,15,0,-1], [14,15,0,-1], [16,20,4,-2], [16,20,4,-1], + [8,22,5,-1], [9,23,6,-1], [9,22,5,-1], [13,22,5,-1], [18,22,4], [17,22,4,-1], [17,19,1,-1], [17,22,4,-1], + [10,45,79,114,148,183,217,252,286,321,355,390,424,459,493,528], + [34,83,132,181,230,279,329,378], + [565,419] + ], + cmex10: [ + [7,29,28,-3], [7,29,28,-1], [6,29,28,-4], [6,29,28], [7,29,28,-4], [7,29,28], [7,29,28,-4], [7,29,28], + [10,29,28,-2], [10,29,28,-2], [8,29,28,-2], [8,29,28,-1], [2,16,15,-3], [7,16,15,-3], [12,29,28,-1], [12,29,28,-1], + [10,44,43,-4], [9,44,43,-1], [12,58,57,-5], [12,58,57,-1], [7,58,57,-6], [7,58,57], [8,58,57,-6], [8,58,57], + [8,58,57,-6], [8,58,57], [12,58,57,-3], [12,58,57,-3], [13,58,57,-3], [13,58,57,-2], [23,58,57,-1], [23,58,57,-1], + [14,72,71,-5], [14,72,71], [8,72,71,-6], [8,72,71], [9,72,71,-6], [9,72,71], [9,72,71,-6], [9,72,71], + [13,72,71,-3], [13,72,71,-3], [14,72,71,-3], [14,72,71,-2], [29,72,71,-1], [29,72,71,-1], [17,44,43,-1], [17,44,43,-1], + [14,44,43,-7], [14,44,43], [9,44,43,-7], [9,44,43], [9,44,43,-7], [9,44,43], [3,15,15,-7], [3,15,15,-6], + [9,22,22,-9], [9,22,22,-4], [9,23,22,-9], [9,23,22,-4], [9,45,44,-4], [9,45,44,-9], [4,9,8,-9], [2,15,15,-7], + [13,45,43,-7], [14,45,43], [3,16,15,-7], [3,16,15,-11], [11,44,43,-2], [10,44,43,-2], [18,24,24,-1], [25,34,34,-1], + [14,27,27,-1], [22,54,54,-1], [25,24,24,-1], [34,34,34,-1], [25,24,24,-1], [34,34,34,-1], [25,24,24,-1], [34,34,34,-1], + [23,24,24,-1], [21,24,24,-1], [14,27,27,-1], [18,24,24,-1], [18,24,24,-1], [18,24,24,-1], [18,24,24,-1], [18,24,24,-1], + [33,34,34,-1], [29,34,34,-1], [22,54,54,-1], [25,34,34,-1], [25,34,34,-1], [25,34,34,-1], [25,34,34,-1], [25,34,34,-1], + [21,24,24,-1], [29,34,34,-1], [14,5,-13], [24,6,-13], [35,6,-13], [14,4,-14], [24,3,-15], [35,3,-15], + [6,44,43,-5], [6,44,43], [8,44,43,-5], [8,44,43], [8,44,43,-5], [8,44,43], [12,44,43,-2], [12,44,43,-2], + [23,29,28,-2], [23,44,43,-2], [23,58,57,-2], [23,72,71,-2], [16,45,44,-2], [2,16,15,-16], [10,15,14,-16], [7,15,15,-6], + [12,15,15,-2], [12,15,15,-2], [12,9,6,1], [13,9,6,1], [12,8,0,1], [13,8,0,1], [17,15,15,-1], [17,15,15,-1], + [11,54,98,141,184,228,271,315,358,401,445,488,532,575,619,662], + [39,145,252,358,465,571,678,785], + [709,888] + ], + cmbx10: [ + [16,17,0], [21,17,0,-1], [19,18,1,-1], [18,17,0,-1], [17,17,0,-1], [21,17,0], [18,17,0,-1], [19,17,0,-1], + [18,17,0,-1], [19,17,0,-1], [18,17,0,-1], [18,17,0], [15,17,0], [15,17,0], [23,17,0], [23,17,0], + [6,11,0,-1], [9,16,5,2], [6,5,-12,-2], [6,5,-12,-5], [8,4,-12,-3], [10,5,-12,-2], [10,2,-13,-2], [7,5,-12,-7], + [8,5,5,-3], [14,18,1], [20,12,1], [21,12,1], [13,17,3], [24,17,0,-1], [26,18,1,-2], [19,20,2,-1], + [8,4,-6], [4,17,0,-2], [11,9,-8,-1], [21,22,5,-1], [12,20,2,-1], [21,20,2,-1], [19,18,1,-1], [5,9,-8,-2], + [8,24,6,-2], [8,24,6,-1], [11,11,-7,-1], [19,20,4,-1], [4,9,5,-2], [8,3,-4], [4,4,0,-2], [12,24,6,-1], + [12,17,1,-1], [10,16,0,-2], [12,16,0,-1], [12,17,1,-1], [13,16,0], [12,17,1,-1], [12,17,1,-1], [13,18,1,-1], + [12,17,1,-1], [12,17,1,-1], [4,11,0,-2], [4,16,5,-2], [4,17,5,-2], [19,8,-2,-1], [11,17,5,-1], [11,17,0,-1], + [19,18,1,-1], [19,17,0,-1], [19,17,0], [18,18,1,-1], [20,17,0], [18,17,0], [17,17,0], [20,18,1,-1], + [21,17,0], [10,17,0], [13,18,1], [21,17,0], [16,17,0], [25,17,0,-1], [21,17,0], [19,18,1,-1], + [18,17,0], [19,22,5,-1], [21,18,1], [13,18,1,-1], [18,17,0,-1], [20,18,1,-1], [21,18,1], [28,18,1], + [20,17,0], [21,17,0], [15,17,0,-1], [4,24,6,-3], [11,9,-8,-3], [5,24,6], [8,5,-12,-3], [4,4,-13,-2], + [5,9,-8,-1], [14,12,1], [15,18,1], [12,12,1], [15,18,1], [12,12,1], [10,17,0,-1], [14,16,5], + [14,17,0,-1], [6,17,0,-1], [9,22,5,2], [15,17,0], [6,17,0,-1], [22,11,0,-1], [14,11,0,-1], [13,12,1], + [15,16,5], [15,16,5], [11,11,0], [10,12,1], [10,17,1], [14,12,1,-1], [14,12,1], [20,12,1], + [14,11,0], [14,16,5], [11,11,0], [14,1,-6], [28,1,-6], [9,5,-12,-3], [10,3,-14,-2], [10,4,-13,-2], + [10,44,78,112,147,181,215,249,283,317,352,386,420,454,488,522], + [32,61,90,118,147,176,204,233], + [560,253] + ], + cmti10: [ + [16,17,0,-1], [17,18,0,-1], [16,18,1,-3], [15,18,0,-1], [17,17,0,-1], [20,17,0,-1], [17,17,0,-2], [15,17,0,-5], + [15,17,0,-3], [15,17,0,-5], [17,17,0,-2], [20,22,5,1], [16,22,5,1], [17,22,5,1], [23,22,5,1], [24,22,5,1], + [6,12,1,-2], [9,16,5,1], [4,5,-12,-7], [6,5,-12,-8], [7,3,-12,-6], [8,5,-12,-6], [9,2,-13,-5], [5,5,-13,-11], + [6,5,5,-2], [15,22,5,1], [16,12,1,-2], [16,12,1,-2], [13,16,3,-1], [22,17,0,-1], [23,18,1,-3], [24,20,2,4], + [7,4,-6,-2], [7,18,0,-2], [9,8,-9,-4], [18,22,5,-2], [15,18,1,-2], [18,20,2,-3], [17,19,1,-3], [4,8,-9,-5], + [10,24,6,-3], [10,24,6], [10,11,-7,-4], [15,16,2,-3], [5,8,5,-1], [7,2,-4,-2], [4,3,0,-2], [15,24,6], + [12,17,1,-2], [9,16,0,-2], [12,17,1,-2], [12,17,1,-2], [11,21,5,-1], [12,17,1,-2], [12,17,1,-2], [12,17,1,-3], + [12,17,1,-2], [12,17,1,-2], [6,11,0,-2], [7,16,5,-1], [7,18,6,-1], [17,6,-3,-2], [9,18,6,-2], [10,18,0,-4], + [16,18,1,-3], [16,18,0,-1], [17,17,0,-1], [17,18,1,-3], [18,17,0,-1], [17,17,0,-1], [17,17,0,-1], [17,18,1,-3], + [20,17,0,-1], [11,17,0,-1], [13,18,1,-2], [20,17,0,-1], [14,17,0,-1], [23,17,0,-1], [20,17,0,-1], [16,18,1,-3], + [17,17,0,-1], [16,22,5,-3], [17,18,1,-1], [15,18,1,-1], [16,17,0,-4], [17,18,1,-4], [16,18,1,-5], [22,18,1,-5], + [24,17,0,4], [16,17,0,-5], [15,17,0,-2], [10,24,6,-1], [9,8,-9,-6], [10,24,6,1], [7,4,-13,-6], [3,3,-13,-6], + [4,8,-9,-5], [11,12,1,-2], [9,18,1,-2], [10,12,1,-2], [12,18,1,-2], [10,12,1,-2], [12,22,5,1], [11,16,5,-1], + [12,18,1,-1], [6,17,1,-2], [10,21,5,1], [11,18,1,-1], [6,18,1,-2], [19,12,1,-2], [12,12,1,-2], [11,12,1,-2], + [13,16,5], [10,16,5,-2], [10,12,1,-2], [9,12,1,-1], [7,16,1,-2], [12,12,1,-2], [10,12,1,-2], [15,12,1,-2], + [12,12,1,-1], [11,16,5,-2], [10,12,1,-1], [12,1,-6,-2], [22,1,-6,-3], [8,5,-12,-6], [8,3,-13,-6], [8,3,-13,-6], + [10,39,68,98,127,156,186,215,245,274,303,333,362,391,421,450], + [32,61,90,118,147,176,204,233], + [482,253] + ] +}); + +jsMath.Img.AddFont(207,{ + cmr10: [ + [16,20,0,-1], [22,21,0,-1], [20,22,1,-1], [20,21,0], [18,20,0,-1], [20,20,0,-1], [19,20,0,-1], [20,21,0,-1], + [19,20,0,-1], [20,20,0,-1], [19,21,0,-1], [19,21,0], [16,21,0], [16,21,0], [24,21,0], [24,21,0], + [7,13,0,-1], [9,19,6,2], [6,6,-15,-3], [6,6,-15,-6], [8,4,-15,-3], [9,6,-15,-3], [11,2,-16,-2], [6,6,-15,-8], + [8,6,6,-3], [14,22,1], [20,14,1,-1], [22,14,1], [13,19,3,-1], [26,20,0], [27,22,1,-2], [20,24,2,-1], + [8,4,-8], [4,21,0,-2], [9,10,-11,-1], [22,27,6,-1], [12,24,2,-1], [22,24,2,-1], [20,22,1,-1], [4,9,-11,-2], + [8,30,8,-2], [8,30,8,-1], [11,13,-9,-2], [20,20,3,-1], [4,9,6,-2], [8,3,-5], [4,3,0,-2], [12,30,8,-1], + [13,21,1,-1], [11,20,0,-2], [12,20,0,-1], [13,21,1,-1], [14,20,0], [12,21,1,-1], [13,21,1,-1], [13,21,1,-1], + [13,21,1,-1], [13,21,1,-1], [4,13,0,-2], [4,19,6,-2], [4,22,7,-2], [20,8,-3,-1], [11,21,6,-1], [11,21,0,-1], + [20,22,1,-1], [21,21,0], [18,20,0,-1], [19,22,1,-1], [20,20,0,-1], [18,20,0,-1], [17,20,0,-1], [21,22,1,-1], + [20,20,0,-1], [10,20,0], [13,21,1,-1], [21,20,0,-1], [16,20,0,-1], [25,20,0,-1], [20,20,0,-1], [20,22,1,-1], + [18,20,0,-1], [21,27,6,-1], [21,21,1,-1], [14,22,1,-1], [19,20,0,-1], [20,21,1,-1], [22,21,1], [30,21,1], + [21,20,0], [22,20,0], [16,20,0,-1], [5,30,8,-3], [10,9,-11,-4], [5,30,8], [8,5,-15,-3], [4,4,-16,-2], + [4,9,-11,-2], [14,14,1,-1], [16,22,1], [11,14,1,-1], [15,22,1,-1], [12,14,1], [10,21,0,-1], [14,20,6], + [16,21,0], [7,20,0,-1], [9,26,6,2], [15,21,0], [7,21,0,-1], [24,13,0], [16,13,0], [14,14,1], + [16,19,6], [15,19,6,-1], [11,13,0], [10,14,1,-1], [10,19,1], [15,14,1,-1], [15,14,1], [21,14,1], + [15,13,0], [15,19,6], [12,13,0], [15,1,-7], [29,1,-7], [10,6,-15,-3], [10,4,-16,-2], [9,4,-16,-3], + [12,47,82,118,153,188,223,259,294,329,365,400,435,471,506,541], + [37,72,106,140,175,209,243,278], + [580,301] + ], + cmmi10: [ + [20,20,0,-1], [22,21,0,-1], [21,22,1,-1], [19,21,0,-1], [22,20,0,-1], [25,20,0,-1], [23,20,0,-1], [21,21,0], + [19,20,0], [20,20,0], [21,21,0,-2], [17,14,1,-1], [18,27,6], [16,20,7], [13,22,1,-1], [10,14,1,-1], + [13,27,6,-1], [15,20,7], [13,22,1,-1], [9,14,1,-1], [15,14,1,-1], [15,22,1,-1], [17,20,7], [15,13,0,-1], + [13,27,6], [17,14,1], [15,20,7], [16,14,1,-1], [15,14,1], [16,14,1], [16,26,6,-1], [17,19,6,-1], + [19,26,6], [18,14,1], [13,15,1], [17,22,1], [24,14,1], [13,19,6,-2], [12,17,4], [17,20,7,-1], + [27,9,-6,-1], [27,9,1,-1], [27,9,-6,-1], [27,9,1,-1], [6,8,-6,-1], [6,8,-6,-1], [14,16,1], [14,16,1], + [13,15,1,-1], [11,13,0,-2], [12,14,0,-1], [13,21,7,-1], [14,20,6], [12,20,7,-1], [13,21,1,-1], [13,21,7,-1], + [13,21,1,-1], [13,21,7,-1], [4,3,0,-2], [4,9,6,-2], [18,18,2,-2], [12,30,8,-1], [18,17,1,-2], [15,14,0], + [16,22,1,-1], [20,21,0,-1], [21,20,0,-1], [21,22,1,-1], [23,20,0,-1], [22,20,0,-1], [21,20,0,-1], [21,22,1,-1], + [25,20,0,-1], [14,20,0,-1], [17,21,1,-2], [25,20,0,-1], [18,20,0,-1], [30,20,0,-1], [25,20,0,-1], [21,22,1,-1], + [21,20,0,-1], [21,27,6,-1], [21,21,1,-1], [18,22,1,-1], [21,20,0], [20,21,1,-2], [22,21,1,-1], [30,21,1,-1], + [29,20,0,4], [21,20,0,-1], [20,20,0,-1], [9,23,1,-1], [7,28,7,-2], [9,28,7,-1], [27,8,-3,-1], [27,8,-3,-1], + [12,22,1], [14,14,1,-1], [11,22,1,-1], [12,14,1,-1], [14,22,1,-1], [12,14,1,-1], [15,27,6,-1], [14,19,6], + [15,22,1,-1], [9,21,1], [13,26,6,1], [14,22,1,-1], [7,22,1,-1], [25,14,1], [17,14,1], [13,14,1,-1], + [16,19,6,1], [12,19,6,-1], [13,14,1], [12,14,1,-1], [10,20,1], [16,14,1], [14,14,1], [20,14,1], + [16,14,1], [15,19,6], [13,14,1,-1], [9,14,1], [12,19,6,1], [16,20,7,-2], [13,6,-15,-5], [12,5,-15,-7], + [11,46,80,115,149,183,218,252,286,321,355,390,424,458,493,527], + [37,72,106,140,175,209,243,278], + [565,301] + ], + cmsy10: [ + [19,2,-6,-2], [4,4,-5,-2], [15,15,0,-4], [11,13,-1,-2], [20,17,1,-1], [15,15,0], [20,20,0,-1], [20,20,5,-1], + [20,20,3,-1], [20,20,3,-1], [20,20,3,-1], [20,20,3,-1], [20,20,3,-1], [27,28,7,-1], [12,12,-1,-1], [12,12,-1,-1], + [20,14,0,-1], [20,13,-1,-1], [19,23,4,-2], [19,23,4,-2], [19,23,4,-2], [19,23,4,-2], [19,23,4,-2], [19,23,4,-2], + [20,8,-3,-1], [20,13,-1,-1], [19,18,2,-2], [19,18,2,-2], [27,19,2,-1], [27,19,2,-1], [19,18,2,-2], [18,17,1,-2], + [27,11,-2,-1], [27,11,-2,-1], [11,26,6,-2], [11,26,6,-2], [27,11,-2,-1], [27,27,6,-1], [27,26,6,-1], [20,13,-1,-1], + [27,17,1,-1], [27,17,1,-1], [17,26,6], [17,27,6], [27,17,1,-1], [27,27,6,-1], [27,26,6,-1], [20,14,1,-1], + [7,16,-1,-1], [27,14,1,-1], [15,18,2,-2], [15,18,2,-2], [23,21,0,-1], [23,22,7,-1], [15,28,7,-4], [3,12,-1,-1], + [17,22,1], [14,21,0,-1], [17,9,-2,-1], [13,26,3,-1], [20,22,1,-1], [19,22,1,-1], [20,20,0,-1], [20,20,0,-1], + [15,20,0,-1], [23,23,2], [19,22,1,-1], [16,22,1], [23,20,0], [17,22,1], [24,21,1], [17,25,4,-1], + [24,22,2], [20,20,0,1], [24,24,4,-1], [21,22,1,-1], [18,22,1,-1], [33,23,2], [30,25,2,1], [22,22,1,-1], + [22,22,2], [20,25,4,-3], [25,21,1], [19,22,1], [23,21,0], [21,21,1,1], [19,22,2,-1], [29,22,2,-1], + [23,20,0,-1], [21,24,4], [22,20,0,-1], [17,19,1,-1], [17,19,1,-1], [17,19,1,-1], [17,19,1,-1], [17,19,1,-1], + [15,20,0,-1], [16,21,0,-1], [8,30,8,-5], [8,30,8], [8,30,8,-5], [8,30,8], [11,30,8,-2], [11,30,8,-2], + [7,30,8,-3], [7,30,8,-1], [2,30,8,-3], [8,30,8,-3], [11,31,8,-2], [17,31,8], [12,30,8,-1], [6,20,3,-1], + [23,30,28,-2], [20,20,0,-1], [22,21,1,-1], [13,28,7,-1], [17,18,0,-1], [17,18,0,-1], [19,23,4,-2], [20,23,4,-1], + [9,27,6,-2], [11,28,7,-1], [11,27,6,-1], [16,27,6,-1], [22,25,4], [20,26,5,-1], [20,22,1,-1], [20,25,4,-1], + [12,53,95,136,177,218,260,301,342,384,425,466,507,549,590,631], + [39,98,157,216,274,333,392,451], + [676,500] + ], + cmex10: [ + [8,36,34,-4], [8,36,34,-1], [7,36,34,-5], [7,36,34], [8,36,34,-5], [8,36,34], [8,36,34,-5], [8,36,34], + [11,36,34,-3], [11,36,34,-3], [10,36,34,-2], [9,36,34,-2], [2,19,18,-4], [8,19,18,-4], [14,36,34,-1], [14,36,34,-1], + [12,53,51,-5], [11,53,51,-1], [15,71,69,-6], [15,71,69,-1], [8,71,69,-7], [8,71,69], [10,71,69,-7], [10,71,69], + [10,71,69,-7], [10,71,69], [15,71,69,-3], [15,71,69,-3], [16,71,69,-3], [16,71,69,-2], [28,71,69,-1], [28,71,69,-1], + [16,88,86,-6], [16,88,86,-1], [9,88,86,-8], [9,88,86], [11,88,86,-8], [11,88,86], [11,88,86,-8], [11,88,86], + [16,88,86,-4], [16,88,86,-4], [17,88,86,-4], [17,88,86,-3], [35,88,86,-1], [35,88,86,-1], [21,53,51,-1], [21,53,51,-1], + [17,54,52,-8], [16,54,52,-1], [11,53,51,-9], [10,53,51], [11,53,51,-9], [10,53,51], [3,18,18,-9], [3,18,18,-7], + [10,27,27,-11], [10,27,27,-5], [10,27,26,-11], [10,28,27,-5], [10,54,53,-5], [10,54,53,-11], [4,10,9,-11], [2,18,18,-9], + [17,53,51,-8], [16,53,51,-1], [4,19,18,-8], [4,19,18,-13], [13,53,51,-3], [13,53,51,-2], [22,29,29,-1], [30,41,41,-1], + [17,33,33,-1], [27,65,65,-1], [30,29,29,-1], [42,41,41,-1], [30,29,29,-1], [42,41,41,-1], [30,29,29,-1], [42,41,41,-1], + [28,29,29,-1], [25,29,29,-1], [17,33,33,-1], [22,29,29,-1], [22,29,29,-1], [22,29,29,-1], [22,29,29,-1], [22,29,29,-1], + [40,41,41,-1], [35,41,41,-1], [27,65,65,-1], [30,41,41,-1], [30,41,41,-1], [30,41,41,-1], [30,41,41,-1], [30,41,41,-1], + [25,29,29,-1], [35,41,41,-1], [17,6,-16], [29,7,-16], [42,7,-16], [16,4,-17], [29,4,-18], [42,4,-18], + [8,53,51,-6], [8,53,51], [9,53,51,-6], [9,53,51], [9,53,51,-6], [9,53,51], [13,53,51,-3], [13,53,51,-3], + [27,35,34,-3], [27,52,51,-3], [27,70,69,-3], [27,87,86,-3], [19,54,53,-3], [2,19,18,-20], [12,19,17,-20], [9,18,18,-7], + [14,18,18,-3], [14,18,18,-3], [15,11,7,1], [15,11,7,1], [15,10,0,1], [15,10,0,1], [20,18,18,-1], [20,18,18,-1], + [13,65,117,169,221,273,325,377,428,480,532,584,636,688,740,792], + [45,173,300,428,555,683,810,938], + [849,1062] + ], + cmbx10: [ + [18,20,0,-1], [25,21,0,-1], [23,22,1,-1], [22,21,0,-1], [20,20,0,-1], [24,20,0,-1], [22,20,0,-1], [23,21,0,-1], + [22,20,0,-1], [23,20,0,-1], [22,21,0,-1], [22,21,0], [18,21,0], [18,21,0], [27,21,0], [27,21,0], + [8,13,0,-1], [10,19,6,2], [7,7,-14,-3], [7,7,-14,-7], [9,4,-15,-4], [11,7,-14,-3], [13,2,-16,-2], [7,6,-15,-9], + [10,6,6,-3], [16,22,1,-1], [23,15,1,-1], [24,15,1,-1], [16,19,3], [29,20,0,-1], [31,22,1,-2], [23,24,2,-1], + [10,4,-8], [6,21,0,-2], [13,11,-10,-1], [25,27,6,-1], [14,24,2,-1], [25,24,2,-1], [24,22,1,-1], [6,11,-10,-2], + [8,30,8,-3], [9,30,8,-1], [13,14,-8,-2], [23,23,4,-1], [6,11,6,-2], [10,3,-5], [5,5,0,-2], [14,30,8,-1], + [15,20,1,-1], [13,19,0,-2], [14,19,0,-1], [15,20,1,-1], [16,19,0], [14,20,1,-1], [15,20,1,-1], [16,21,1,-1], + [15,20,1,-1], [15,20,1,-1], [5,13,0,-2], [5,19,6,-2], [6,21,6,-2], [23,9,-3,-1], [13,21,6,-1], [13,21,0,-1], + [23,22,1,-1], [23,21,0,-1], [21,20,0,-1], [22,22,1,-1], [23,20,0,-1], [20,20,0,-1], [19,20,0,-1], [24,22,1,-1], + [24,20,0,-1], [11,20,0,-1], [16,21,1], [24,20,0,-1], [18,20,0,-1], [30,20,0,-1], [24,20,0,-1], [23,22,1,-1], + [20,20,0,-1], [23,27,6,-1], [24,21,1,-1], [16,22,1,-1], [21,20,0,-1], [24,21,1,-1], [25,21,1], [34,21,1], + [24,20,0,-1], [25,20,0], [18,20,0,-1], [6,30,8,-3], [13,10,-10,-4], [6,30,8], [10,5,-15,-3], [5,6,-15,-2], + [6,10,-10,-1], [16,15,1,-1], [17,22,1,-1], [13,15,1,-1], [17,22,1,-1], [15,15,1], [12,21,0,-1], [16,20,6,-1], + [17,21,0,-1], [8,21,0,-1], [10,27,6,2], [16,21,0,-1], [8,21,0,-1], [27,13,0,-1], [17,13,0,-1], [16,15,1], + [17,19,6,-1], [17,19,6,-1], [12,13,0,-1], [11,15,1,-1], [12,20,1], [17,14,1,-1], [17,14,1], [24,14,1], + [17,13,0], [17,19,6], [13,13,0,-1], [17,2,-7], [34,2,-7], [11,6,-15,-4], [11,4,-17,-3], [11,5,-16,-3], + [12,53,94,135,175,216,257,298,339,380,421,462,502,543,584,625], + [37,72,106,140,175,209,243,278], + [670,301] + ], + cmti10: [ + [20,20,0,-1], [20,21,0,-2], [19,22,1,-4], [18,21,0,-1], [20,20,0,-2], [24,20,0,-1], [21,20,0,-2], [19,21,0,-6], + [18,20,0,-4], [18,20,0,-6], [20,21,0,-2], [23,27,6,1], [19,27,6,1], [20,27,6,1], [28,27,6,1], [29,27,6,1], + [8,14,1,-2], [11,19,6,1], [5,7,-14,-8], [6,7,-14,-10], [8,5,-14,-8], [9,5,-15,-8], [11,2,-16,-6], [7,6,-15,-13], + [7,6,6,-3], [18,27,6,1], [19,14,1,-2], [18,14,1,-3], [14,19,3,-2], [27,20,0,-1], [27,22,1,-4], [21,24,2,-3], + [8,4,-8,-2], [8,21,0,-3], [10,10,-11,-5], [21,27,6,-3], [19,22,1,-2], [21,24,2,-4], [21,22,1,-3], [5,10,-11,-6], + [11,30,8,-4], [12,30,8], [12,13,-9,-5], [18,18,2,-4], [5,9,6,-2], [8,2,-5,-2], [4,3,0,-3], [18,30,8], + [14,21,1,-3], [11,20,0,-3], [14,21,1,-2], [15,21,1,-2], [13,26,6,-1], [14,21,1,-3], [14,21,1,-3], [14,21,1,-4], + [14,21,1,-2], [13,21,1,-3], [6,13,0,-3], [7,19,6,-2], [9,22,7,-1], [20,8,-3,-3], [11,22,7,-2], [11,21,0,-5], + [19,22,1,-4], [19,21,0,-1], [20,20,0,-2], [20,22,1,-4], [22,20,0,-1], [21,20,0,-1], [21,20,0,-1], [20,22,1,-4], + [24,20,0,-1], [14,20,0,-1], [16,21,1,-2], [24,20,0,-1], [17,20,0,-1], [27,20,0,-2], [24,20,0,-1], [19,22,1,-4], + [21,20,0,-1], [19,27,6,-4], [20,21,1,-1], [17,22,1,-2], [19,20,0,-5], [20,21,1,-5], [20,21,1,-6], [27,21,1,-6], + [28,20,0,4], [21,20,0,-5], [19,20,0,-2], [11,30,8,-2], [10,9,-11,-8], [12,30,8,1], [8,5,-15,-7], [4,4,-16,-7], + [5,9,-11,-6], [13,14,1,-3], [11,22,1,-3], [11,14,1,-3], [14,22,1,-3], [11,14,1,-3], [15,27,6,1], [14,19,6,-1], + [14,22,1,-2], [8,20,1,-2], [12,25,6,1], [13,22,1,-2], [7,22,1,-2], [23,14,1,-2], [15,14,1,-2], [12,14,1,-3], + [15,19,6], [12,19,6,-3], [13,14,1,-2], [11,14,1,-2], [9,20,1,-2], [15,14,1,-2], [13,14,1,-2], [19,14,1,-2], + [14,14,1,-1], [13,19,6,-2], [12,14,1,-2], [14,1,-7,-2], [27,1,-7,-3], [10,7,-14,-7], [10,4,-16,-7], [9,4,-16,-7], + [12,47,82,117,152,187,222,257,293,328,363,398,433,468,503,539], + [37,72,106,140,175,209,243,278], + [577,301] + ] +}); + +jsMath.Img.AddFont(249,{ + cmr10: [ + [19,24,0,-1], [26,25,0,-1], [24,25,1,-1], [22,25,0,-1], [21,23,0,-1], [24,24,0,-1], [21,24,0,-2], [23,24,0,-2], + [22,24,0,-1], [23,24,0,-2], [22,24,0,-1], [21,24,0,-1], [17,24,0,-1], [17,24,0,-1], [27,24,0,-1], [27,24,0,-1], + [8,15,0,-1], [10,22,7,2], [7,7,-17,-3], [7,7,-17,-7], [9,5,-17,-4], [11,7,-17,-3], [13,2,-19,-2], [7,7,-18,-9], + [9,7,7,-4], [15,25,1,-1], [23,17,1,-1], [25,17,1,-1], [15,22,4,-1], [29,24,0,-1], [32,25,1,-2], [24,27,2,-1], + [8,5,-9,-1], [4,25,0,-3], [11,11,-13,-1], [25,31,7,-2], [14,28,2,-1], [26,28,2,-1], [24,26,1,-1], [4,11,-13,-3], + [9,35,9,-3], [8,35,9,-2], [13,16,-10,-2], [23,23,3,-2], [4,11,7,-3], [10,3,-6], [4,4,0,-3], [13,35,9,-2], + [15,24,1,-1], [12,23,0,-3], [15,23,0,-1], [15,24,1,-1], [15,23,0,-1], [15,24,1,-1], [15,24,1,-1], [15,24,1,-2], + [15,24,1,-1], [15,24,1,-1], [4,15,0,-3], [4,22,7,-3], [4,25,8,-3], [23,9,-4,-2], [14,24,7,-1], [14,24,0,-1], + [24,25,1,-1], [24,25,0,-1], [22,24,0,-1], [22,25,1,-1], [23,24,0,-1], [22,24,0,-1], [20,24,0,-1], [24,25,1,-1], + [24,24,0,-1], [11,24,0,-1], [15,25,1,-1], [24,24,0,-1], [19,24,0,-1], [29,24,0,-1], [24,24,0,-1], [24,25,1,-1], + [21,24,0,-1], [24,31,7,-1], [24,25,1,-1], [16,25,1,-1], [23,23,0,-1], [24,25,1,-1], [25,25,1], [35,25,1], + [25,24,0], [26,24,0], [18,24,0,-1], [5,35,9,-4], [11,11,-13,-5], [6,35,9], [9,6,-18,-4], [4,4,-19,-3], + [5,11,-13,-2], [16,17,1,-1], [17,25,1,-1], [13,17,1,-1], [17,25,1,-1], [14,17,1,-1], [12,24,0,-1], [16,23,7,-1], + [18,24,0,-1], [8,23,0,-1], [10,30,7,2], [17,24,0,-1], [8,24,0,-1], [27,15,0,-1], [18,15,0,-1], [15,17,1,-1], + [17,22,7,-1], [17,22,7,-1], [12,15,0,-1], [12,17,1,-1], [12,22,1], [18,16,1,-1], [18,16,1], [24,16,1], + [18,15,0], [18,22,7], [13,15,0,-1], [17,2,-8], [34,2,-8], [11,7,-17,-4], [11,4,-19,-3], [11,4,-19,-3], + [14,56,99,141,184,226,269,311,354,396,439,481,524,566,609,651], + [46,87,128,170,211,253,294,335], + [698,363] + ], + cmmi10: [ + [24,24,0,-1], [26,25,0,-1], [25,25,1,-1], [22,25,0,-1], [26,23,0,-1], [29,24,0,-1], [26,24,0,-2], [23,24,0,-1], + [22,24,0], [23,24,0,-1], [25,24,0,-2], [20,16,1,-1], [20,31,7], [19,23,8], [15,26,1,-1], [12,16,1,-1], + [15,31,7,-1], [16,23,8,-1], [15,25,1,-1], [10,16,1,-1], [18,16,1,-1], [18,25,1,-1], [19,23,8,-1], [17,15,0,-1], + [16,31,7], [19,16,1,-1], [16,23,8,-1], [19,16,1,-1], [17,16,1,-1], [17,16,1,-1], [19,31,7,-1], [20,22,7,-1], + [21,31,7,-1], [21,16,1], [15,17,1], [18,25,1,-1], [27,16,1,-1], [15,22,7,-2], [13,19,4,-1], [20,23,8,-1], + [31,11,-7,-1], [31,11,1,-1], [31,11,-7,-1], [31,11,1,-1], [7,9,-7,-1], [7,9,-7,-1], [16,19,1], [16,19,1,-1], + [15,17,1,-1], [12,16,0,-3], [15,16,0,-1], [15,24,8,-1], [15,23,7,-1], [15,24,8,-1], [15,24,1,-1], [16,24,8,-1], + [15,24,1,-1], [15,24,8,-1], [4,4,0,-3], [4,11,7,-3], [22,21,2,-2], [13,35,9,-2], [22,21,2,-2], [17,17,0], + [19,26,1,-1], [24,25,0,-1], [25,24,0,-1], [25,25,1,-1], [27,24,0,-1], [25,24,0,-1], [25,24,0,-1], [25,25,1,-1], + [29,24,0,-1], [16,24,0,-1], [20,25,1,-2], [30,24,0,-1], [21,24,0,-1], [35,24,0,-1], [29,24,0,-1], [25,25,1,-1], + [25,24,0,-1], [25,31,7,-1], [25,25,1,-1], [21,25,1,-1], [24,23,0], [24,25,1,-2], [25,25,1,-2], [35,25,1,-1], + [28,24,0,-1], [25,24,0,-1], [23,24,0,-2], [11,27,1,-1], [9,33,8,-2], [11,33,8,-1], [30,9,-4,-2], [30,9,-4,-2], + [14,25,1], [16,16,1,-1], [14,25,1,-1], [14,16,1,-1], [17,25,1,-1], [14,16,1,-1], [18,31,7,-1], [17,22,7], + [18,25,1,-1], [9,24,1,-1], [15,30,7,1], [17,25,1,-1], [8,25,1,-1], [28,16,1,-1], [19,16,1,-1], [15,16,1,-1], + [18,22,7,1], [15,22,7,-1], [14,16,1,-1], [14,16,1,-1], [12,23,1], [18,16,1,-1], [15,16,1,-1], [23,16,1,-1], + [17,16,1,-1], [16,22,7,-1], [15,16,1,-1], [9,16,1,-1], [14,22,7,1], [19,24,8,-2], [16,8,-17,-6], [13,5,-18,-9], + [14,55,96,138,179,221,262,303,345,386,427,469,510,551,593,634], + [46,87,128,170,211,253,294,335], + [679,363] + ], + cmsy10: [ + [22,3,-7,-2], [4,5,-6,-3], [17,17,0,-5], [13,15,-1,-2], [23,19,1,-2], [17,17,0], [23,23,0,-2], [23,23,6,-2], + [24,23,3,-1], [24,23,3,-1], [24,23,3,-1], [24,23,3,-1], [24,23,3,-1], [31,33,8,-1], [14,15,-1,-1], [14,15,-1,-1], + [23,17,0,-2], [23,15,-1,-2], [22,27,5,-2], [22,27,5,-2], [22,27,5,-2], [22,27,5,-2], [22,27,5,-2], [22,27,5,-2], + [24,9,-4,-1], [23,16,-1,-2], [22,21,2,-2], [22,21,2,-2], [30,23,3,-2], [30,23,3,-2], [22,21,2,-2], [22,21,2,-2], + [30,13,-2,-2], [30,13,-2,-2], [13,31,7,-2], [13,31,7,-2], [30,13,-2,-2], [31,31,7,-2], [31,31,7,-2], [24,15,-1,-1], + [30,19,1,-2], [30,19,1,-2], [19,31,7,-1], [19,31,7,-1], [32,19,1,-1], [31,31,7,-1], [31,31,7,-1], [24,16,1,-1], + [8,18,-1,-1], [31,16,1,-1], [18,21,2,-2], [18,21,2,-2], [27,25,0,-2], [27,25,8,-2], [18,33,8,-4], [4,13,-2,-1], + [19,25,1], [15,24,0,-2], [19,10,-3,-2], [15,30,3,-1], [24,26,1,-1], [23,25,1,-1], [23,23,0,-2], [23,23,0,-2], + [18,24,0,-1], [26,27,2,-1], [22,25,1,-1], [19,25,1], [26,24,0], [19,25,1,-1], [29,26,2], [20,28,4,-1], + [28,26,2], [23,24,0,1], [28,28,4,-1], [24,25,1,-1], [22,25,1,-1], [37,26,2,-1], [35,29,2,1], [25,25,1,-2], + [25,26,2], [24,29,5,-3], [29,25,1], [22,25,1], [26,25,0,-1], [25,25,1,1], [22,26,2,-1], [35,26,2,-1], + [27,24,0,-1], [24,29,5,-1], [25,24,0,-1], [20,22,1,-1], [20,22,1,-1], [20,22,1,-1], [19,22,1,-2], [19,22,1,-2], + [18,24,0,-1], [17,24,0,-2], [10,35,9,-5], [10,35,9], [10,35,9,-5], [10,35,9], [13,35,9,-2], [13,35,9,-2], + [9,35,9,-3], [8,35,9,-2], [2,35,9,-4], [9,35,9,-4], [13,37,10,-2], [19,37,10,-1], [13,35,9,-2], [7,23,3,-1], + [27,35,33,-2], [24,24,0,-1], [26,26,2,-1], [15,33,8,-1], [19,21,0,-2], [19,21,0,-2], [22,27,5,-3], [22,27,5,-2], + [11,31,7,-2], [12,32,8,-2], [12,31,7,-2], [19,31,7,-1], [25,30,5,-1], [23,31,6,-2], [24,27,2,-1], [24,30,5,-1], + [14,64,114,163,213,263,312,362,412,461,511,561,610,660,710,759], + [48,119,190,260,331,402,472,543], + [814,603] + ], + cmex10: [ + [9,42,40,-5], [10,42,40,-1], [8,42,40,-6], [8,42,40], [10,42,40,-6], [10,42,40], [10,42,40,-6], [10,42,40], + [12,42,40,-4], [12,42,40,-4], [11,42,40,-3], [11,42,40,-2], [3,22,21,-4], [10,22,21,-4], [16,42,40,-2], [16,42,40,-2], + [13,62,60,-6], [14,62,60,-1], [17,83,81,-7], [17,83,81,-1], [10,83,81,-8], [10,83,81], [12,83,81,-8], [12,83,81], + [12,83,81,-8], [12,83,81], [17,83,81,-4], [17,83,81,-4], [19,83,81,-4], [19,83,81,-3], [32,83,81,-2], [32,83,81,-2], + [18,103,101,-8], [18,103,101,-1], [11,103,101,-9], [11,103,101], [13,103,101,-9], [13,103,101], [13,103,101,-9], [13,103,101], + [19,103,101,-4], [19,103,101,-4], [20,103,101,-4], [20,103,101,-3], [40,103,101,-2], [40,103,101,-2], [24,62,60,-2], [24,62,60,-2], + [20,63,61,-9], [19,63,61,-1], [12,62,60,-11], [12,62,60], [12,62,60,-11], [12,62,60], [3,21,21,-11], [3,21,21,-9], + [12,31,31,-13], [13,31,31,-5], [12,32,31,-13], [13,32,31,-5], [13,63,62,-5], [12,63,62,-13], [5,12,11,-13], [3,21,21,-10], + [20,62,60,-9], [19,62,60,-1], [5,22,21,-9], [4,22,21,-16], [15,62,60,-3], [14,62,60,-3], [26,34,34,-1], [35,48,48,-1], + [19,38,38,-2], [31,76,76,-1], [35,34,34,-1], [49,48,48,-1], [35,34,34,-1], [49,48,48,-1], [35,34,34,-1], [49,48,48,-1], + [33,34,34,-1], [30,34,34,-1], [19,38,38,-2], [26,34,34,-1], [26,34,34,-1], [26,34,34,-1], [25,34,34,-2], [25,34,34,-2], + [46,48,48,-1], [41,48,48,-1], [31,76,76,-1], [35,48,48,-1], [35,48,48,-1], [35,48,48,-1], [34,48,48,-2], [35,48,48,-1], + [30,34,34,-1], [41,48,48,-1], [19,7,-19], [34,8,-19], [49,8,-19], [19,5,-20], [34,5,-21], [49,5,-21], + [9,62,60,-7], [9,62,60], [11,62,60,-7], [11,62,60], [11,62,60,-7], [11,62,60], [15,62,60,-4], [15,62,60,-4], + [32,42,40,-3], [32,62,60,-3], [32,83,81,-3], [32,103,101,-3], [23,63,62,-3], [3,22,21,-23], [14,22,20,-23], [10,21,21,-8], + [16,21,21,-3], [16,21,21,-3], [17,13,8,1], [18,13,8,1], [17,12,0,1], [18,12,0,1], [24,21,21,-1], [24,21,21,-1], + [16,78,141,203,265,328,390,453,515,578,640,703,765,828,890,953], + [55,209,362,515,669,822,976,1129], + [1021,1278] + ], + cmbx10: [ + [21,24,0,-1], [29,24,0,-2], [27,25,1,-2], [25,24,0,-1], [24,23,0,-1], [29,24,0,-1], [24,24,0,-2], [27,24,0,-2], + [24,24,0,-2], [27,24,0,-2], [26,24,0,-1], [25,24,0,-1], [20,24,0,-1], [20,24,0,-1], [31,24,0,-1], [31,24,0,-1], + [9,16,0,-1], [12,23,7,2], [8,7,-17,-4], [8,7,-17,-8], [11,6,-17,-4], [13,7,-17,-3], [15,3,-18,-2], [9,6,-18,-10], + [11,7,7,-4], [19,25,1,-1], [27,17,1,-1], [29,17,1,-1], [18,23,4,-1], [34,24,0,-1], [37,25,1,-2], [27,28,2,-2], + [11,5,-9], [6,24,0,-3], [15,13,-11,-1], [29,31,7,-2], [16,28,2,-2], [29,28,2,-2], [28,25,1,-1], [7,13,-11,-2], + [10,35,9,-3], [10,35,9,-2], [15,16,-10,-2], [27,27,5,-2], [7,13,7,-2], [11,5,-5], [6,6,0,-2], [16,35,9,-2], + [17,24,1,-1], [15,23,0,-2], [17,23,0,-1], [17,24,1,-1], [18,23,0,-1], [16,24,1,-2], [17,24,1,-1], [17,24,1,-2], + [17,24,1,-1], [17,24,1,-1], [6,16,0,-2], [7,23,7,-2], [6,24,7,-3], [27,11,-3,-2], [15,24,7,-2], [15,24,0,-2], + [27,25,1,-2], [28,24,0,-1], [25,24,0,-1], [24,25,1,-2], [27,24,0,-1], [24,24,0,-1], [22,24,0,-1], [27,25,1,-2], + [29,24,0,-1], [13,24,0,-1], [18,25,1], [28,24,0,-1], [21,24,0,-1], [35,24,0,-1], [29,24,0,-1], [26,25,1,-2], + [24,24,0,-1], [26,31,7,-2], [29,25,1,-1], [18,25,1,-2], [25,23,0,-1], [28,25,1,-1], [29,25,1], [40,25,1], + [28,24,0,-1], [29,24,0], [20,24,0,-2], [6,35,9,-4], [16,13,-11,-4], [7,35,9], [11,6,-18,-4], [6,6,-18,-2], + [6,13,-11,-2], [18,17,1,-1], [20,25,1,-1], [16,17,1,-1], [20,25,1,-1], [16,17,1,-1], [14,24,0,-1], [18,23,7,-1], + [20,24,0,-1], [9,24,0,-1], [12,31,7,2], [19,24,0,-1], [9,24,0,-1], [31,16,0,-1], [20,16,0,-1], [18,17,1,-1], + [20,23,7,-1], [20,23,7,-1], [14,16,0,-1], [14,17,1,-1], [13,23,1], [20,17,1,-1], [20,17,1], [28,17,1], + [20,16,0], [20,23,7], [15,16,0,-1], [20,2,-8], [39,2,-8], [13,8,-17,-4], [14,4,-20,-3], [13,6,-18,-3], + [14,64,113,162,211,260,309,359,408,457,506,555,604,653,703,752], + [46,87,128,170,211,253,294,335], + [806,363] + ], + cmti10: [ + [22,24,0,-2], [24,25,0,-2], [22,25,1,-5], [20,25,0,-2], [24,23,0,-2], [27,24,0,-2], [25,24,0,-2], [22,24,0,-7], + [20,24,0,-5], [21,24,0,-7], [23,24,0,-3], [27,31,7,1], [22,31,7,1], [23,31,7,1], [33,31,7,1], [33,31,7,1], + [10,16,1,-2], [13,22,7,2], [6,7,-17,-9], [8,7,-17,-11], [10,5,-17,-9], [11,7,-17,-9], [12,1,-19,-8], [7,7,-18,-16], + [9,7,7,-3], [21,31,7,1], [22,16,1,-3], [22,16,1,-3], [17,23,4,-2], [31,24,0,-2], [31,25,1,-5], [24,28,2,-4], + [9,5,-9,-3], [10,25,0,-3], [12,11,-13,-6], [25,31,7,-4], [21,25,1,-3], [24,28,2,-5], [24,26,1,-4], [6,11,-13,-7], + [13,35,9,-5], [13,35,9], [14,16,-10,-6], [22,21,2,-4], [6,11,7,-2], [9,3,-6,-3], [5,4,0,-3], [21,35,9], + [15,24,1,-4], [12,23,0,-4], [17,24,1,-2], [17,24,1,-3], [15,30,7,-1], [17,24,1,-3], [16,24,1,-4], [17,24,1,-5], + [16,24,1,-3], [16,24,1,-3], [8,15,0,-3], [9,22,7,-2], [9,25,8,-2], [23,9,-4,-4], [13,25,8,-2], [13,25,0,-6], + [22,25,1,-5], [22,25,0,-2], [23,24,0,-2], [23,25,1,-5], [25,24,0,-2], [24,24,0,-2], [23,24,0,-2], [23,25,1,-5], + [27,24,0,-2], [15,24,0,-2], [19,25,1,-3], [28,24,0,-2], [20,24,0,-2], [32,24,0,-2], [27,24,0,-2], [22,25,1,-5], + [23,24,0,-2], [22,31,7,-5], [23,25,1,-2], [20,25,1,-2], [22,23,0,-6], [23,25,1,-6], [23,25,1,-7], [31,25,1,-7], + [33,24,0,5], [24,24,0,-6], [22,24,0,-2], [13,35,9,-2], [12,11,-13,-9], [14,35,9,1], [9,6,-18,-9], [5,4,-19,-8], + [6,11,-13,-7], [16,16,1,-3], [13,25,1,-3], [13,16,1,-3], [16,25,1,-3], [13,16,1,-3], [17,31,7,1], [16,22,7,-1], + [17,25,1,-2], [10,24,-294,-2], [15,30,7,2], [15,25,1,-2], [8,25,1,-3], [27,16,1,-2], [18,16,1,-2], [15,16,1,-3], + [18,22,7], [14,22,7,-3], [15,16,1,-2], [13,16,1,-2], [10,23,1,-3], [17,16,1,-2], [15,16,1,-2], [22,16,1,-2], + [17,16,1,-1], [16,22,7,-2], [14,16,1,-2], [16,2,-8,-3], [32,2,-8,-4], [11,7,-17,-9], [12,4,-19,-8], [10,4,-19,-9], + [14,56,98,141,183,225,267,310,352,394,437,479,521,563,606,648], + [46,87,128,170,211,253,294,335], + [694,363] + ] +}); + +jsMath.Img.AddFont(298,{ + cmr10: [ + [23,28,0,-1], [31,30,0,-2], [28,30,1,-2], [27,30,0,-1], [25,28,0,-1], [29,28,0,-1], [26,28,0,-2], [28,29,0,-2], + [26,28,0,-2], [28,28,0,-2], [27,29,0,-1], [25,29,0,-1], [21,29,0,-1], [21,29,0,-1], [32,29,0,-1], [32,29,0,-1], + [10,19,0,-1], [11,28,9,2], [8,8,-21,-4], [8,8,-21,-8], [11,5,-21,-5], [13,8,-21,-4], [16,3,-22,-2], [9,8,-22,-11], + [10,9,9,-5], [19,30,1,-1], [28,20,1,-1], [30,20,1,-1], [18,26,4,-1], [35,28,0,-1], [39,30,1,-2], [28,34,3,-2], + [10,5,-11,-1], [5,30,0,-3], [14,13,-16,-1], [30,37,8,-2], [17,34,3,-2], [30,34,3,-2], [29,31,1,-1], [6,13,-16,-3], + [10,42,11,-4], [10,42,11,-2], [16,18,-13,-2], [28,28,4,-2], [6,13,8,-3], [12,3,-7], [5,5,0,-3], [17,42,11,-2], + [18,29,1,-1], [15,28,0,-3], [17,28,0,-2], [18,29,1,-1], [19,28,0,-1], [17,29,1,-2], [18,29,1,-1], [18,29,1,-2], + [18,29,1,-1], [18,29,1,-1], [5,18,0,-3], [5,26,8,-3], [5,30,9,-3], [28,10,-5,-2], [15,30,9,-2], [15,29,0,-2], + [28,30,1,-2], [29,30,0,-1], [26,28,0,-1], [26,30,1,-2], [28,28,0,-1], [26,28,0,-1], [24,28,0,-1], [29,30,1,-2], + [29,28,0,-1], [13,28,0,-1], [19,29,1,-1], [30,28,0,-1], [23,28,0,-1], [35,28,0,-1], [29,28,0,-1], [28,30,1,-2], + [25,28,0,-1], [28,37,8,-2], [29,29,1,-1], [19,30,1,-2], [27,28,0,-1], [29,29,1,-1], [30,29,1], [42,29,1], + [29,28,0,-1], [31,28,0], [21,28,0,-2], [7,42,11,-4], [14,13,-16,-6], [7,42,11], [11,7,-22,-5], [5,5,-23,-3], + [5,13,-16,-3], [20,20,1,-1], [21,30,1,-1], [16,20,1,-1], [21,30,1,-1], [16,20,1,-1], [14,29,0,-1], [19,28,9,-1], + [21,29,0,-1], [10,28,0,-1], [11,37,9,2], [20,29,0,-1], [10,29,0,-1], [33,19,0,-1], [21,19,0,-1], [19,20,1,-1], + [21,27,8,-1], [21,27,8,-1], [14,19,0,-1], [14,20,1,-1], [14,27,1], [21,20,1,-1], [21,19,1], [29,19,1], + [22,18,0], [21,27,9], [16,18,0,-1], [21,2,-10], [41,2,-10], [13,8,-21,-5], [14,5,-23,-3], [13,5,-23,-4], + [17,67,118,169,220,271,322,373,423,474,525,576,627,678,729,780], + [55,104,154,203,253,302,352,401], + [835,434] + ], + cmmi10: [ + [29,28,0,-1], [31,30,0,-2], [29,30,1,-2], [27,30,0,-1], [30,28,0,-2], [35,28,0,-1], [31,28,0,-2], [28,29,0,-1], + [26,28,0,-1], [28,28,0,-1], [30,29,0,-3], [24,20,1,-1], [24,37,8,-1], [23,28,9], [18,31,1,-1], [15,19,1,-1], + [19,38,9,-1], [20,28,9,-1], [18,30,1,-1], [12,20,1,-2], [21,20,1,-2], [21,30,1,-2], [23,27,9,-1], [20,19,0,-2], + [18,38,9,-1], [23,19,1,-1], [20,28,9,-1], [23,19,1,-1], [20,19,1,-1], [21,20,1,-1], [22,38,9,-2], [24,28,9,-1], + [25,38,9,-1], [25,19,1], [17,20,1,-1], [22,30,1,-1], [33,19,1,-1], [18,27,8,-3], [16,24,5,-1], [24,28,9,-2], + [37,12,-9,-2], [37,13,1,-2], [37,12,-9,-2], [37,13,1,-2], [7,10,-9,-2], [8,10,-9,-2], [19,22,1,-1], [19,22,1,-1], + [18,20,1,-1], [15,19,0,-3], [18,19,0,-1], [18,28,9,-1], [19,27,8,-1], [17,28,9,-2], [18,29,1,-1], [18,28,9,-2], + [18,29,1,-1], [18,28,9,-1], [5,5,0,-3], [6,13,8,-3], [26,25,2,-3], [17,42,11,-2], [26,25,2,-3], [21,20,0], + [23,31,1,-1], [29,30,0,-1], [30,28,0,-1], [30,30,1,-2], [32,28,0,-1], [31,28,0,-1], [30,28,0,-1], [30,30,1,-2], + [36,28,0,-1], [20,28,0,-1], [24,29,1,-2], [36,28,0,-1], [26,28,0,-1], [42,28,0,-1], [36,28,0,-1], [29,30,1,-2], + [30,28,0,-1], [29,37,8,-2], [30,29,1,-1], [25,30,1,-2], [28,28,0,-1], [30,29,1,-2], [30,29,1,-2], [41,29,1,-2], + [34,28,0,-1], [31,28,0,-1], [28,28,0,-2], [12,32,1,-2], [10,39,9,-3], [12,39,9,-2], [37,11,-5,-2], [37,11,-5,-2], + [17,30,1], [20,20,1,-1], [16,30,1,-1], [17,20,1,-1], [20,30,1,-1], [17,20,1,-1], [21,38,9,-2], [20,28,9], + [21,30,1,-2], [11,28,1,-1], [18,36,9,1], [19,30,1,-2], [10,30,1,-1], [34,20,1,-1], [23,20,1,-1], [19,20,1,-1], + [23,27,8,2], [18,27,8,-1], [17,20,1,-1], [16,20,1,-2], [13,27,1,-1], [22,20,1,-1], [19,20,1,-1], [28,20,1,-1], + [21,20,1,-1], [20,28,9,-1], [18,20,1,-1], [11,20,1,-1], [16,28,9,1], [23,28,9,-3], [19,9,-21,-7], [17,6,-22,-10], + [16,66,115,165,214,264,313,363,412,462,511,561,610,660,709,759], + [55,104,154,203,253,302,352,401], + [813,434] + ], + cmsy10: [ + [26,3,-9,-3], [5,5,-8,-3], [20,20,0,-6], [16,18,-1,-2], [28,24,2,-2], [20,20,0], [28,28,0,-2], [28,28,7,-2], + [28,28,4,-2], [28,28,4,-2], [28,28,4,-2], [28,28,4,-2], [28,28,4,-2], [37,39,9,-2], [17,17,-2,-2], [17,17,-2,-2], + [28,20,0,-2], [28,18,-1,-2], [26,33,6,-3], [26,33,6,-3], [26,32,6,-3], [26,32,6,-3], [26,32,6,-3], [26,32,6,-3], + [28,10,-5,-2], [28,18,-2,-2], [26,25,2,-3], [26,25,2,-3], [37,27,3,-2], [37,27,3,-2], [26,24,2,-3], [26,24,2,-3], + [37,15,-3,-2], [37,15,-3,-2], [15,37,8,-3], [15,37,8,-3], [37,15,-3,-2], [37,37,8,-2], [37,37,8,-2], [28,18,-1,-2], + [37,23,1,-2], [37,23,1,-2], [23,37,8,-1], [23,37,8,-1], [39,23,1,-1], [37,37,8,-2], [37,37,8,-2], [28,20,1,-2], + [10,22,-1,-1], [37,20,1,-2], [21,25,2,-3], [21,25,2,-3], [32,30,0,-2], [32,30,9,-2], [22,39,9,-5], [3,16,-2,-2], + [23,30,1], [19,29,0,-2], [23,12,-3,-2], [18,36,4,-1], [28,31,1,-2], [27,30,1,-2], [28,28,0,-2], [28,28,0,-2], + [21,29,0,-2], [32,32,2,-1], [27,30,1,-1], [22,30,1], [32,28,0], [23,30,1,-1], [34,30,2], [24,34,5,-1], + [34,30,2], [27,28,0,1], [34,33,5,-1], [29,30,1,-1], [26,30,1,-1], [45,31,2,-1], [42,34,2,2], [30,30,1,-2], + [30,30,2], [29,35,6,-4], [35,29,1], [27,30,1], [32,30,0,-1], [30,30,2,1], [26,30,2,-1], [42,30,2,-1], + [32,28,0,-2], [29,34,6,-1], [31,28,0,-1], [23,26,1,-2], [23,26,1,-2], [23,26,1,-2], [23,26,1,-2], [23,26,1,-2], + [21,29,0,-2], [21,29,0,-2], [11,42,11,-7], [11,42,11], [11,42,11,-7], [10,42,11,-1], [15,42,11,-3], [15,42,11,-3], + [10,42,11,-4], [10,42,11,-2], [3,42,11,-4], [10,42,11,-5], [15,44,12,-3], [23,44,12,-1], [17,42,11,-2], [7,28,4,-2], + [32,42,40,-3], [29,28,0,-1], [31,30,2,-2], [18,39,9,-2], [23,25,0,-2], [23,25,0,-2], [27,33,6,-3], [27,33,6,-2], + [14,38,9,-2], [14,38,9,-2], [14,38,9,-2], [22,37,8,-2], [30,36,6,-1], [28,37,7,-2], [28,32,2,-2], [28,36,6,-2], + [17,77,136,196,255,314,374,433,493,552,612,671,730,790,849,909], + [58,142,227,311,396,481,565,650], + [974,721] + ], + cmex10: [ + [11,50,48,-6], [12,50,48,-1], [9,50,48,-8], [9,50,48], [11,50,48,-8], [11,50,48], [11,50,48,-8], [11,50,48], + [16,50,48,-4], [16,50,48,-4], [12,50,48,-4], [13,50,48,-3], [3,27,26,-5], [12,27,26,-5], [20,50,48,-2], [20,50,48,-2], + [16,75,73,-7], [17,75,73,-1], [21,99,97,-8], [21,99,97,-1], [11,99,97,-10], [12,99,97], [14,99,97,-10], [14,99,97], + [14,99,97,-10], [14,99,97], [21,99,97,-5], [21,99,97,-5], [22,99,97,-5], [22,99,97,-4], [39,99,97,-2], [39,99,97,-2], + [22,124,122,-9], [22,124,122,-1], [13,124,122,-11], [13,124,122], [15,124,122,-11], [15,124,122], [15,124,122,-11], [15,124,122], + [23,124,122,-5], [23,124,122,-5], [24,124,122,-5], [24,124,122,-4], [48,124,122,-2], [48,124,122,-2], [29,75,73,-2], [29,74,72,-2], + [24,75,73,-11], [23,75,73,-1], [14,75,73,-13], [14,75,73], [14,75,73,-13], [14,75,73], [4,25,25,-13], [3,25,25,-11], + [15,38,38,-15], [14,38,38,-7], [15,38,37,-15], [14,38,37,-7], [14,76,75,-7], [15,76,75,-15], [6,14,13,-15], [3,25,25,-12], + [24,75,73,-11], [23,75,73,-1], [6,26,25,-11], [5,26,25,-19], [18,75,73,-4], [18,75,73,-3], [30,41,41,-2], [42,58,58,-2], + [23,46,46,-2], [37,92,92,-2], [42,41,41,-2], [58,58,58,-2], [42,41,41,-2], [58,58,58,-2], [42,41,41,-2], [58,58,58,-2], + [39,41,41,-2], [35,41,41,-2], [23,46,46,-2], [30,41,41,-2], [30,41,41,-2], [30,41,41,-2], [30,41,41,-2], [30,41,41,-2], + [55,58,58,-2], [49,58,58,-2], [37,92,92,-2], [42,58,58,-2], [42,58,58,-2], [42,58,58,-2], [42,58,58,-2], [42,58,58,-2], + [35,41,41,-2], [49,58,58,-2], [23,8,-23], [41,9,-23], [60,9,-23], [23,6,-24], [41,6,-25], [59,6,-25], + [10,75,73,-9], [10,75,73], [12,75,73,-9], [13,75,73], [12,75,73,-9], [13,75,73], [19,75,73,-4], [19,75,73,-4], + [38,50,48,-4], [38,75,73,-4], [38,99,97,-4], [38,124,122,-4], [27,75,74,-4], [3,27,26,-28], [16,26,24,-28], [12,25,25,-10], + [19,25,25,-4], [19,25,25,-4], [20,14,9,1], [21,14,9,1], [20,14,0,1], [21,14,0,1], [28,25,25,-2], [28,25,25,-2], + [19,93,168,243,318,392,467,542,617,692,766,841,916,991,1066,1140], + [66,249,433,617,800,984,1167,1351], + [1222,1530] + ], + cmbx10: [ + [26,28,0,-1], [35,29,0,-2], [32,30,1,-2], [31,29,0,-1], [28,28,0,-2], [35,28,0,-1], [30,29,0,-2], [32,29,0,-2], + [30,29,0,-2], [32,29,0,-2], [30,29,0,-2], [30,29,0,-1], [24,29,0,-1], [24,29,0,-1], [37,29,0,-1], [37,29,0,-1], + [11,19,0,-1], [14,28,9,3], [10,8,-21,-4], [10,8,-21,-9], [13,6,-21,-5], [15,9,-20,-4], [18,3,-22,-3], [10,7,-22,-13], + [13,9,9,-5], [23,30,1,-1], [32,20,1,-1], [35,20,1,-1], [22,28,5,-1], [41,29,0,-1], [44,30,1,-3], [32,34,3,-2], + [14,6,-11], [7,29,0,-4], [18,15,-14,-1], [35,37,8,-2], [19,34,3,-2], [35,34,3,-2], [33,30,1,-2], [8,15,-14,-3], + [12,42,11,-4], [12,42,11,-2], [18,19,-12,-3], [32,32,6,-2], [8,15,8,-3], [13,5,-7], [7,7,0,-3], [19,42,11,-2], + [21,28,1,-1], [18,27,0,-3], [20,27,0,-2], [20,28,1,-2], [22,27,0,-1], [20,28,1,-2], [20,28,1,-2], [21,29,1,-2], + [20,28,1,-2], [20,28,1,-2], [7,19,0,-3], [7,27,8,-3], [7,30,9,-4], [32,13,-4,-2], [18,30,9,-2], [18,29,0,-2], + [32,30,1,-2], [33,29,0,-1], [30,29,0,-1], [30,30,1,-2], [33,29,0,-1], [29,28,0,-1], [27,28,0,-1], [33,30,1,-2], + [35,29,0,-1], [16,29,0,-1], [21,30,1,-1], [34,29,0,-1], [26,29,0,-1], [43,29,0,-1], [35,29,0,-1], [31,30,1,-2], + [29,29,0,-1], [31,37,8,-2], [35,30,1,-1], [22,30,1,-2], [30,28,0,-1], [34,30,1,-1], [34,30,1,-1], [47,30,1,-1], + [34,29,0,-1], [35,29,0], [25,29,0,-2], [7,42,11,-5], [19,15,-14,-5], [7,42,11,-1], [13,8,-21,-5], [7,7,-22,-3], + [8,15,-14,-2], [22,20,1,-1], [24,30,1,-1], [19,20,1,-1], [24,30,1,-1], [20,20,1,-1], [17,29,0,-1], [22,28,9,-1], + [25,29,0,-1], [11,29,0,-1], [14,38,9,3], [24,29,0,-1], [11,29,0,-1], [38,19,0,-1], [25,19,0,-1], [22,20,1,-1], + [24,27,8,-1], [24,27,8,-1], [18,19,0,-1], [16,20,1,-1], [16,27,1], [25,20,1,-1], [23,20,1,-1], [32,20,1,-1], + [24,19,0], [24,28,9], [18,19,0,-1], [24,2,-10], [48,2,-10], [16,9,-21,-5], [16,5,-24,-4], [16,7,-22,-4], + [17,76,135,194,253,311,370,429,488,547,606,664,723,782,841,900], + [55,104,154,203,253,302,352,401], + [964,434] + ], + cmti10: [ + [27,28,0,-2], [28,30,0,-3], [27,30,1,-6], [25,30,0,-2], [28,28,0,-3], [33,28,0,-2], [29,28,0,-3], [27,29,0,-8], + [24,28,0,-6], [26,28,0,-8], [28,29,0,-4], [32,38,9,1], [26,38,9,1], [27,38,9,1], [39,38,9,1], [40,38,9,1], + [11,20,1,-3], [16,28,9,2], [6,9,-20,-12], [9,9,-20,-14], [11,6,-20,-11], [13,8,-21,-11], [15,3,-22,-9], [9,8,-22,-19], + [10,8,8,-4], [25,38,9,1], [27,20,1,-3], [26,20,1,-4], [21,27,5,-2], [37,28,0,-2], [37,30,1,-6], [30,34,3,-4], + [11,5,-11,-3], [12,30,0,-4], [14,13,-16,-7], [30,37,8,-4], [26,30,1,-3], [29,34,3,-6], [28,31,1,-5], [7,13,-16,-9], + [16,42,11,-6], [16,42,11], [16,18,-13,-8], [26,26,3,-5], [7,13,8,-3], [11,3,-7,-3], [6,5,0,-4], [26,42,11], + [19,29,1,-4], [15,28,0,-4], [20,29,1,-3], [20,29,1,-3], [19,36,8,-1], [20,29,1,-4], [20,29,1,-4], [20,29,1,-6], + [19,29,1,-4], [19,29,1,-4], [9,18,0,-4], [10,26,8,-3], [12,30,9,-2], [28,10,-5,-4], [16,30,9,-3], [15,30,0,-8], + [27,30,1,-6], [27,30,0,-2], [29,28,0,-2], [28,30,1,-6], [30,28,0,-2], [29,28,0,-2], [28,28,0,-2], [28,30,1,-6], + [33,28,0,-2], [19,28,0,-2], [23,29,1,-3], [34,28,0,-2], [24,28,0,-2], [39,28,0,-2], [33,28,0,-2], [27,30,1,-6], + [28,28,0,-2], [27,37,8,-6], [28,29,1,-2], [23,30,1,-3], [26,28,0,-7], [27,29,1,-8], [28,29,1,-8], [37,29,1,-8], + [40,28,0,6], [28,28,0,-8], [26,28,0,-3], [16,42,11,-3], [14,13,-16,-11], [16,42,11,1], [11,7,-22,-11], [5,5,-23,-10], + [7,13,-16,-8], [18,20,1,-4], [15,30,1,-4], [16,20,1,-4], [19,30,1,-4], [16,20,1,-4], [20,38,9,1], [18,28,9,-2], + [19,30,1,-3], [11,28,1,-3], [17,36,9,2], [18,30,1,-3], [10,30,1,-3], [32,20,1,-3], [21,20,1,-3], [17,20,1,-4], + [21,27,8], [17,27,8,-4], [17,20,1,-3], [15,20,1,-3], [13,27,1,-3], [20,20,1,-3], [18,20,1,-3], [26,20,1,-3], + [20,20,1,-2], [19,28,9,-3], [17,20,1,-2], [20,2,-10,-3], [38,2,-10,-5], [13,9,-20,-11], [14,5,-23,-10], [12,5,-23,-11], + [17,67,118,168,219,270,320,371,421,472,522,573,624,674,725,775], + [55,104,154,203,253,302,352,401], + [831,434] + ] +}); + +jsMath.Img.AddFont(358,{ + cmr10: [ + [28,34,0,-1], [37,35,0,-2], [34,36,1,-2], [32,35,0,-1], [29,34,0,-2], [35,34,0,-1], [31,34,0,-2], [34,35,0,-2], + [31,34,0,-2], [34,34,0,-2], [32,35,0,-2], [30,35,0,-1], [25,35,0,-1], [25,35,0,-1], [39,35,0,-1], [39,35,0,-1], + [12,22,0,-1], [13,32,10,2], [10,10,-25,-5], [10,10,-25,-10], [13,7,-25,-6], [16,9,-25,-4], [18,2,-27,-3], [10,10,-26,-13], + [12,9,10,-6], [23,36,1,-1], [32,23,1,-2], [36,23,1,-1], [22,31,5,-1], [42,34,0,-1], [46,37,2,-3], [34,39,3,-2], + [12,6,-13,-1], [6,35,0,-4], [16,15,-19,-1], [36,44,10,-2], [20,40,3,-2], [36,40,3,-2], [34,38,2,-2], [7,15,-19,-4], + [13,50,13,-4], [13,50,13,-2], [19,22,-15,-3], [34,33,4,-2], [6,16,10,-4], [14,3,-9], [6,6,0,-4], [20,50,13,-2], + [22,35,2,-1], [17,33,0,-4], [20,33,0,-2], [21,35,2,-2], [23,34,0,-1], [20,35,2,-2], [21,35,2,-2], [22,35,1,-2], + [21,35,2,-2], [21,34,1,-2], [6,22,0,-4], [6,32,10,-4], [6,36,11,-4], [34,12,-6,-2], [19,35,10,-2], [19,35,0,-2], + [34,36,1,-2], [35,35,0,-1], [31,34,0,-1], [31,37,2,-2], [34,34,0,-1], [31,34,0,-1], [29,34,0,-1], [34,37,2,-2], + [35,34,0,-1], [16,34,0,-1], [21,35,1,-2], [36,34,0,-1], [28,34,0,-1], [43,34,0,-1], [35,34,0,-1], [34,36,1,-2], + [30,34,0,-1], [34,45,10,-2], [35,35,1,-1], [23,37,2,-2], [33,34,0,-1], [35,35,1,-1], [36,35,1], [50,35,1], + [35,34,0,-1], [37,34,0], [26,34,0,-2], [8,50,13,-5], [16,15,-19,-7], [7,50,13,-1], [14,8,-26,-5], [6,6,-27,-4], + [7,15,-19,-3], [23,23,1,-2], [25,35,1,-1], [20,23,1,-1], [25,35,1,-1], [20,23,1,-1], [17,35,0,-1], [23,34,11,-1], + [26,34,0,-1], [12,33,0,-1], [13,43,10,2], [24,34,0,-1], [12,34,0,-1], [39,22,0,-1], [26,22,0,-1], [23,23,1,-1], + [25,32,10,-1], [25,32,10,-1], [17,22,0,-1], [17,23,1,-1], [16,32,1,-1], [26,23,1,-1], [25,23,1], [35,23,1], + [26,22,0], [25,32,10], [19,22,0,-1], [25,2,-12], [49,2,-12], [15,10,-25,-6], [17,5,-28,-4], [15,6,-27,-5], + [20,81,142,203,264,325,387,448,509,570,631,692,753,814,875,937], + [64,124,183,243,302,362,421,481], + [1003,521] + ], + cmmi10: [ + [34,34,0,-2], [37,35,0,-2], [35,37,2,-2], [32,35,0,-1], [36,34,0,-2], [42,34,0,-2], [38,34,0,-2], [34,35,0,-1], + [31,34,0,-1], [33,34,0,-1], [36,35,0,-3], [28,23,1,-2], [28,45,10,-1], [27,33,11], [21,36,1,-2], [17,23,1,-2], + [22,45,10,-2], [24,33,11,-1], [21,36,1,-2], [14,23,1,-2], [25,23,1,-2], [25,35,1,-2], [27,33,11,-1], [24,22,0,-2], + [21,45,10,-1], [27,23,1,-1], [24,33,11,-1], [27,23,1,-1], [24,23,1,-1], [25,23,1,-1], [26,44,10,-2], [28,32,10,-1], + [31,44,10,-1], [30,23,1], [20,25,2,-1], [27,36,1,-1], [39,23,1,-1], [22,32,10,-3], [19,28,6,-1], [29,33,11,-2], + [45,14,-11,-2], [45,15,1,-2], [45,14,-11,-2], [45,15,1,-2], [9,12,-11,-2], [9,12,-11,-2], [23,26,1,-1], [23,26,1,-1], + [21,25,2,-2], [17,23,0,-4], [20,23,0,-2], [21,34,11,-2], [22,33,10,-1], [20,34,11,-2], [21,35,2,-2], [22,34,11,-2], + [21,35,2,-2], [21,34,11,-2], [6,6,0,-4], [6,16,10,-4], [30,29,2,-4], [20,50,13,-2], [30,29,2,-4], [25,24,0], + [26,36,1,-2], [35,35,0,-1], [35,34,0,-2], [36,37,2,-2], [38,34,0,-2], [37,34,0,-1], [36,34,0,-1], [36,37,2,-2], + [42,34,0,-2], [24,34,0,-1], [28,35,1,-3], [43,34,0,-1], [30,34,0,-2], [50,34,0,-2], [42,34,0,-2], [35,37,2,-2], + [35,34,0,-2], [35,45,10,-2], [35,35,1,-2], [30,37,2,-2], [34,34,0,-1], [35,36,2,-3], [36,35,1,-2], [50,35,1,-2], + [41,34,0,-1], [37,34,0,-1], [34,34,0,-2], [15,38,1,-2], [13,47,11,-3], [15,46,11,-2], [45,13,-6,-2], [45,13,-6,-2], + [20,36,1], [23,23,1,-2], [19,35,1,-2], [19,23,1,-2], [24,35,1,-2], [19,23,1,-2], [25,45,10,-2], [24,32,10], + [25,35,1,-2], [14,34,1,-1], [21,43,10,1], [23,35,1,-2], [11,35,1,-2], [41,23,1,-1], [27,23,1,-1], [21,23,1,-2], + [26,32,10,2], [20,32,10,-2], [21,23,1,-1], [19,23,1,-2], [16,32,1,-1], [26,23,1,-1], [22,23,1,-1], [33,23,1,-1], + [25,23,1,-1], [23,32,10,-1], [21,23,1,-2], [14,23,1,-1], [19,32,10,1], [28,34,11,-3], [22,10,-25,-9], [19,7,-26,-13], + [20,79,139,198,258,317,377,436,495,555,614,674,733,793,852,912], + [64,124,183,243,302,362,421,481], + [977,521] + ], + cmsy10: [ + [30,3,-11,-4], [6,6,-9,-4], [24,24,0,-7], [19,22,-1,-3], [34,28,2,-2], [24,24,0], [34,33,0,-2], [34,34,9,-2], + [34,33,4,-2], [34,33,4,-2], [34,33,4,-2], [34,33,4,-2], [34,33,4,-2], [45,47,11,-2], [20,20,-2,-2], [20,20,-2,-2], + [34,24,0,-2], [34,22,-1,-2], [30,39,7,-4], [30,39,7,-4], [30,38,7,-4], [30,39,7,-4], [30,38,7,-4], [30,39,7,-4], + [34,12,-6,-2], [34,22,-2,-2], [30,29,2,-4], [30,29,2,-4], [45,32,4,-2], [45,32,4,-2], [30,29,2,-4], [30,29,2,-4], + [45,18,-3,-2], [45,18,-3,-2], [18,44,10,-3], [18,44,10,-3], [45,18,-3,-2], [45,45,10,-2], [45,44,10,-2], [34,22,-1,-2], + [45,28,2,-2], [45,28,2,-2], [28,44,10,-1], [28,44,10,-1], [47,28,2,-1], [45,45,10,-2], [45,44,10,-2], [34,23,1,-2], + [12,26,-2,-1], [45,23,1,-2], [25,29,2,-4], [25,29,2,-4], [38,35,0,-3], [39,36,11,-2], [26,46,11,-6], [4,19,-3,-2], + [28,35,1], [23,34,0,-2], [28,14,-4,-2], [21,42,4,-2], [33,38,2,-2], [32,36,1,-2], [34,33,0,-2], [34,33,0,-2], + [26,34,0,-2], [38,39,3,-1], [32,37,2,-1], [27,37,2], [37,34,0,-1], [27,37,2,-1], [41,36,2], [28,41,6,-2], + [39,37,3,-1], [33,34,0,2], [39,40,6,-2], [35,37,2,-1], [31,37,2,-1], [54,38,3,-1], [50,41,3,2], [37,37,2,-2], + [35,37,3,-1], [34,42,7,-5], [40,36,2,-1], [32,37,2], [38,36,0,-1], [35,36,2,1], [32,37,3,-1], [50,37,3,-1], + [38,34,0,-2], [35,41,7,-1], [37,34,0,-1], [28,32,2,-2], [28,31,1,-2], [28,32,2,-2], [28,31,1,-2], [28,31,1,-2], + [25,34,0,-2], [26,34,0,-2], [13,50,13,-8], [13,50,13,-1], [13,50,13,-8], [13,50,13,-1], [18,50,13,-3], [18,50,13,-3], + [12,50,13,-5], [12,50,13,-2], [3,50,13,-5], [12,50,13,-6], [18,52,14,-3], [28,52,14,-1], [20,50,13,-2], [9,33,4,-2], + [39,49,47,-3], [34,34,0,-1], [37,36,2,-2], [21,46,11,-2], [27,30,0,-3], [27,30,0,-3], [31,39,7,-4], [31,39,7,-3], + [16,45,10,-3], [17,46,11,-2], [17,45,10,-2], [27,44,10,-2], [36,43,7,-1], [34,44,8,-2], [34,38,2,-2], [34,43,7,-2], + [21,92,164,235,306,378,449,521,592,663,735,806,878,949,1020,1092], + [68,170,271,373,475,576,678,780], + [1170,865] + ], + cmex10: [ + [14,59,57,-7], [13,59,57,-2], [11,59,57,-9], [10,59,57,-1], [13,59,57,-9], [13,59,57,-1], [13,59,57,-9], [13,59,57,-1], + [18,59,57,-5], [18,59,57,-5], [16,59,57,-4], [16,59,57,-3], [3,32,31,-7], [14,32,31,-7], [24,59,57,-2], [24,59,57,-2], + [20,89,87,-8], [20,89,87,-1], [25,118,116,-10], [25,118,116,-1], [14,118,116,-12], [14,118,116], [16,118,116,-12], [17,118,116], + [16,118,116,-12], [17,118,116], [25,118,116,-6], [25,118,116,-6], [26,118,116,-6], [27,118,116,-4], [47,118,116,-2], [47,118,116,-2], + [26,147,145,-11], [27,147,145,-1], [15,147,145,-13], [15,147,145], [18,147,145,-13], [18,147,145], [18,147,145,-13], [18,147,145], + [26,147,145,-7], [26,147,145,-7], [29,147,145,-6], [28,147,145,-5], [58,147,145,-2], [58,147,145,-2], [35,89,87,-2], [35,89,87,-2], + [28,89,87,-14], [28,89,87,-1], [17,89,87,-16], [17,89,87], [17,89,87,-16], [17,89,87], [4,30,30,-16], [4,30,30,-13], + [18,45,45,-18], [17,45,45,-8], [18,45,44,-18], [17,45,44,-8], [17,90,89,-8], [18,90,89,-18], [7,17,16,-18], [3,30,30,-15], + [28,90,87,-14], [28,90,87,-1], [6,31,30,-14], [6,31,30,-23], [21,89,87,-5], [21,89,87,-4], [36,49,49,-2], [50,69,69,-2], + [28,55,55,-2], [45,109,109,-2], [50,49,49,-2], [70,69,69,-2], [50,49,49,-2], [70,69,69,-2], [50,49,49,-2], [70,69,69,-2], + [47,49,49,-2], [42,49,49,-2], [28,55,55,-2], [36,49,49,-2], [36,49,49,-2], [36,49,49,-2], [36,49,49,-2], [36,49,49,-2], + [66,69,69,-2], [58,69,69,-2], [45,109,109,-2], [50,69,69,-2], [50,69,69,-2], [50,69,69,-2], [50,69,69,-2], [50,69,69,-2], + [42,49,49,-2], [58,69,69,-2], [29,10,-27,1], [49,10,-28], [71,10,-28], [27,7,-29], [49,7,-30], [71,7,-30], + [12,89,87,-11], [12,89,87], [14,89,87,-11], [15,89,87], [14,89,87,-11], [15,89,87], [22,89,87,-5], [22,89,87,-5], + [45,59,57,-5], [45,89,87,-5], [45,118,116,-5], [45,147,145,-5], [32,90,89,-5], [3,32,31,-34], [19,31,29,-34], [14,30,30,-12], + [23,30,30,-5], [23,30,30,-5], [25,17,11,2], [25,17,11,1], [25,17,0,2], [25,17,0,1], [34,30,30,-2], [34,29,29,-2], + [22,112,202,292,382,472,561,651,741,831,921,1011,1100,1190,1280,1370], + [78,298,519,740,960,1181,1401,1622], + [1468,1836] + ], + cmbx10: [ + [31,34,0,-1], [42,35,0,-2], [38,36,1,-3], [36,35,0,-2], [34,34,0,-2], [42,34,0,-1], [35,34,0,-3], [38,35,0,-3], + [35,34,0,-3], [38,34,0,-3], [37,35,0,-2], [36,35,0,-1], [29,35,0,-1], [29,35,0,-1], [45,35,0,-1], [45,35,0,-1], + [12,22,0,-2], [17,32,10,3], [12,10,-25,-5], [12,10,-25,-11], [16,7,-25,-6], [18,10,-24,-5], [22,3,-27,-3], [13,9,-26,-15], + [16,10,10,-6], [27,36,1,-1], [39,24,1,-1], [42,24,1,-1], [26,32,5,-1], [48,34,0,-2], [52,36,1,-4], [38,40,3,-3], + [15,7,-13,-1], [9,35,0,-4], [22,18,-16,-1], [41,44,10,-3], [22,40,3,-3], [41,40,3,-3], [39,36,1,-2], [9,18,-16,-4], + [14,50,13,-5], [14,50,13,-3], [22,22,-15,-3], [38,38,7,-3], [9,18,10,-4], [16,6,-8], [8,8,0,-4], [22,50,13,-3], + [24,34,1,-2], [21,32,0,-4], [24,33,0,-2], [24,34,1,-2], [26,33,0,-1], [24,33,1,-2], [24,34,1,-2], [25,35,1,-3], + [24,34,1,-2], [24,34,1,-2], [8,22,0,-4], [8,32,10,-4], [9,35,10,-4], [38,15,-5,-3], [21,35,10,-3], [21,35,0,-3], + [38,36,1,-3], [39,35,0,-2], [36,34,0,-1], [35,36,1,-3], [39,34,0,-1], [35,34,0,-1], [32,34,0,-1], [39,36,1,-3], + [42,34,0,-1], [19,34,0,-1], [25,35,1,-1], [41,34,0,-1], [31,34,0,-1], [50,34,0,-2], [42,34,0,-1], [37,36,1,-3], + [35,34,0,-1], [37,45,10,-3], [41,35,1,-1], [26,36,1,-3], [35,34,0,-2], [41,35,1,-1], [41,35,1,-1], [56,35,1,-1], + [40,34,0,-1], [42,34,0], [29,34,0,-3], [9,50,13,-6], [22,18,-16,-6], [9,50,13,-1], [16,8,-26,-6], [8,8,-26,-4], + [9,18,-16,-3], [27,24,1,-1], [29,35,1,-1], [23,24,1,-1], [29,35,1,-1], [24,24,1,-1], [20,35,0,-2], [27,33,10,-1], + [29,34,0,-2], [12,34,0,-2], [17,44,10,3], [28,34,0,-1], [13,34,0,-2], [44,22,0,-2], [29,22,0,-2], [26,24,1,-1], + [29,32,10,-1], [29,32,10,-1], [21,22,0,-1], [20,24,1,-1], [18,33,1,-1], [29,23,1,-2], [28,23,1,-1], [39,23,1,-1], + [28,22,0,-1], [28,32,10,-1], [22,22,0,-1], [29,3,-12], [57,3,-12], [17,10,-25,-7], [20,6,-28,-4], [19,7,-27,-5], + [21,91,162,233,303,374,445,516,586,657,728,798,869,940,1010,1081], + [64,124,183,243,302,362,421,481], + [1158,521] + ], + cmti10: [ + [32,34,0,-3], [34,35,0,-3], [32,37,2,-7], [30,35,0,-2], [34,34,0,-3], [39,34,0,-3], [35,34,0,-4], [31,35,0,-10], + [29,34,0,-7], [31,34,0,-10], [34,35,0,-4], [40,45,10,2], [32,45,10,2], [34,45,10,2], [47,45,10,2], [49,45,10,2], + [13,23,1,-4], [18,32,10,2], [8,10,-24,-14], [11,11,-24,-16], [14,7,-24,-13], [15,9,-25,-13], [17,2,-27,-11], [10,9,-26,-23], + [12,10,10,-5], [30,45,10,1], [32,23,1,-4], [31,23,1,-5], [24,33,6,-3], [45,34,0,-2], [44,37,2,-8], [36,40,3,-5], + [13,7,-13,-4], [14,35,0,-5], [18,15,-19,-8], [36,44,10,-5], [31,36,1,-4], [35,40,3,-7], [34,37,2,-6], [9,15,-19,-10], + [19,50,13,-7], [18,50,13,-1], [20,22,-15,-9], [31,31,3,-6], [8,16,10,-3], [13,3,-9,-4], [6,6,0,-5], [30,50,13,-1], + [23,35,2,-5], [18,33,0,-5], [23,34,1,-4], [24,35,2,-4], [22,43,10,-2], [23,34,1,-5], [23,34,1,-5], [24,34,1,-7], + [24,35,2,-4], [23,34,1,-5], [10,22,0,-5], [12,32,10,-3], [14,36,11,-2], [33,12,-6,-5], [18,36,11,-4], [18,35,0,-9], + [32,36,1,-7], [32,35,0,-2], [33,34,0,-3], [33,37,2,-7], [35,34,0,-3], [34,34,0,-3], [33,34,0,-3], [33,37,2,-7], + [39,34,0,-3], [23,34,0,-2], [27,36,2,-4], [39,34,0,-3], [28,34,0,-3], [46,34,0,-3], [39,34,0,-3], [32,37,2,-7], + [33,34,0,-3], [32,45,10,-7], [33,36,2,-3], [28,37,2,-3], [32,34,0,-8], [33,36,2,-9], [33,35,1,-10], [45,36,2,-10], + [48,34,0,7], [34,34,0,-9], [31,34,0,-4], [19,50,13,-3], [17,15,-19,-13], [19,50,13,1], [13,8,-26,-13], [6,6,-27,-12], + [8,15,-19,-10], [22,23,1,-5], [18,35,1,-5], [18,23,1,-5], [23,35,1,-5], [18,23,1,-5], [25,45,10,2], [22,32,10,-2], + [24,35,1,-3], [13,34,1,-4], [20,43,10,2], [22,35,1,-3], [11,35,1,-4], [38,23,1,-4], [25,23,1,-4], [20,23,1,-5], + [25,32,10], [20,32,10,-5], [20,23,1,-4], [18,23,1,-3], [15,32,1,-4], [24,23,1,-4], [21,23,1,-4], [31,23,1,-4], + [24,23,1,-2], [22,32,10,-4], [20,23,1,-3], [23,2,-12,-4], [45,2,-12,-6], [16,11,-24,-13], [16,6,-27,-12], [14,6,-27,-13], + [20,81,141,202,263,324,385,445,506,567,628,688,749,810,871,932], + [64,124,183,243,302,362,421,481], + [998,521] + ] +}); + +jsMath.Img.AddFont(430,{ + cmr10: [ + [33,41,0,-2], [45,43,0,-2], [40,44,2,-3], [38,43,0,-1], [35,40,0,-2], [41,41,0,-2], [37,41,0,-3], [40,42,0,-3], + [37,41,0,-3], [40,41,0,-3], [38,42,0,-2], [36,42,0,-1], [31,42,0,-1], [31,42,0,-1], [47,42,0,-1], [47,42,0,-1], + [13,26,0,-2], [16,39,13,3], [12,12,-30,-6], [11,12,-30,-12], [16,8,-30,-7], [19,11,-30,-5], [22,2,-33,-4], [12,11,-32,-16], + [15,11,12,-7], [27,43,1,-1], [39,28,1,-2], [44,28,1,-1], [26,38,6,-2], [51,41,0,-1], [54,44,2,-4], [40,48,4,-3], + [15,7,-16,-1], [7,43,0,-5], [19,18,-23,-2], [43,53,12,-3], [24,49,4,-3], [43,49,4,-3], [41,45,2,-2], [8,18,-23,-5], + [15,60,15,-5], [14,60,15,-3], [23,27,-18,-3], [40,40,5,-3], [7,19,12,-5], [17,4,-11], [7,7,0,-5], [24,60,15,-3], + [26,42,2,-2], [20,40,0,-5], [24,40,0,-3], [25,42,2,-2], [27,40,0,-1], [24,42,2,-3], [25,42,2,-2], [26,42,2,-3], + [25,42,2,-2], [25,42,2,-2], [7,26,0,-5], [7,38,12,-5], [7,43,13,-5], [40,15,-7,-3], [22,43,13,-3], [22,42,0,-3], + [40,43,1,-3], [42,43,0,-1], [37,41,0,-2], [37,44,2,-3], [40,41,0,-2], [37,41,0,-2], [34,41,0,-2], [41,44,2,-3], + [41,41,0,-2], [19,41,0,-1], [26,43,2,-2], [42,41,0,-2], [33,41,0,-2], [50,41,0,-2], [41,41,0,-2], [40,44,2,-3], + [35,41,0,-2], [40,54,12,-3], [42,43,2,-2], [27,44,2,-3], [39,40,0,-2], [41,43,2,-2], [43,43,2,-1], [59,43,2,-1], + [42,41,0,-1], [44,41,0], [30,41,0,-3], [8,60,15,-7], [19,18,-23,-9], [9,60,15,-1], [16,9,-32,-7], [7,7,-33,-5], + [8,18,-23,-4], [28,28,1,-2], [30,42,1,-1], [23,28,1,-2], [30,42,1,-2], [24,28,1,-1], [19,42,0,-2], [28,40,13,-1], + [31,41,0,-1], [13,40,0,-2], [16,53,13,3], [30,41,0,-1], [13,41,0,-2], [47,27,0,-1], [31,27,0,-1], [27,28,1,-1], + [30,39,12,-1], [30,39,12,-2], [21,26,0,-1], [20,28,1,-2], [19,38,1,-1], [31,27,1,-1], [29,27,1,-1], [41,27,1,-1], + [31,26,0], [29,39,13,-1], [23,26,0,-1], [30,2,-15], [59,2,-15], [18,12,-30,-7], [20,7,-33,-5], [18,7,-33,-6], + [24,97,171,244,317,391,464,538,611,684,758,831,904,978,1051,1125], + [77,149,220,292,363,434,506,577], + [1205,625] + ], + cmmi10: [ + [41,41,0,-2], [44,43,0,-3], [42,44,2,-2], [38,43,0,-2], [43,40,0,-3], [50,41,0,-2], [45,41,0,-3], [41,42,0,-1], + [37,41,0,-1], [40,41,0,-1], [43,42,0,-4], [34,28,1,-2], [34,54,12,-1], [31,40,13,-1], [25,43,1,-2], [21,27,1,-2], + [26,55,13,-2], [29,40,13,-1], [25,43,1,-2], [17,27,1,-3], [30,27,1,-3], [30,42,1,-3], [33,39,13,-1], [28,26,0,-3], + [26,54,13,-1], [33,27,1,-1], [29,40,13,-1], [32,27,1,-2], [30,27,1,-1], [30,27,1,-1], [32,53,12,-2], [34,39,13,-1], + [37,53,12,-1], [36,27,1], [25,29,2,-1], [32,43,1,-1], [48,27,1,-1], [26,39,12,-4], [24,34,7,-1], [34,39,13,-3], + [53,18,-13,-3], [53,17,1,-3], [53,18,-13,-3], [53,17,1,-3], [10,15,-13,-3], [11,15,-13,-3], [27,31,1,-1], [27,31,1,-1], + [26,29,2,-2], [20,27,0,-5], [25,27,0,-2], [25,40,13,-2], [27,40,12,-1], [24,40,13,-3], [25,42,2,-2], [26,41,13,-3], + [25,42,2,-2], [25,40,13,-2], [7,7,0,-5], [7,19,12,-5], [37,35,3,-4], [24,60,15,-3], [37,35,3,-4], [30,28,-1], + [32,45,2,-2], [41,43,0,-2], [43,41,0,-2], [42,44,2,-3], [46,41,0,-2], [43,41,0,-2], [43,41,0,-2], [42,44,2,-3], + [50,41,0,-2], [28,41,0,-2], [34,43,2,-4], [51,41,0,-2], [36,41,0,-2], [60,41,0,-2], [50,41,0,-2], [42,44,2,-2], + [43,41,0,-2], [42,54,12,-2], [43,43,2,-2], [35,44,2,-3], [41,40,0,-1], [41,43,2,-4], [43,43,2,-3], [59,43,2,-3], + [50,41,0,-1], [43,41,0,-2], [40,41,0,-3], [17,47,2,-3], [15,56,13,-4], [17,56,13,-3], [53,15,-7,-3], [53,16,-7,-3], + [24,43,1], [28,28,1,-2], [23,42,1,-2], [24,28,1,-2], [29,42,1,-2], [24,28,1,-2], [30,54,12,-3], [28,40,13], + [30,42,1,-3], [17,40,1,-1], [25,52,13,1], [27,42,1,-3], [14,42,1,-2], [49,28,1,-1], [33,28,1,-1], [26,28,1,-2], + [31,38,12,2], [25,39,12,-2], [25,28,1,-1], [22,28,1,-3], [19,38,1,-1], [31,27,1,-1], [27,27,1,-1], [40,27,1,-1], + [31,28,1,-1], [28,39,13,-1], [26,27,1,-2], [17,27,1,-1], [23,39,13,1], [33,40,13,-4], [27,13,-30,-10], [24,9,-31,-15], + [24,95,167,238,309,381,452,524,595,666,738,809,880,952,1023,1095], + [77,149,220,292,363,434,506,577], + [1172,625] + ], + cmsy10: [ + [36,3,-13,-5], [7,7,-11,-5], [30,29,0,-8], [23,26,-2,-3], [40,34,2,-3], [29,29,0], [40,40,0,-3], [40,40,10,-3], + [40,40,5,-3], [40,40,5,-3], [40,40,5,-3], [40,40,5,-3], [40,40,5,-3], [53,56,13,-3], [24,24,-3,-3], [24,24,-3,-3], + [40,28,-1,-3], [40,26,-2,-3], [37,47,9,-4], [37,47,9,-4], [37,47,9,-4], [37,47,9,-4], [37,47,9,-4], [37,47,9,-4], + [40,15,-7,-3], [40,26,-3,-3], [37,35,3,-4], [37,35,3,-4], [53,38,4,-3], [53,38,4,-3], [37,35,3,-4], [37,35,3,-4], + [53,22,-4,-3], [53,22,-4,-3], [22,53,12,-4], [22,53,12,-4], [53,22,-4,-3], [53,53,12,-3], [53,53,12,-3], [40,26,-2,-3], + [53,33,2,-3], [53,33,2,-3], [34,53,12,-1], [34,53,12,-1], [55,33,2,-2], [53,54,12,-3], [53,53,12,-3], [40,28,1,-3], + [15,31,-2,-1], [53,28,1,-3], [31,35,3,-4], [31,35,3,-4], [46,43,0,-3], [46,43,13,-3], [30,56,13,-8], [5,23,-3,-3], + [33,43,2], [27,41,0,-3], [33,16,-5,-3], [25,51,5,-2], [40,45,2,-2], [38,43,1,-3], [40,40,0,-3], [40,40,0,-3], + [30,41,0,-3], [46,46,3,-1], [39,44,2,-1], [32,44,2], [45,41,0,-1], [33,44,2,-1], [48,43,2,-1], [34,49,7,-2], + [48,44,3,-1], [40,41,0,2], [48,48,7,-2], [43,44,2,-1], [38,44,2,-1], [65,45,3,-1], [60,49,3,2], [43,44,2,-3], + [43,44,3,-1], [41,50,8,-6], [49,43,2,-1], [37,44,2,-1], [46,43,0,-1], [42,43,2,1], [37,44,3,-2], [60,44,3,-2], + [45,41,0,-3], [42,49,8,-1], [44,41,0,-2], [33,38,2,-3], [33,38,2,-3], [33,38,2,-3], [33,38,2,-3], [33,38,2,-3], + [30,41,0,-3], [30,41,0,-3], [15,60,15,-10], [15,60,15,-1], [15,60,15,-10], [15,60,15,-1], [22,60,15,-4], [22,60,15,-4], + [14,60,15,-6], [14,60,15,-3], [3,60,15,-7], [15,60,15,-7], [22,62,16,-4], [34,62,16,-1], [24,60,15,-3], [10,40,5,-3], + [47,60,57,-4], [40,41,0,-2], [45,43,2,-2], [25,56,13,-3], [33,36,0,-3], [33,36,0,-3], [38,47,9,-5], [38,47,9,-3], + [18,55,13,-4], [20,55,13,-3], [20,54,12,-3], [32,53,12,-3], [44,51,8,-1], [40,53,10,-3], [40,45,2,-3], [40,51,8,-3], + [25,111,196,282,368,454,539,625,711,797,882,968,1054,1140,1225,1311], + [82,204,326,448,570,692,814,936], + [1404,1039] + ], + cmex10: [ + [16,72,69,-9], [16,72,69,-2], [13,72,69,-11], [12,72,69,-1], [16,72,69,-11], [15,72,69,-1], [16,72,69,-11], [15,72,69,-1], + [22,72,69,-6], [22,72,69,-6], [19,72,69,-5], [18,72,69,-4], [4,39,37,-8], [17,39,37,-8], [28,72,69,-3], [28,72,69,-3], + [23,107,104,-10], [23,107,104,-2], [30,143,140,-12], [30,143,140,-2], [17,143,140,-14], [17,143,140], [20,143,140,-14], [20,143,140], + [20,143,140,-14], [20,143,140], [30,143,140,-7], [30,143,140,-7], [32,143,140,-7], [32,143,140,-5], [56,143,140,-3], [56,143,140,-3], + [32,178,175,-13], [31,178,175,-2], [18,178,175,-16], [19,178,175], [21,178,175,-16], [22,178,175], [21,178,175,-16], [22,178,175], + [31,178,175,-8], [31,178,175,-8], [34,178,175,-8], [34,178,175,-6], [69,178,175,-3], [69,178,175,-3], [42,107,104,-3], [42,107,104,-3], + [33,108,105,-17], [33,108,105,-2], [20,107,104,-19], [21,107,104], [20,107,104,-19], [21,107,104], [5,37,36,-19], [5,37,36,-16], + [21,54,54,-22], [20,54,54,-10], [21,54,53,-22], [20,54,53,-10], [20,108,107,-10], [21,108,107,-22], [8,20,19,-22], [3,37,36,-18], + [33,107,104,-17], [33,107,104,-2], [7,37,36,-17], [8,37,36,-27], [25,107,104,-6], [25,107,104,-5], [43,59,59,-3], [60,83,83,-3], + [33,66,66,-3], [53,132,132,-3], [60,59,59,-3], [83,83,83,-3], [60,59,59,-3], [83,83,83,-3], [60,59,59,-3], [83,83,83,-3], + [56,59,59,-3], [50,59,59,-3], [33,66,66,-3], [43,59,59,-3], [43,59,59,-3], [43,59,59,-3], [43,59,59,-3], [43,59,59,-3], + [79,83,83,-3], [69,83,83,-3], [53,132,132,-3], [60,83,83,-3], [60,83,83,-3], [60,83,83,-3], [60,83,83,-3], [60,83,83,-3], + [50,59,59,-3], [69,83,83,-3], [34,11,-33,1], [60,12,-34,1], [86,12,-34], [33,8,-35], [59,9,-36], [85,9,-36], + [14,107,104,-13], [14,107,104,-1], [17,107,104,-13], [17,107,104,-1], [17,107,104,-13], [17,107,104,-1], [26,107,104,-7], [26,107,104,-7], + [55,72,69,-6], [55,107,104,-6], [55,143,140,-6], [55,178,175,-6], [38,109,107,-6], [3,39,37,-41], [23,38,35,-41], [16,37,36,-15], + [27,36,36,-6], [27,36,36,-6], [30,21,13,2], [29,21,13,1], [30,20,0,2], [29,20,0,1], [40,36,36,-3], [40,35,35,-3], + [27,135,243,350,458,566,674,782,890,998,1106,1213,1321,1429,1537,1645], + [93,358,623,888,1153,1418,1683,1947], + [1762,2205] + ], + cmbx10: [ + [36,41,0,-2], [50,42,0,-3], [46,43,1,-3], [44,42,0,-2], [41,40,0,-2], [49,41,0,-2], [43,41,0,-3], [46,42,0,-3], + [43,41,0,-3], [46,41,0,-3], [43,42,0,-3], [43,42,0,-1], [35,42,0,-1], [35,42,0,-1], [54,42,0,-1], [54,42,0,-1], + [15,27,0,-2], [20,39,12,4], [13,12,-30,-7], [13,12,-30,-14], [18,9,-30,-8], [22,12,-29,-6], [26,4,-32,-4], [15,11,-31,-18], + [19,12,12,-7], [32,43,1,-2], [46,28,1,-2], [50,28,1,-1], [31,40,7,-1], [58,41,0,-2], [63,43,1,-4], [46,48,4,-3], + [18,8,-16,-1], [10,42,0,-5], [26,21,-20,-2], [50,53,12,-3], [28,49,4,-3], [50,49,4,-3], [48,43,1,-2], [11,21,-20,-4], + [17,60,15,-6], [17,60,15,-3], [26,27,-18,-4], [46,46,8,-3], [11,22,12,-4], [19,6,-10], [10,10,0,-4], [28,60,15,-3], + [30,40,1,-2], [25,39,0,-5], [28,39,0,-3], [29,40,1,-2], [31,39,0,-1], [28,40,1,-3], [29,40,1,-2], [30,41,1,-3], + [29,40,1,-2], [29,40,1,-2], [10,27,0,-4], [11,39,12,-4], [10,43,13,-5], [46,18,-6,-3], [26,42,12,-3], [26,42,0,-3], + [46,43,1,-3], [47,42,0,-2], [43,41,0,-2], [43,43,1,-3], [47,41,0,-2], [41,41,0,-2], [38,41,0,-2], [47,43,1,-3], + [49,41,0,-2], [22,41,0,-2], [31,42,1,-1], [49,41,0,-2], [36,41,0,-2], [60,41,0,-2], [49,41,0,-2], [45,43,1,-3], + [41,41,0,-2], [45,54,12,-3], [49,42,1,-2], [31,43,1,-3], [43,40,0,-2], [48,42,1,-2], [49,42,1,-1], [68,42,1,-1], + [48,41,0,-2], [50,41,0,-1], [35,41,0,-3], [11,60,15,-7], [26,21,-20,-8], [11,60,15,-1], [19,10,-31,-7], [10,10,-31,-4], + [11,21,-20,-3], [32,28,1,-1], [34,42,1,-2], [27,28,1,-2], [34,42,1,-2], [29,28,1,-1], [24,42,0,-2], [32,39,12,-1], + [35,41,0,-2], [15,41,0,-2], [20,53,12,4], [33,41,0,-2], [16,41,0,-2], [54,27,0,-2], [35,27,0,-2], [31,28,1,-1], + [34,39,12,-2], [34,39,12,-2], [24,27,0,-2], [23,28,1,-2], [22,39,1,-1], [35,28,1,-2], [34,28,1,-1], [47,28,1,-1], + [34,27,0,-1], [34,39,12,-1], [27,27,0,-1], [34,3,-15], [68,3,-15], [21,12,-30,-8], [23,7,-34,-5], [22,9,-32,-6], + [25,110,195,280,364,449,534,619,704,789,874,959,1043,1128,1213,1298], + [77,149,220,292,363,434,506,577], + [1390,625], + ], + cmti10: [ + [39,41,0,-3], [41,43,0,-4], [39,44,2,-8], [35,43,0,-3], [41,40,0,-4], [48,41,0,-3], [43,41,0,-4], [38,42,0,-12], + [34,41,0,-9], [37,41,0,-12], [40,42,0,-5], [47,55,13,2], [38,55,13,2], [40,55,13,2], [56,55,13,2], [58,55,13,2], + [15,28,1,-5], [21,39,13,2], [9,12,-29,-17], [13,12,-29,-20], [16,9,-29,-16], [18,11,-30,-16], [21,2,-33,-13], [12,12,-31,-28], + [14,12,12,-6], [37,55,13,2], [38,28,1,-5], [37,28,1,-6], [29,39,7,-4], [53,41,0,-3], [53,44,2,-9], [42,48,4,-7], + [16,8,-16,-5], [17,43,0,-6], [21,18,-23,-10], [43,53,12,-6], [37,43,1,-5], [42,49,4,-8], [41,45,2,-7], [9,18,-23,-13], + [22,60,15,-9], [22,60,15,-1], [24,27,-18,-11], [37,37,4,-8], [10,19,12,-4], [15,4,-11,-5], [7,7,0,-6], [36,60,15,-1], + [27,42,2,-6], [21,40,0,-7], [28,42,2,-5], [29,42,2,-5], [26,52,12,-2], [28,42,2,-6], [27,42,2,-7], [29,42,2,-8], + [28,42,2,-5], [27,42,2,-6], [12,26,0,-6], [14,38,12,-4], [16,43,13,-3], [40,15,-7,-6], [21,43,13,-5], [22,43,0,-11], + [39,43,1,-8], [38,43,0,-3], [41,41,0,-3], [40,44,2,-8], [43,41,0,-3], [41,41,0,-3], [41,41,0,-3], [40,44,2,-8], + [48,41,0,-3], [27,41,0,-3], [32,43,2,-5], [48,41,0,-3], [34,41,0,-3], [56,41,0,-4], [48,41,0,-3], [39,44,2,-8], + [40,41,0,-3], [39,54,12,-8], [40,43,2,-3], [34,44,2,-4], [38,40,0,-10], [40,43,2,-11], [40,43,2,-12], [54,43,2,-12], + [57,41,0,8], [40,41,0,-12], [38,41,0,-4], [23,60,15,-4], [20,18,-23,-16], [23,60,15,996], [16,10,-31,-15], [7,7,-33,-15], + [10,18,-23,-12], [26,27,1,-6], [21,42,1,-6], [22,28,1,-6], [27,42,1,-6], [22,28,1,-6], [29,54,12,2], [26,39,13,-3], + [28,42,1,-4], [15,40,1,-5], [23,52,13,2], [26,42,1,-4], [13,42,1,-5], [45,28,1,-5], [30,28,1,-5], [24,28,1,-6], + [31,38,12], [24,38,12,-6], [24,28,1,-5], [21,28,1,-4], [17,38,1,-5], [28,28,1,-5], [25,28,1,-5], [37,28,1,-5], + [28,28,1,-3], [26,40,13,-5], [25,28,1,-3], [28,2,-15,-5], [55,2,-15,-7], [18,11,-30,-16], [20,7,-33,-14], [17,7,-33,-16], + [24,97,170,243,316,389,462,535,608,681,754,827,900,973,1046,1119], + [77,149,220,292,363,434,506,577], + [1198,625] + ] +}); + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/jsMath-fallback-mac.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/jsMath-fallback-mac.js new file mode 100644 index 0000000..5bbc299 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/jsMath-fallback-mac.js @@ -0,0 +1,1016 @@ +/* + * jsMath-fallback-mac.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file makes changes needed for when the TeX fonts are not available + * with a browser on the Mac. + * + * --------------------------------------------------------------------- + * + * Copyright 2004-2006 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +/******************************************************************** + * + * Here we replace the TeX character mappings by equivalent unicode + * points when possible, and adjust the character dimensions + * based on the fonts we hope we get them from (the styles are set + * to try to use the best characters available in the standard + * fonts). + */ + +jsMath.Add(jsMath.TeX,{ + + cmr10: [ + // 00 - 0F + {c: 'Γ', tclass: 'greek'}, + {c: 'Δ', tclass: 'greek'}, + {c: 'Θ', tclass: 'greek'}, + {c: 'Λ', tclass: 'greek'}, + {c: 'Ξ', tclass: 'greek'}, + {c: 'Π', tclass: 'greek'}, + {c: 'Σ', tclass: 'greek'}, + {c: 'Υ', tclass: 'greek'}, + {c: 'Φ', tclass: 'greek'}, + {c: 'Ψ', tclass: 'greek'}, + {c: 'Ω', tclass: 'greek'}, + {c: 'ff', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 14, '108': 15}, tclass: 'normal'}, + {c: 'fi', tclass: 'normal'}, + {c: 'fl', tclass: 'normal'}, + {c: 'ffi', tclass: 'normal'}, + {c: 'ffl', tclass: 'normal'}, + // 10 - 1F + {c: 'ı', a:0, tclass: 'normal'}, + {c: 'j', d:.2, tclass: 'normal'}, + {c: '`', tclass: 'accent'}, + {c: '´', tclass: 'accent'}, + {c: 'ˇ', tclass: 'accent'}, + {c: '˘', tclass: 'accent'}, + {c: 'ˉ', tclass: 'accent'}, + {c: '˚', tclass: 'accent'}, + {c: '̧', tclass: 'normal'}, + {c: 'ß', tclass: 'normal'}, + {c: 'æ', a:0, tclass: 'normal'}, + {c: 'œ', a:0, tclass: 'normal'}, + {c: 'ø', tclass: 'normal'}, + {c: 'Æ', tclass: 'normal'}, + {c: 'Œ', tclass: 'normal'}, + {c: 'Ø', tclass: 'normal'}, + // 20 - 2F + {c: '?', krn: {'108': -0.278, '76': -0.319}, tclass: 'normal'}, + {c: '!', lig: {'96': 60}, tclass: 'normal'}, + {c: '”', tclass: 'normal'}, + {c: '#', tclass: 'normal'}, + {c: '$', tclass: 'normal'}, + {c: '%', tclass: 'normal'}, + {c: '&', tclass: 'normal'}, + {c: '’', krn: {'63': 0.111, '33': 0.111}, lig: {'39': 34}, tclass: 'normal'}, + {c: '(', d:.2, tclass: 'normal'}, + {c: ')', d:.2, tclass: 'normal'}, + {c: '*', tclass: 'normal'}, + {c: '+', a:.1, tclass: 'normal'}, + {c: ',', a:-.3, d:.2, w: 0.278, tclass: 'normal'}, + {c: '-', a:0, lig: {'45': 123}, tclass: 'normal'}, + {c: '.', a:-.25, tclass: 'normal'}, + {c: '/', tclass: 'normal'}, + // 30 - 3F + {c: '0', tclass: 'normal'}, + {c: '1', tclass: 'normal'}, + {c: '2', tclass: 'normal'}, + {c: '3', tclass: 'normal'}, + {c: '4', tclass: 'normal'}, + {c: '5', tclass: 'normal'}, + {c: '6', tclass: 'normal'}, + {c: '7', tclass: 'normal'}, + {c: '8', tclass: 'normal'}, + {c: '9', tclass: 'normal'}, + {c: ':', tclass: 'normal'}, + {c: ';', tclass: 'normal'}, + {c: '¡', tclass: 'normal'}, + {c: '=', a:0, d:-.1, tclass: 'normal'}, + {c: '¿', tclass: 'normal'}, + {c: '?', lig: {'96': 62}, tclass: 'normal'}, + // 40 - 4F + {c: '@', tclass: 'normal'}, + {c: 'A', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'normal'}, + {c: 'B', tclass: 'normal'}, + {c: 'C', tclass: 'normal'}, + {c: 'D', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'normal'}, + {c: 'E', tclass: 'normal'}, + {c: 'F', krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'}, + {c: 'G', tclass: 'normal'}, + {c: 'H', tclass: 'normal'}, + {c: 'I', krn: {'73': 0.0278}, tclass: 'normal'}, + {c: 'J', tclass: 'normal'}, + {c: 'K', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'}, + {c: 'L', krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'normal'}, + {c: 'M', tclass: 'normal'}, + {c: 'N', tclass: 'normal'}, + {c: 'O', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'normal'}, + // 50 - 5F + {c: 'P', krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'normal'}, + {c: 'Q', d:.1, tclass: 'normal'}, + {c: 'R', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'normal'}, + {c: 'S', tclass: 'normal'}, + {c: 'T', krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'normal'}, + {c: 'U', tclass: 'normal'}, + {c: 'V', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'}, + {c: 'W', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'}, + {c: 'X', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'}, + {c: 'Y', ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'normal'}, + {c: 'Z', tclass: 'normal'}, + {c: '[', d:.1, tclass: 'normal'}, + {c: '“', tclass: 'normal'}, + {c: ']', d:.1, tclass: 'normal'}, + {c: 'ˆ', tclass: 'accent'}, + {c: '˙', tclass: 'accent'}, + // 60 - 6F + {c: '‘', lig: {'96': 92}, tclass: 'normal'}, + {c: 'a', a:0, krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'b', krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'c', a:0, krn: {'104': -0.0278, '107': -0.0278}, tclass: 'normal'}, + {c: 'd', tclass: 'normal'}, + {c: 'e', a:0, tclass: 'normal'}, + {c: 'f', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}, tclass: 'normal'}, + {c: 'g', a:0, d:.2, ic: 0.0139, krn: {'106': 0.0278}, tclass: 'normal'}, + {c: 'h', krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'i', tclass: 'normal'}, + {c: 'j', d:.2, tclass: 'normal'}, + {c: 'k', krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'normal'}, + {c: 'l', tclass: 'normal'}, + {c: 'm', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'n', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'o', a:0, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'}, + // 70 - 7F + {c: 'p', a:0, d:.2, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'q', a:0, d:.2, tclass: 'normal'}, + {c: 'r', a:0, tclass: 'normal'}, + {c: 's', a:0, tclass: 'normal'}, + {c: 't', krn: {'121': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'u', a:0, krn: {'119': -0.0278}, tclass: 'normal'}, + {c: 'v', a:0, ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'normal'}, + {c: 'w', a:0, ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'normal'}, + {c: 'x', a:0, tclass: 'normal'}, + {c: 'y', a:0, d:.2, ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'normal'}, + {c: 'z', a:0, tclass: 'normal'}, + {c: '–', a:.1, ic: 0.0278, lig: {'45': 124}, tclass: 'normal'}, + {c: '—', a:.1, ic: 0.0278, tclass: 'normal'}, + {c: '˝', tclass: 'accent'}, + {c: '˜', tclass: 'accent'}, + {c: '¨', tclass: 'accent'} + ], + + cmmi10: [ + // 00 - 0F + {c: 'Γ', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}, tclass: 'igreek'}, + {c: 'Δ', krn: {'127': 0.167}, tclass: 'igreek'}, + {c: 'Θ', ic: 0.0278, krn: {'127': 0.0833}, tclass: 'igreek'}, + {c: 'Λ', krn: {'127': 0.167}, tclass: 'igreek'}, + {c: 'Ξ', ic: 0.0757, krn: {'127': 0.0833}, tclass: 'igreek'}, + {c: 'Π', ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'igreek'}, + {c: 'Σ', ic: 0.0576, krn: {'127': 0.0833}, tclass: 'igreek'}, + {c: 'Υ', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0556}, tclass: 'igreek'}, + {c: 'Φ', krn: {'127': 0.0833}, tclass: 'igreek'}, + {c: 'Ψ', ic: 0.11, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'igreek'}, + {c: 'Ω', ic: 0.0502, krn: {'127': 0.0833}, tclass: 'igreek'}, + {c: 'α', a:0, ic: 0.0037, krn: {'127': 0.0278}, tclass: 'greek'}, + {c: 'β', d:.2, ic: 0.0528, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'γ', a:0, d:.2, ic: 0.0556, tclass: 'greek'}, + {c: 'δ', ic: 0.0378, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'greek'}, + {c: 'ε', a:0, krn: {'127': 0.0556}, tclass: 'lucida'}, + // 10 - 1F + {c: 'ζ', d:.2, ic: 0.0738, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'η', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0556}, tclass: 'greek'}, + {c: 'θ', ic: 0.0278, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'ι', a:0, krn: {'127': 0.0556}, tclass: 'greek'}, + {c: 'κ', a:0, tclass: 'greek'}, + {c: 'λ', tclass: 'greek'}, + {c: 'μ', a:0, d:.2, krn: {'127': 0.0278}, tclass: 'greek'}, + {c: 'ν', a:0, ic: 0.0637, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}, tclass: 'greek'}, + {c: 'ξ', d:.2, ic: 0.046, krn: {'127': 0.111}, tclass: 'greek'}, + {c: 'π', a:0, ic: 0.0359, tclass: 'greek'}, + {c: 'ρ', a:0, d:.2, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'σ', a:0, ic: 0.0359, krn: {'59': -0.0556, '58': -0.0556}, tclass: 'greek'}, + {c: 'τ', a:0, ic: 0.113, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}, tclass: 'greek'}, + {c: 'υ', a:0, ic: 0.0359, krn: {'127': 0.0278}, tclass: 'greek'}, + {c: 'φ', a:.1, d:.2, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'χ', a:0, d:.2, krn: {'127': 0.0556}, tclass: 'greek'}, + // 20 - 2F + {c: 'ψ', a:.1, d:.2, ic: 0.0359, krn: {'127': 0.111}, tclass: 'greek'}, + {c: 'ω', a:0, ic: 0.0359, tclass: 'greek'}, + {c: 'ε', a:0, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'ϑ', krn: {'127': 0.0833}, tclass: 'normal'}, + {c: 'ϖ', a:0, ic: 0.0278, tclass: 'normal'}, + {c: 'ϱ', a:0, d:.2, krn: {'127': 0.0833}, tclass: 'normal'}, + {c: 'ς', a:0, d:.2, ic: 0.0799, krn: {'127': 0.0833}, tclass: 'normal'}, + {c: 'ϕ', a:.1, d:.2, krn: {'127': 0.0833}, tclass: 'normal'}, + {c: '↼', a:0, d:-.2, tclass: 'harpoon'}, + {c: '↽', a:0, d:-.1, tclass: 'harpoon'}, + {c: '⇀', a:0, d:-.2, tclass: 'harpoon'}, + {c: '⇁', a:0, d:-.1, tclass: 'harpoon'}, + {c: '˓', a:.1, tclass: 'lucida'}, + {c: '˒', a:.1, tclass: 'lucida'}, + {c: '', tclass: 'symbol'}, + {c: '', tclass: 'symbol'}, + // 30 - 3F + {c: '0', tclass: 'normal'}, + {c: '1', tclass: 'normal'}, + {c: '2', tclass: 'normal'}, + {c: '3', tclass: 'normal'}, + {c: '4', tclass: 'normal'}, + {c: '5', tclass: 'normal'}, + {c: '6', tclass: 'normal'}, + {c: '7', tclass: 'normal'}, + {c: '8', tclass: 'normal'}, + {c: '9', tclass: 'normal'}, + {c: '.', a:-.3, tclass: 'normal'}, + {c: ',', a:-.3, d:.2, tclass: 'normal'}, + {c: '<', a:.1, tclass: 'normal'}, + {c: '/', d:.1, krn: {'1': -0.0556, '65': -0.0556, '77': -0.0556, '78': -0.0556, '89': 0.0556, '90': -0.0556}, tclass: 'normal'}, + {c: '>', a:.1, tclass: 'normal'}, + {c: '', a:0, tclass: 'symbol'}, + // 40 - 4F + {c: '∂', ic: 0.0556, krn: {'127': 0.0833}, tclass: 'normal'}, + {c: 'A', krn: {'127': 0.139}, tclass: 'italic'}, + {c: 'B', ic: 0.0502, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'C', ic: 0.0715, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'D', ic: 0.0278, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 'E', ic: 0.0576, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'F', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}, tclass: 'italic'}, + {c: 'G', krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'H', ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'italic'}, + {c: 'I', ic: 0.0785, krn: {'127': 0.111}, tclass: 'italic'}, + {c: 'J', ic: 0.0962, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.167}, tclass: 'italic'}, + {c: 'K', ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'italic'}, + {c: 'L', krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'M', ic: 0.109, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'N', ic: 0.109, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'O', ic: 0.0278, krn: {'127': 0.0833}, tclass: 'italic'}, + // 50 - 5F + {c: 'P', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}, tclass: 'italic'}, + {c: 'Q', d:.2, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'R', ic: 0.00773, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'S', ic: 0.0576, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'T', ic: 0.139, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'U', ic: 0.109, krn: {'59': -0.111, '58': -0.111, '61': -0.0556, '127': 0.0278}, tclass: 'italic'}, + {c: 'V', ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}, tclass: 'italic'}, + {c: 'W', ic: 0.139, krn: {'59': -0.167, '58': -0.167, '61': -0.111}, tclass: 'italic'}, + {c: 'X', ic: 0.0785, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'Y', ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}, tclass: 'italic'}, + {c: 'Z', ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: '♭', tclass: 'symbol2'}, + {c: '♮', tclass: 'symbol2'}, + {c: '♯', tclass: 'symbol2'}, + {c: '', a:0, d:-.1, tclass: 'normal'}, + {c: '', a:0, d:-.1, tclass: 'normal'}, + // 60 - 6F + {c: 'ℓ', krn: {'127': 0.111}, tclass: 'symbol'}, + {c: 'a', a:0, tclass: 'italic'}, + {c: 'b', tclass: 'italic'}, + {c: 'c', a:0, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 'd', krn: {'89': 0.0556, '90': -0.0556, '106': -0.111, '102': -0.167, '127': 0.167}, tclass: 'italic'}, + {c: 'e', a:0, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 'f', d:.2, ic: 0.108, krn: {'59': -0.0556, '58': -0.0556, '127': 0.167}, tclass: 'italic'}, + {c: 'g', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'h', krn: {'127': -0.0278}, tclass: 'italic'}, + {c: 'i', tclass: 'italic'}, + {c: 'j', d:.2, ic: 0.0572, krn: {'59': -0.0556, '58': -0.0556}, tclass: 'italic'}, + {c: 'k', ic: 0.0315, tclass: 'italic'}, + {c: 'l', ic: 0.0197, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'm', a:0, tclass: 'italic'}, + {c: 'n', a:0, tclass: 'italic'}, + {c: 'o', a:0, krn: {'127': 0.0556}, tclass: 'italic'}, + // 70 - 7F + {c: 'p', a:0, d:.2, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'q', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'r', a:0, ic: 0.0278, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'italic'}, + {c: 's', a:0, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 't', krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'u', a:0, krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'v', a:0, ic: 0.0359, krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'w', a:0, ic: 0.0269, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'x', a:0, krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'y', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 'z', a:0, ic: 0.044, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 'ı', a:0, krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'j', d:.2, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: '℘', a:0, d:.2, krn: {'127': 0.111}, tclass: 'normal'}, + {c: '', ic: 0.154, tclass: 'symbol'}, + {c: '̑', ic: 0.399, tclass: 'normal'} + ], + + cmsy10: [ + // 00 - 0F + {c: '−', a:.1, tclass: 'symbol'}, + {c: '·', a:0, d:-.2, tclass: 'symbol'}, + {c: '×', a:0, tclass: 'symbol'}, + {c: '*', a:0, tclass: 'symbol'}, + {c: '÷', a:0, tclass: 'symbol'}, + {c: '◊', tclass: 'lucida'}, + {c: '±', a:.1, tclass: 'symbol'}, + {c: '∓', tclass: 'symbol'}, + {c: '⊕', tclass: 'symbol'}, + {c: '⊖', tclass: 'symbol'}, + {c: '⊗', tclass: 'symbol'}, + {c: '⊘', tclass: 'symbol'}, + {c: '⊙', tclass: 'symbol3'}, + {c: '◯', tclass: 'symbol'}, + {c: '°', a:0, d:-.1, tclass: 'symbol'}, + {c: '•', a:0, d:-.2, tclass: 'symbol'}, + // 10 - 1F + {c: '≍', a:.1, tclass: 'symbol'}, + {c: '≡', a:.1, tclass: 'symbol'}, + {c: '⊆', tclass: 'symbol'}, + {c: '⊇', tclass: 'symbol'}, + {c: '≤', tclass: 'symbol'}, + {c: '≥', tclass: 'symbol'}, + {c: '≼', tclass: 'symbol'}, + {c: '≽', tclass: 'symbol'}, + {c: '~', a:0, d: -.2, tclass: 'normal'}, + {c: '≈', a:.1, d:-.1, tclass: 'symbol'}, + {c: '⊂', tclass: 'symbol'}, + {c: '⊃', tclass: 'symbol'}, + {c: '≪', tclass: 'symbol'}, + {c: '≫', tclass: 'symbol'}, + {c: '≺', tclass: 'symbol'}, + {c: '≻', tclass: 'symbol'}, + // 20 - 2F + {c: '←', a:0, d:-.15, tclass: 'arrow1'}, + {c: '→', a:0, d:-.15, tclass: 'arrow1'}, + {c: '↑', h:1, tclass: 'arrow1a'}, + {c: '↓', h:1, tclass: 'arrow1a'}, + {c: '↔', a:0, tclass: 'arrow1'}, + {c: '↗', h:1, tclass: 'arrows'}, + {c: '↘', h:1, tclass: 'arrows'}, + {c: '≃', a: .1, tclass: 'symbol'}, + {c: '⇐', a:.1, tclass: 'arrow2'}, + {c: '⇒', a:.1, tclass: 'arrow2'}, + {c: '⇑', h:.9, d:.1, tclass: 'arrow2a'}, + {c: '⇓', h:.9, d:.1, tclass: 'arrow2a'}, + {c: '⇔', a:.1, tclass: 'arrow2'}, + {c: '↖', h:1, tclass: 'arrows'}, + {c: '↙', h:1, tclass: 'arrows'}, + {c: '∝', a:.1, tclass: 'symbol'}, + // 30 - 3F + {c: '', a: 0, tclass: 'lucida'}, + {c: '∞', a:.1, tclass: 'symbol'}, + {c: '∈', tclass: 'symbol'}, + {c: '∋', tclass: 'symbol'}, + {c: '△', tclass: 'symbol'}, + {c: '▽', tclass: 'symbol'}, + {c: '/', tclass: 'symbol'}, + {c: '|', a:0, tclass: 'normal'}, + {c: '∀', tclass: 'symbol'}, + {c: '∃', tclass: 'symbol'}, + {c: '¬', a:0, d:-.1, tclass: 'symbol1'}, + {c: '∅', tclass: 'symbol'}, + {c: 'ℜ', tclass: 'symbol'}, + {c: 'ℑ', tclass: 'symbol'}, + {c: '⊤', tclass: 'symbol'}, + {c: '⊥', tclass: 'symbol'}, + // 40 - 4F + {c: 'ℵ', tclass: 'symbol'}, + {c: 'A', krn: {'48': 0.194}, tclass: 'cal'}, + {c: 'B', ic: 0.0304, krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'C', ic: 0.0583, krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'D', ic: 0.0278, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'E', ic: 0.0894, krn: {'48': 0.111}, tclass: 'cal'}, + {c: 'F', ic: 0.0993, krn: {'48': 0.111}, tclass: 'cal'}, + {c: 'G', d:.2, ic: 0.0593, krn: {'48': 0.111}, tclass: 'cal'}, + {c: 'H', ic: 0.00965, krn: {'48': 0.111}, tclass: 'cal'}, + {c: 'I', ic: 0.0738, krn: {'48': 0.0278}, tclass: 'cal'}, + {c: 'J', d:.2, ic: 0.185, krn: {'48': 0.167}, tclass: 'cal'}, + {c: 'K', ic: 0.0144, krn: {'48': 0.0556}, tclass: 'cal'}, + {c: 'L', krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'M', krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'N', ic: 0.147, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'O', ic: 0.0278, krn: {'48': 0.111}, tclass: 'cal'}, + // 50 - 5F + {c: 'P', ic: 0.0822, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'Q', d:.2, krn: {'48': 0.111}, tclass: 'cal'}, + {c: 'R', krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'S', ic: 0.075, krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'T', ic: 0.254, krn: {'48': 0.0278}, tclass: 'cal'}, + {c: 'U', ic: 0.0993, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'V', ic: 0.0822, krn: {'48': 0.0278}, tclass: 'cal'}, + {c: 'W', ic: 0.0822, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'X', ic: 0.146, krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'Y', ic: 0.0822, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'Z', ic: 0.0794, krn: {'48': 0.139}, tclass: 'cal'}, + {c: '⋃', tclass: 'symbol'}, + {c: '⋂', tclass: 'symbol'}, + {c: '⊎', tclass: 'symbol'}, + {c: '⋀', tclass: 'symbol'}, + {c: '⋁', tclass: 'symbol'}, + // 60 - 6F + {c: '⊢', tclass: 'symbol'}, + {c: '⊣', tclass: 'symbol2'}, + {c: '', a:.3, d:.2, tclass: 'normal'}, + {c: '', a:.3, d:.2, tclass: 'normal'}, + {c: '', a:.3, d:.2, tclass: 'normal'}, + {c: '', a:.3, d:.2, tclass: 'normal'}, + {c: '{', d:.2, tclass: 'normal'}, + {c: '}', d:.2, tclass: 'normal'}, + {c: '〈', a:.3, d:.2, tclass: 'normal'}, + {c: '〉', a:.3, d:.2, tclass: 'normal'}, + {c: '|', d:.1, tclass: 'vertical'}, + {c: '||', d:.1, tclass: 'vertical'}, + {c: '↕', h:1, d:.15, tclass: 'arrow1a'}, + {c: '⇕', a:.2, d:.1, tclass: 'arrows'}, + {c: '', a:.3, d:.1, tclass: 'lucida'}, + {c: '', tclass: 'symbol'}, + // 70 - 7F + {c: '', h:.04, d:.9, tclass: 'lucida'}, + {c: '∐', a:.4, tclass: 'symbol'}, + {c: '∇', tclass: 'symbol'}, + {c: '∫', h:1, d:.1, ic: 0.111, tclass: 'root'}, + {c: '⊔', tclass: 'symbol'}, + {c: '⊓', tclass: 'symbol'}, + {c: '⊑', tclass: 'symbol'}, + {c: '⊒', tclass: 'symbol'}, + {c: '§', d:.1, tclass: 'normal'}, + {c: '†', d:.1, tclass: 'normal'}, + {c: '‡', d:.1, tclass: 'normal'}, + {c: '¶', a:.3, d:.1, tclass: 'lucida'}, + {c: '♣', tclass: 'symbol'}, + {c: '♦', tclass: 'symbol'}, + {c: '♥', tclass: 'symbol'}, + {c: '♠', tclass: 'symbol'} + ], + + cmex10: [ + // 00 - 0F + {c: '(', h: 0.04, d: 1.16, n: 16, tclass: 'delim1'}, + {c: ')', h: 0.04, d: 1.16, n: 17, tclass: 'delim1'}, + {c: '[', h: 0.04, d: 1.16, n: 104, tclass: 'delim1'}, + {c: ']', h: 0.04, d: 1.16, n: 105, tclass: 'delim1'}, + {c: '', h: 0.04, d: 1.16, n: 106, tclass: 'delim1'}, + {c: '', h: 0.04, d: 1.16, n: 107, tclass: 'delim1'}, + {c: '', h: 0.04, d: 1.16, n: 108, tclass: 'delim1'}, + {c: '', h: 0.04, d: 1.16, n: 109, tclass: 'delim1'}, + {c: '{', h: 0.04, d: 1.16, n: 110, tclass: 'delim1'}, + {c: '}', h: 0.04, d: 1.16, n: 111, tclass: 'delim1'}, + {c: '〈', h: 0.04, d: 1.16, n: 68, tclass: 'delim1c'}, + {c: '〉', h: 0.04, d: 1.16, n: 69, tclass: 'delim1c'}, + {c: '|', h:.7, d:.15, delim: {rep: 12}, tclass: 'vertical1'}, + {c: '||', h:.7, d:.15, delim: {rep: 13}, tclass: 'vertical1'}, + {c: '∕', h: 0.04, d: 1.16, n: 46, tclass: 'delim1b'}, + {c: '∖', h: 0.04, d: 1.16, n: 47, tclass: 'delim1b'}, + // 10 - 1F + {c: '(', h: 0.04, d: 1.76, n: 18, tclass: 'delim2'}, + {c: ')', h: 0.04, d: 1.76, n: 19, tclass: 'delim2'}, + {c: '(', h: 0.04, d: 2.36, n: 32, tclass: 'delim3'}, + {c: ')', h: 0.04, d: 2.36, n: 33, tclass: 'delim3'}, + {c: '[', h: 0.04, d: 2.36, n: 34, tclass: 'delim3'}, + {c: ']', h: 0.04, d: 2.36, n: 35, tclass: 'delim3'}, + {c: '', h: 0.04, d: 2.36, n: 36, tclass: 'delim3'}, + {c: '', h: 0.04, d: 2.36, n: 37, tclass: 'delim3'}, + {c: '', h: 0.04, d: 2.36, n: 38, tclass: 'delim3'}, + {c: '', h: 0.04, d: 2.36, n: 39, tclass: 'delim3'}, + {c: '{', h: 0.04, d: 2.36, n: 40, tclass: 'delim3'}, + {c: '}', h: 0.04, d: 2.36, n: 41, tclass: 'delim3'}, + {c: '〈', h: 0.04, d: 2.36, n: 42, tclass: 'delim3c'}, + {c: '〉', h: 0.04, d: 2.36, n: 43, tclass: 'delim3c'}, + {c: '∕', h: 0.04, d: 2.36, n: 44, tclass: 'delim3b'}, + {c: '∖', h: 0.04, d: 2.36, n: 45, tclass: 'delim3b'}, + // 20 - 2F + {c: '(', h: 0.04, d: 2.96, n: 48, tclass: 'delim4'}, + {c: ')', h: 0.04, d: 2.96, n: 49, tclass: 'delim4'}, + {c: '[', h: 0.04, d: 2.96, n: 50, tclass: 'delim4'}, + {c: ']', h: 0.04, d: 2.96, n: 51, tclass: 'delim4'}, + {c: '', h: 0.04, d: 2.96, n: 52, tclass: 'delim4'}, + {c: '', h: 0.04, d: 2.96, n: 53, tclass: 'delim4'}, + {c: '', h: 0.04, d: 2.96, n: 54, tclass: 'delim4'}, + {c: '', h: 0.04, d: 2.96, n: 55, tclass: 'delim4'}, + {c: '{', h: 0.04, d: 2.96, n: 56, tclass: 'delim4'}, + {c: '}', h: 0.04, d: 2.96, n: 57, tclass: 'delim4'}, + {c: '〈', h: 0.04, d: 2.96, tclass: 'delim4c'}, + {c: '〉', h: 0.04, d: 2.96, tclass: 'delim4c'}, + {c: '∕', h: 0.04, d: 2.96, tclass: 'delim4b'}, + {c: '∖', h: 0.04, d: 2.96, tclass: 'delim4b'}, + {c: '∕', h: 0.04, d: 1.76, n: 30, tclass: 'delim2b'}, + {c: '∖', h: 0.04, d: 1.76, n: 31, tclass: 'delim2b'}, + // 30 - 3F + {c: '', h: .85, d: .2, delim: {top: 48, bot: 64, rep: 66}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {top: 49, bot: 65, rep: 67}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {top: 50, bot: 52, rep: 54}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {top: 51, bot: 53, rep: 55}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {bot: 52, rep: 54}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {bot: 53, rep: 55}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {top: 50, rep: 54}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {top: 51, rep: 55}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {top: 56, mid: 60, bot: 58, rep: 62}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {top: 57, mid: 61, bot: 59, rep: 62}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {top: 56, bot: 58, rep: 62}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {top: 57, bot: 59, rep: 62}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {rep: 63}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {rep: 119}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {rep: 62}, tclass: 'normal'}, + {c: '|', h: .7, d: .15, delim: {top: 120, bot: 121, rep: 63}, tclass: 'vertical2'}, + // 40 - 4F + {c: '', h: .85, d: .2, delim: {top: 56, bot: 59, rep: 62}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {top: 57, bot: 58, rep: 62}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {rep: 66}, tclass: 'normal'}, + {c: '', h: .85, d: .2, delim: {rep: 67}, tclass: 'normal'}, + {c: '〈', h: 0.04, d: 1.76, n: 28, tclass: 'delim2c'}, + {c: '〉', h: 0.04, d: 1.76, n: 29, tclass: 'delim2c'}, + {c: '⊔', h: 0, d: 1, n: 71, tclass: 'bigop1'}, + {c: '⊔', h: 0.1, d: 1.5, tclass: 'bigop2'}, + {c: '∮', h: 0, d: 1.11, ic: 0.095, n: 73, tclass: 'bigop1c'}, + {c: '∮', h: 0, d: 2.22, ic: 0.222, tclass: 'bigop2c'}, + {c: '⊙', h: 0, d: 1, n: 75, tclass: 'bigop1'}, + {c: '⊙', h: 0.1, d: 1.5, tclass: 'bigop2'}, + {c: '⊕', h: 0, d: 1, n: 77, tclass: 'bigop1'}, + {c: '⊕', h: 0.1, d: 1.5, tclass: 'bigop2'}, + {c: '⊗', h: 0, d: 1, n: 79, tclass: 'bigop1'}, + {c: '⊗', h: 0.1, d: 1.5, tclass: 'bigop2'}, + // 50 - 5F + {c: '∑', h: 0, d: 1, n: 88, tclass: 'bigop1a'}, + {c: '∏', h: 0, d: 1, n: 89, tclass: 'bigop1a'}, + {c: '∫', h: 0, d: 1.11, ic: 0.095, n: 90, tclass: 'bigop1c'}, + {c: '∪', h: 0, d: 1, n: 91, tclass: 'bigop1b'}, + {c: '∩', h: 0, d: 1, n: 92, tclass: 'bigop1b'}, + {c: '⊎', h: 0, d: 1, n: 93, tclass: 'bigop1b'}, + {c: '∧', h: 0, d: 1, n: 94, tclass: 'bigop1'}, + {c: '∨', h: 0, d: 1, n: 95, tclass: 'bigop1'}, + {c: '∑', h: 0.1, d: 1.6, tclass: 'bigop2a'}, + {c: '∏', h: 0.1, d: 1.5, tclass: 'bigop2a'}, + {c: '∫', h: 0, d: 2.22, ic: 0.222, tclass: 'bigop2c'}, + {c: '∪', h: 0.1, d: 1.5, tclass: 'bigop2b'}, + {c: '∩', h: 0.1, d: 1.5, tclass: 'bigop2b'}, + {c: '⊎', h: 0.1, d: 1.5, tclass: 'bigop2b'}, + {c: '∧', h: 0.1, d: 1.5, tclass: 'bigop2'}, + {c: '∨', h: 0.1, d: 1.5, tclass: 'bigop2'}, + // 60 - 6F + {c: '∐', h: 0, d: 1, n: 97, tclass: 'bigop1a'}, + {c: '∐', h: 0.1, d: 1.5, tclass: 'bigop2a'}, + {c: '︿', h: 0.722, w: .65, n: 99, tclass: 'wide1'}, + {c: '︿', h: 0.85, w: 1.1, n: 100, tclass: 'wide2'}, + {c: '︿', h: 0.99, w: 1.65, tclass: 'wide3'}, + {c: '⁓', h: 0.722, w: .75, n: 102, tclass: 'wide1a'}, + {c: '⁓', h: 0.8, w: 1.35, n: 103, tclass: 'wide2a'}, + {c: '⁓', h: 0.99, w: 2, tclass: 'wide3a'}, + {c: '[', h: 0.04, d: 1.76, n: 20, tclass: 'delim2'}, + {c: ']', h: 0.04, d: 1.76, n: 21, tclass: 'delim2'}, + {c: '', h: 0.04, d: 1.76, n: 22, tclass: 'delim2'}, + {c: '', h: 0.04, d: 1.76, n: 23, tclass: 'delim2'}, + {c: '', h: 0.04, d: 1.76, n: 24, tclass: 'delim2'}, + {c: '', h: 0.04, d: 1.76, n: 25, tclass: 'delim2'}, + {c: '{', h: 0.04, d: 1.76, n: 26, tclass: 'delim2'}, + {c: '}', h: 0.04, d: 1.76, n: 27, tclass: 'delim2'}, + // 70 - 7F + {c: '', h: 0.04, d: 1.16, n: 113, tclass: 'root'}, + {c: '', h: 0.04, d: 1.76, n: 114, tclass: 'root'}, + {c: '', h: 0.06, d: 2.36, n: 115, tclass: 'root'}, + {c: '', h: 0.08, d: 2.96, n: 116, tclass: 'root'}, + {c: '', h: 0.1, d: 3.75, n: 117, tclass: 'root'}, + {c: '', h: .12, d: 4.5, n: 118, tclass: 'root'}, + {c: '', h: .14, d: 5.7, tclass: 'root'}, + {c: '||', h:.65, d:.15, delim: {top: 126, bot: 127, rep: 119}, tclass: 'vertical2'}, + {c: '▵', h:.4, delim: {top: 120, rep: 63}, tclass: 'arrow1b'}, + {c: '▿', h:.38, delim: {bot: 121, rep: 63}, tclass: 'arrow1b'}, + {c: '', h:.1, tclass: 'symbol'}, + {c: '', h:.1, tclass: 'symbol'}, + {c: '', h:.1, tclass: 'symbol'}, + {c: '', h:.1, tclass: 'symbol'}, + {c: '▵', h:.5, delim: {top: 126, rep: 119}, tclass: 'arrow2b'}, + {c: '▿', h:.6, d:-.1, delim: {bot: 127, rep: 119}, tclass: 'arrow2b'} + ], + + cmti10: [ + // 00 - 0F + {c: 'Γ', ic: 0.133, tclass: 'igreek'}, + {c: 'Δ', tclass: 'igreek'}, + {c: 'Θ', ic: 0.094, tclass: 'igreek'}, + {c: 'Λ', tclass: 'igreek'}, + {c: 'Ξ', ic: 0.153, tclass: 'igreek'}, + {c: 'Π', ic: 0.164, tclass: 'igreek'}, + {c: 'Σ', ic: 0.12, tclass: 'igreek'}, + {c: 'Υ', ic: 0.111, tclass: 'igreek'}, + {c: 'Φ', ic: 0.0599, tclass: 'igreek'}, + {c: 'Ψ', ic: 0.111, tclass: 'igreek'}, + {c: 'Ω', ic: 0.103, tclass: 'igreek'}, + {c: 'ff', ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 14, '108': 15}, tclass: 'italic'}, + {c: 'fi', ic: 0.103, tclass: 'italic'}, + {c: 'fl', ic: 0.103, tclass: 'italic'}, + {c: 'ffi', ic: 0.103, tclass: 'italic'}, + {c: 'ffl', ic: 0.103, tclass: 'italic'}, + // 10 - 1F + {c: 'ı', a:0, ic: 0.0767, tclass: 'italic'}, + {c: 'j', d:.2, ic: 0.0374, tclass: 'italic'}, + {c: '`', tclass: 'iaccent'}, + {c: '´', ic: 0.0969, tclass: 'iaccent'}, + {c: 'ˇ', ic: 0.083, tclass: 'iaccent'}, + {c: '˘', ic: 0.108, tclass: 'iaccent'}, + {c: 'ˉ', ic: 0.103, tclass: 'iaccent'}, + {c: '˚', tclass: 'iaccent'}, + {c: '?', d: 0.17, w: 0.46, tclass: 'italic'}, + {c: 'ß', ic: 0.105, tclass: 'italic'}, + {c: 'æ', a:0, ic: 0.0751, tclass: 'italic'}, + {c: 'œ', a:0, ic: 0.0751, tclass: 'italic'}, + {c: 'ø', ic: 0.0919, tclass: 'italic'}, + {c: 'Æ', ic: 0.12, tclass: 'italic'}, + {c: 'Œ', ic: 0.12, tclass: 'italic'}, + {c: 'Ø', ic: 0.094, tclass: 'italic'}, + // 20 - 2F + {c: '?', krn: {'108': -0.256, '76': -0.321}, tclass: 'italic'}, + {c: '!', ic: 0.124, lig: {'96': 60}, tclass: 'italic'}, + {c: '”', ic: 0.0696, tclass: 'italic'}, + {c: '#', ic: 0.0662, tclass: 'italic'}, + {c: '$', tclass: 'italic'}, + {c: '%', ic: 0.136, tclass: 'italic'}, + {c: '&', ic: 0.0969, tclass: 'italic'}, + {c: '’', ic: 0.124, krn: {'63': 0.102, '33': 0.102}, lig: {'39': 34}, tclass: 'italic'}, + {c: '(', d:.2, ic: 0.162, tclass: 'italic'}, + {c: ')', d:.2, ic: 0.0369, tclass: 'italic'}, + {c: '*', ic: 0.149, tclass: 'italic'}, + {c: '+', a:.1, ic: 0.0369, tclass: 'italic'}, + {c: ',', a:-.3, d:.2, w: 0.278, tclass: 'italic'}, + {c: '-', a:0, ic: 0.0283, lig: {'45': 123}, tclass: 'italic'}, + {c: '.', a:-.25, tclass: 'italic'}, + {c: '/', ic: 0.162, tclass: 'italic'}, + // 30 - 3F + {c: '0', ic: 0.136, tclass: 'italic'}, + {c: '1', ic: 0.136, tclass: 'italic'}, + {c: '2', ic: 0.136, tclass: 'italic'}, + {c: '3', ic: 0.136, tclass: 'italic'}, + {c: '4', ic: 0.136, tclass: 'italic'}, + {c: '5', ic: 0.136, tclass: 'italic'}, + {c: '6', ic: 0.136, tclass: 'italic'}, + {c: '7', ic: 0.136, tclass: 'italic'}, + {c: '8', ic: 0.136, tclass: 'italic'}, + {c: '9', ic: 0.136, tclass: 'italic'}, + {c: ':', ic: 0.0582, tclass: 'italic'}, + {c: ';', ic: 0.0582, tclass: 'italic'}, + {c: '¡', ic: 0.0756, tclass: 'italic'}, + {c: '=', a:0, d:-.1, ic: 0.0662, tclass: 'italic'}, + {c: '¿', tclass: 'italic'}, + {c: '?', ic: 0.122, lig: {'96': 62}, tclass: 'italic'}, + // 40 - 4F + {c: '@', ic: 0.096, tclass: 'italic'}, + {c: 'A', krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'B', ic: 0.103, tclass: 'italic'}, + {c: 'C', ic: 0.145, tclass: 'italic'}, + {c: 'D', ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}, tclass: 'italic'}, + {c: 'E', ic: 0.12, tclass: 'italic'}, + {c: 'F', ic: 0.133, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'}, + {c: 'G', ic: 0.0872, tclass: 'italic'}, + {c: 'H', ic: 0.164, tclass: 'italic'}, + {c: 'I', ic: 0.158, tclass: 'italic'}, + {c: 'J', ic: 0.14, tclass: 'italic'}, + {c: 'K', ic: 0.145, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'}, + {c: 'L', krn: {'84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'M', ic: 0.164, tclass: 'italic'}, + {c: 'N', ic: 0.164, tclass: 'italic'}, + {c: 'O', ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}, tclass: 'italic'}, + // 50 - 5F + {c: 'P', ic: 0.103, krn: {'65': -0.0767}, tclass: 'italic'}, + {c: 'Q', d:.1, ic: 0.094, tclass: 'italic'}, + {c: 'R', ic: 0.0387, krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'S', ic: 0.12, tclass: 'italic'}, + {c: 'T', ic: 0.133, krn: {'121': -0.0767, '101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}, tclass: 'italic'}, + {c: 'U', ic: 0.164, tclass: 'italic'}, + {c: 'V', ic: 0.184, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'}, + {c: 'W', ic: 0.184, krn: {'65': -0.0767}, tclass: 'italic'}, + {c: 'X', ic: 0.158, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'}, + {c: 'Y', ic: 0.194, krn: {'101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}, tclass: 'italic'}, + {c: 'Z', ic: 0.145, tclass: 'italic'}, + {c: '[', d:.1, ic: 0.188, tclass: 'italic'}, + {c: '“', ic: 0.169, tclass: 'italic'}, + {c: ']', d:.1, ic: 0.105, tclass: 'italic'}, + {c: 'ˆ', ic: 0.0665, tclass: 'iaccent'}, + {c: '˙', ic: 0.118, tclass: 'iaccent'}, + // 60 - 6F + {c: '‘', ic: 0.124, lig: {'96': 92}, tclass: 'italic'}, + {c: 'a', a:0, ic: 0.0767, tclass: 'italic'}, + {c: 'b', ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'c', a:0, ic: 0.0565, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'd', ic: 0.103, krn: {'108': 0.0511}, tclass: 'italic'}, + {c: 'e', a:0, ic: 0.0751, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'f', ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 12, '102': 11, '108': 13}, tclass: 'italic'}, + {c: 'g', a:0, d:.2, ic: 0.0885, tclass: 'italic'}, + {c: 'h', ic: 0.0767, tclass: 'italic'}, + {c: 'i', ic: 0.102, tclass: 'italic'}, + {c: 'j', d:.2, ic: 0.145, tclass: 'italic'}, + {c: 'k', ic: 0.108, tclass: 'italic'}, + {c: 'l', ic: 0.103, krn: {'108': 0.0511}, tclass: 'italic'}, + {c: 'm', a:0, ic: 0.0767, tclass: 'italic'}, + {c: 'n', a:0, ic: 0.0767, krn: {'39': -0.102}, tclass: 'italic'}, + {c: 'o', a:0, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + // 70 - 7F + {c: 'p', a:0, d:.2, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'q', a:0, d:.2, ic: 0.0885, tclass: 'italic'}, + {c: 'r', a:0, ic: 0.108, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 's', a:0, ic: 0.0821, tclass: 'italic'}, + {c: 't', ic: 0.0949, tclass: 'italic'}, + {c: 'u', a:0, ic: 0.0767, tclass: 'italic'}, + {c: 'v', a:0, ic: 0.108, tclass: 'italic'}, + {c: 'w', a:0, ic: 0.108, krn: {'108': 0.0511}, tclass: 'italic'}, + {c: 'x', a:0, ic: 0.12, tclass: 'italic'}, + {c: 'y', a:0, d:.2, ic: 0.0885, tclass: 'italic'}, + {c: 'z', a:0, ic: 0.123, tclass: 'italic'}, + {c: '–', a:.1, ic: 0.0921, lig: {'45': 124}, tclass: 'italic'}, + {c: '—', a:.1, ic: 0.0921, tclass: 'italic'}, + {c: '˝', ic: 0.122, tclass: 'iaccent'}, + {c: '˜', ic: 0.116, tclass: 'iaccent'}, + {c: '¨', tclass: 'iaccent'} + ], + + cmbx10: [ + // 00 - 0F + {c: 'Γ', tclass: 'bgreek'}, + {c: 'Δ', tclass: 'bgreek'}, + {c: 'Θ', tclass: 'bgreek'}, + {c: 'Λ', tclass: 'bgreek'}, + {c: 'Ξ', tclass: 'bgreek'}, + {c: 'Π', tclass: 'bgreek'}, + {c: 'Σ', tclass: 'bgreek'}, + {c: 'Υ', tclass: 'bgreek'}, + {c: 'Φ', tclass: 'bgreek'}, + {c: 'Ψ', tclass: 'bgreek'}, + {c: 'Ω', tclass: 'bgreek'}, + {c: 'ff', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 14, '108': 15}, tclass: 'bold'}, + {c: 'fi', tclass: 'bold'}, + {c: 'fl', tclass: 'bold'}, + {c: 'ffi', tclass: 'bold'}, + {c: 'ffl', tclass: 'bold'}, + // 10 - 1F + {c: 'ı', a:0, tclass: 'bold'}, + {c: 'j', d:.2, tclass: 'bold'}, + {c: '`', tclass: 'baccent'}, + {c: '´', tclass: 'baccent'}, + {c: 'ˇ', tclass: 'baccent'}, + {c: '˘', tclass: 'baccent'}, + {c: 'ˉ', tclass: 'baccent'}, + {c: '˚', tclass: 'baccent'}, + {c: '?', tclass: 'bold'}, + {c: 'ß', tclass: 'bold'}, + {c: 'æ', a:0, tclass: 'bold'}, + {c: 'œ', a:0, tclass: 'bold'}, + {c: 'ø', tclass: 'bold'}, + {c: 'Æ', tclass: 'bold'}, + {c: 'Œ', tclass: 'bold'}, + {c: 'Ø', tclass: 'bold'}, + // 20 - 2F + {c: '?', krn: {'108': -0.278, '76': -0.319}, tclass: 'bold'}, + {c: '!', lig: {'96': 60}, tclass: 'bold'}, + {c: '”', tclass: 'bold'}, + {c: '#', tclass: 'bold'}, + {c: '$', tclass: 'bold'}, + {c: '%', tclass: 'bold'}, + {c: '&', tclass: 'bold'}, + {c: '’', krn: {'63': 0.111, '33': 0.111}, lig: {'39': 34}, tclass: 'bold'}, + {c: '(', d:.2, tclass: 'bold'}, + {c: ')', d:.2, tclass: 'bold'}, + {c: '*', tclass: 'bold'}, + {c: '+', a:.1, tclass: 'bold'}, + {c: ',', a:-.3, d:.2, w: 0.278, tclass: 'bold'}, + {c: '-', a:0, lig: {'45': 123}, tclass: 'bold'}, + {c: '.', a:-.25, tclass: 'bold'}, + {c: '/', tclass: 'bold'}, + // 30 - 3F + {c: '0', tclass: 'bold'}, + {c: '1', tclass: 'bold'}, + {c: '2', tclass: 'bold'}, + {c: '3', tclass: 'bold'}, + {c: '4', tclass: 'bold'}, + {c: '5', tclass: 'bold'}, + {c: '6', tclass: 'bold'}, + {c: '7', tclass: 'bold'}, + {c: '8', tclass: 'bold'}, + {c: '9', tclass: 'bold'}, + {c: ':', tclass: 'bold'}, + {c: ';', tclass: 'bold'}, + {c: '¡', tclass: 'bold'}, + {c: '=', a:0, d:-.1, tclass: 'bold'}, + {c: '¿', tclass: 'bold'}, + {c: '?', lig: {'96': 62}, tclass: 'bold'}, + // 40 - 4F + {c: '@', tclass: 'bold'}, + {c: 'A', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'bold'}, + {c: 'B', tclass: 'bold'}, + {c: 'C', tclass: 'bold'}, + {c: 'D', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'bold'}, + {c: 'E', tclass: 'bold'}, + {c: 'F', krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'}, + {c: 'G', tclass: 'bold'}, + {c: 'H', tclass: 'bold'}, + {c: 'I', krn: {'73': 0.0278}, tclass: 'bold'}, + {c: 'J', tclass: 'bold'}, + {c: 'K', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'}, + {c: 'L', krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'bold'}, + {c: 'M', tclass: 'bold'}, + {c: 'N', tclass: 'bold'}, + {c: 'O', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'bold'}, + // 50 - 5F + {c: 'P', krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'bold'}, + {c: 'Q', d:.1, tclass: 'bold'}, + {c: 'R', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'bold'}, + {c: 'S', tclass: 'bold'}, + {c: 'T', krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'bold'}, + {c: 'U', tclass: 'bold'}, + {c: 'V', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'}, + {c: 'W', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'}, + {c: 'X', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'}, + {c: 'Y', ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'bold'}, + {c: 'Z', tclass: 'bold'}, + {c: '[', d:.1, tclass: 'bold'}, + {c: '“', tclass: 'bold'}, + {c: ']', d:.1, tclass: 'bold'}, + {c: 'ˆ', tclass: 'baccent'}, + {c: '˙', tclass: 'baccent'}, + // 60 - 6F + {c: '‘', lig: {'96': 92}, tclass: 'bold'}, + {c: 'a', a:0, krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'b', krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'c', a:0, krn: {'104': -0.0278, '107': -0.0278}, tclass: 'bold'}, + {c: 'd', tclass: 'bold'}, + {c: 'e', a:0, tclass: 'bold'}, + {c: 'f', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}, tclass: 'bold'}, + {c: 'g', a:0, d:.2, ic: 0.0139, krn: {'106': 0.0278}, tclass: 'bold'}, + {c: 'h', krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'i', tclass: 'bold'}, + {c: 'j', d:.2, tclass: 'bold'}, + {c: 'k', krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'bold'}, + {c: 'l', tclass: 'bold'}, + {c: 'm', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'n', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'o', a:0, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'}, + // 70 - 7F + {c: 'p', a:0, d:.2, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'q', a:0, d:.2, tclass: 'bold'}, + {c: 'r', a:0, tclass: 'bold'}, + {c: 's', a:0, tclass: 'bold'}, + {c: 't', krn: {'121': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'u', a:0, krn: {'119': -0.0278}, tclass: 'bold'}, + {c: 'v', a:0, ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'bold'}, + {c: 'w', a:0, ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'bold'}, + {c: 'x', a:0, tclass: 'bold'}, + {c: 'y', a:0, d:.2, ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'bold'}, + {c: 'z', a:0, tclass: 'bold'}, + {c: '–', a:.1, ic: 0.0278, lig: {'45': 124}, tclass: 'bold'}, + {c: '—', a:.1, ic: 0.0278, tclass: 'bold'}, + {c: '˝', tclass: 'baccent'}, + {c: '˜', tclass: 'baccent'}, + {c: '¨', tclass: 'baccent'} + ] +}); + + +jsMath.Setup.Styles({ + '.typeset .cmr10': "font-family: serif", + '.typeset .italic': "font-style: italic", + '.typeset .bold': "font-weight: bold", + '.typeset .lucida': "font-family: 'Lucida Grande'", + '.typeset .asymbol': "font-family: 'Apple Symbols'; font-size: 115%", + '.typeset .cal': "font-family: 'Apple Chancery'", + '.typeset .arrows': "font-family: 'Hiragino Mincho Pro'", + '.typeset .arrow1': "font-family: 'Hiragino Mincho Pro'; position: relative; top: .075em; margin: -1px", + '.typeset .arrow1a': "font-family: 'Hiragino Mincho Pro'; margin:-.3em", + '.typeset .arrow1b': "font-family: AppleGothic; font-size: 50%", + '.typeset .arrow2': "font-family: Symbol; font-size: 140%; position: relative; top: .1em; margin:-1px", + '.typeset .arrow2a': "font-family: Symbol", + '.typeset .arrow2b': "font-family: AppleGothic; font-size: 67%", + '.typeset .harpoon': "font-family: AppleGothic; font-size: 90%", + '.typeset .symbol': "font-family: 'Hiragino Mincho Pro'", + '.typeset .symbol2': "font-family: 'Hiragino Mincho Pro'; margin:-.2em", + '.typeset .symbol3': "font-family: AppleGothic", + '.typeset .delim1': "font-family: Times; font-size: 133%; position:relative; top:.75em", + '.typeset .delim1b': "font-family: 'Hiragino Mincho Pro'; font-size: 133%; position:relative; top:.8em; margin: -.1em", + '.typeset .delim1c': "font-family: Symbol; font-size: 120%; position:relative; top:.8em;", + '.typeset .delim2': "font-family: Baskerville; font-size: 180%; position:relative; top:.75em", + '.typeset .delim2b': "font-family: 'Hiragino Mincho Pro'; font-size: 190%; position:relative; top:.8em; margin: -.1em", + '.typeset .delim2c': "font-family: Symbol; font-size: 167%; position:relative; top:.8em;", + '.typeset .delim3': "font-family: Baskerville; font-size: 250%; position:relative; top:.725em", + '.typeset .delim3b': "font-family: 'Hiragino Mincho Pro'; font-size: 250%; position:relative; top:.8em; margin: -.1em", + '.typeset .delim3c': "font-family: symbol; font-size: 240%; position:relative; top:.775em;", + '.typeset .delim4': "font-family: Baskerville; font-size: 325%; position:relative; top:.7em", + '.typeset .delim4b': "font-family: 'Hiragino Mincho Pro'; font-size: 325%; position:relative; top:.8em; margin: -.1em", + '.typeset .delim4c': "font-family: Symbol; font-size: 300%; position:relative; top:.8em;", + '.typeset .vertical': "font-family: Copperplate", + '.typeset .vertical1': "font-family: Copperplate; font-size: 85%; margin: .15em;", + '.typeset .vertical2': "font-family: Copperplate; font-size: 85%; margin: .17em;", + '.typeset .greek': "font-family: serif", + '.typeset .igreek': "font-family: serif; font-style:italic", + '.typeset .bgreek': "font-family: serif; font-weight:bold", + '.typeset .bigop1': "font-family: 'Hiragino Mincho Pro'; font-size: 133%; position: relative; top: .85em; margin:-.05em", + '.typeset .bigop1a': "font-family: Baskerville; font-size: 100%; position: relative; top: .775em;", + '.typeset .bigop1b': "font-family: 'Hiragino Mincho Pro'; font-size: 160%; position: relative; top: .7em; margin:-.1em", + '.typeset .bigop1c': "font-family: 'Apple Symbols'; font-size: 125%; position: relative; top: .75em; margin:-.1em;", + '.typeset .bigop2': "font-family: 'Hiragino Mincho Pro'; font-size: 200%; position: relative; top: .8em; margin:-.07em", + '.typeset .bigop2a': "font-family: Baskerville; font-size: 175%; position: relative; top: .7em;", + '.typeset .bigop2b': "font-family: 'Hiragino Mincho Pro'; font-size: 270%; position: relative; top: .62em; margin:-.1em", + '.typeset .bigop2c': "font-family: 'Apple Symbols'; font-size: 250%; position: relative; top: .7em; margin:-.17em;", + '.typeset .wide1': "font-size: 67%; position: relative; top:-.8em", + '.typeset .wide2': "font-size: 110%; position: relative; top:-.5em", + '.typeset .wide3': "font-size: 175%; position: relative; top:-.32em", + '.typeset .wide1a': "font-size: 75%; position: relative; top:-.5em", + '.typeset .wide2a': "font-size: 133%; position: relative; top: -.15em", + '.typeset .wide3a': "font-size: 200%; position: relative; top: -.05em", + '.typeset .root': "font-family: Baskerville;", + '.typeset .accent': "position: relative; top: .02em", + '.typeset .iaccent': "position: relative; top: .02em; font-style:italic", + '.typeset .baccent': "position: relative; top: .02em; font-weight:bold" +}); + +/* + * Check for ability to access Apple Symbols font + */ + +jsMath.noAppleSymbols = (jsMath.BBoxFor('∣').w == + jsMath.BBoxFor('').w); + +if (jsMath.noAppleSymbols) { + jsMath.Update.TeXfonts({ + cmsy10: { + '16': {c: '', tclass: 'normal'}, + '22': {c: '≺', tclass: 'normal'}, + '23': {c: '≻', tclass: 'normal'}, + '91': {c: '∪'}, + '92': {c: '∩'}, + '93': {c: '∪+'}, + '94': {c: '∧'}, + '95': {c: '∨'}, + '96': {c: '|', tclass: 'normal'}, + '109': {c: '⇑', h:.9, d:.2, tclass: 'arrow2a'} + }, + + cmex10: { + '85': {c: '∪+'}, + '93': {c: '∪+'} + } + }); + + jsMath.Macro('rightleftharpoons','\\unicode{x21CC}'); +} else { + jsMath.Setup.Styles({ + '.typeset .harpoon': "font-family: 'Apple Symbols'; font-size: 125%" + }); + +} + + +// +// Adjust for OmniWeb +// +if (jsMath.browser == 'OmniWeb') { + jsMath.Update.TeXfonts({ + cmsy10: { + '55': {c: '˫'}, + '104': {c: ''}, + '105': {c: ''} + } + }); + + jsMath.Setup.Styles({ + '.typeset .arrow2': 'font-family: Symbol; font-size: 100%; position: relative; top: -.1em; margin:-1px' + }); + + if (jsMath.noAppleSymbols) { + jsMath.Update.TeXfonts({ + cmsy10: { + '22': {c: '≺', tclass: 'normal'}, + '23': {c: '≻', tclass: 'normal'}, + '96': {c: '|', tclass: 'normal'} + } + }); + } + +} + +// +// Adjust for Opera +// +if (jsMath.browser == 'Opera') { + jsMath.Setup.Styles({ + '.typeset .bigop1c': "margin:0pt .12em 0pt 0pt;", + '.typeset .bigop2c': "margin:0pt .12em 0pt 0pt;" + }); +} + +if (jsMath.browser == 'Mozilla') {jsMath.Setup.Script('jsMath-fallback-mac-mozilla.js')} +if (jsMath.browser == 'MSIE') {jsMath.Setup.Script('jsMath-fallback-mac-msie.js')} + + +/* + * No access to TeX "not" character, so fake this + */ +jsMath.Macro('not','\\mathrel{\\rlap{\\kern 4mu/}}'); + +jsMath.Box.defaultH = 0.8; + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/jsMath-fallback-pc.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/jsMath-fallback-pc.js new file mode 100644 index 0000000..49a9393 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/jsMath-fallback-pc.js @@ -0,0 +1,977 @@ +/* + * jsMath-fallback-pc.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file makes changes needed for when the TeX fonts are not available + * with a browser on the PC. + * + * --------------------------------------------------------------------- + * + * Copyright 2004-2006 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +/******************************************************************** + * + * Here we replace the TeX character mappings by equivalent unicode + * points when possible, and adjust the character dimensions + * based on the fonts we hope we get them from (the styles are set + * to try to use the best characters available in the standard + * fonts). + */ + +jsMath.Add(jsMath.TeX,{ + + cmr10: [ + // 00 - 0F + {c: 'Γ', tclass: 'greek'}, + {c: 'Δ', tclass: 'greek'}, + {c: 'Θ', tclass: 'greek'}, + {c: 'Λ', tclass: 'greek'}, + {c: 'Ξ', tclass: 'greek'}, + {c: 'Π', tclass: 'greek'}, + {c: 'Σ', tclass: 'greek'}, + {c: 'Υ', tclass: 'greek'}, + {c: 'Φ', tclass: 'greek'}, + {c: 'Ψ', tclass: 'greek'}, + {c: 'Ω', tclass: 'greek'}, + {c: 'ff', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 14, '108': 15}, tclass: 'normal'}, + {c: 'fi', tclass: 'normal'}, + {c: 'fl', tclass: 'normal'}, + {c: 'ffi', tclass: 'normal'}, + {c: 'ffl', tclass: 'normal'}, + // 10 - 1F + {c: 'ı', a:0, tclass: 'normal'}, + {c: 'j', d:.2, tclass: 'normal'}, + {c: 'ˋ', tclass: 'accent'}, + {c: 'ˊ', tclass: 'accent'}, + {c: 'ˇ', tclass: 'accent'}, + {c: '˘', tclass: 'accent'}, + {c: 'ˉ', tclass: 'accent'}, + {c: '˚', tclass: 'accent'}, + {c: '̧', tclass: 'normal'}, + {c: 'ß', tclass: 'normal'}, + {c: 'æ', a:0, tclass: 'normal'}, + {c: 'œ', a:0, tclass: 'normal'}, + {c: 'ø', tclass: 'normal'}, + {c: 'Æ', tclass: 'normal'}, + {c: 'Œ', tclass: 'normal'}, + {c: 'Ø', tclass: 'normal'}, + // 20 - 2F + {c: '?', krn: {'108': -0.278, '76': -0.319}, tclass: 'normal'}, + {c: '!', lig: {'96': 60}, tclass: 'normal'}, + {c: '”', tclass: 'normal'}, + {c: '#', tclass: 'normal'}, + {c: '$', tclass: 'normal'}, + {c: '%', tclass: 'normal'}, + {c: '&', tclass: 'normal'}, + {c: '’', krn: {'63': 0.111, '33': 0.111}, lig: {'39': 34}, tclass: 'normal'}, + {c: '(', d:.2, tclass: 'normal'}, + {c: ')', d:.2, tclass: 'normal'}, + {c: '*', tclass: 'normal'}, + {c: '+', a:.1, tclass: 'normal'}, + {c: ',', a:-.3, d:.2, w: 0.278, tclass: 'normal'}, + {c: '-', a:0, lig: {'45': 123}, tclass: 'normal'}, + {c: '.', a:-.25, tclass: 'normal'}, + {c: '/', tclass: 'normal'}, + // 30 - 3F + {c: '0', tclass: 'normal'}, + {c: '1', tclass: 'normal'}, + {c: '2', tclass: 'normal'}, + {c: '3', tclass: 'normal'}, + {c: '4', tclass: 'normal'}, + {c: '5', tclass: 'normal'}, + {c: '6', tclass: 'normal'}, + {c: '7', tclass: 'normal'}, + {c: '8', tclass: 'normal'}, + {c: '9', tclass: 'normal'}, + {c: ':', tclass: 'normal'}, + {c: ';', tclass: 'normal'}, + {c: '¡', tclass: 'normal'}, + {c: '=', a:0, d:-.1, tclass: 'normal'}, + {c: '¿', tclass: 'normal'}, + {c: '?', lig: {'96': 62}, tclass: 'normal'}, + // 40 - 4F + {c: '@', tclass: 'normal'}, + {c: 'A', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'normal'}, + {c: 'B', tclass: 'normal'}, + {c: 'C', tclass: 'normal'}, + {c: 'D', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'normal'}, + {c: 'E', tclass: 'normal'}, + {c: 'F', krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'}, + {c: 'G', tclass: 'normal'}, + {c: 'H', tclass: 'normal'}, + {c: 'I', krn: {'73': 0.0278}, tclass: 'normal'}, + {c: 'J', tclass: 'normal'}, + {c: 'K', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'}, + {c: 'L', krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'normal'}, + {c: 'M', tclass: 'normal'}, + {c: 'N', tclass: 'normal'}, + {c: 'O', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'normal'}, + // 50 - 5F + {c: 'P', krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'normal'}, + {c: 'Q', d:.2, tclass: 'normal'}, + {c: 'R', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'normal'}, + {c: 'S', tclass: 'normal'}, + {c: 'T', krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'normal'}, + {c: 'U', tclass: 'normal'}, + {c: 'V', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'}, + {c: 'W', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'}, + {c: 'X', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'}, + {c: 'Y', ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'normal'}, + {c: 'Z', tclass: 'normal'}, + {c: '[', d:.1, tclass: 'normal'}, + {c: '“', tclass: 'normal'}, + {c: ']', d:.1, tclass: 'normal'}, + {c: 'ˆ', tclass: 'accent'}, + {c: '˙', tclass: 'accent'}, + // 60 - 6F + {c: '‘', lig: {'96': 92}, tclass: 'normal'}, + {c: 'a', a:0, krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'b', krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'c', a:0, krn: {'104': -0.0278, '107': -0.0278}, tclass: 'normal'}, + {c: 'd', tclass: 'normal'}, + {c: 'e', a:0, tclass: 'normal'}, + {c: 'f', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}, tclass: 'normal'}, + {c: 'g', a:0, d:.2, ic: 0.0139, krn: {'106': 0.0278}, tclass: 'normal'}, + {c: 'h', krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'i', tclass: 'normal'}, + {c: 'j', d:.2, tclass: 'normal'}, + {c: 'k', krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'normal'}, + {c: 'l', tclass: 'normal'}, + {c: 'm', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'n', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'o', a:0, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'}, + // 70 - 7F + {c: 'p', a:0, d:.2, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'q', a:0, d:.2, tclass: 'normal'}, + {c: 'r', a:0, tclass: 'normal'}, + {c: 's', a:0, tclass: 'normal'}, + {c: 't', krn: {'121': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'u', a:0, krn: {'119': -0.0278}, tclass: 'normal'}, + {c: 'v', a:0, ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'normal'}, + {c: 'w', a:0, ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'normal'}, + {c: 'x', a:0, tclass: 'normal'}, + {c: 'y', a:0, d:.2, ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'normal'}, + {c: 'z', a:0, tclass: 'normal'}, + {c: '–', a:.1, ic: 0.0278, lig: {'45': 124}, tclass: 'normal'}, + {c: '—', a:.1, ic: 0.0278, tclass: 'normal'}, + {c: '˝', tclass: 'accent'}, + {c: '˜', tclass: 'accent'}, + {c: '¨', tclass: 'accent'} + ], + + cmmi10: [ + // 00 - 0F + {c: 'Γ', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}, tclass: 'igreek'}, + {c: 'Δ', krn: {'127': 0.167}, tclass: 'igreek'}, + {c: 'Θ', ic: 0.0278, krn: {'127': 0.0833}, tclass: 'igreek'}, + {c: 'Λ', krn: {'127': 0.167}, tclass: 'igreek'}, + {c: 'Ξ', ic: 0.0757, krn: {'127': 0.0833}, tclass: 'igreek'}, + {c: 'Π', ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'igreek'}, + {c: 'Σ', ic: 0.0576, krn: {'127': 0.0833}, tclass: 'igreek'}, + {c: 'Υ', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0556}, tclass: 'igreek'}, + {c: 'Φ', krn: {'127': 0.0833}, tclass: 'igreek'}, + {c: 'Ψ', ic: 0.11, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'igreek'}, + {c: 'Ω', ic: 0.0502, krn: {'127': 0.0833}, tclass: 'igreek'}, + {c: 'α', a:0, ic: 0.0037, krn: {'127': 0.0278}, tclass: 'greek'}, + {c: 'β', d:.2, ic: 0.0528, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'γ', a:0, d:.2, ic: 0.0556, tclass: 'greek'}, + {c: 'δ', ic: 0.0378, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'greek'}, + {c: 'ε', a:0, krn: {'127': 0.0556}, tclass: 'lucida'}, + // 10 - 1F + {c: 'ζ', d:.2, ic: 0.0738, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'η', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0556}, tclass: 'greek'}, + {c: 'θ', ic: 0.0278, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'ι', a:0, krn: {'127': 0.0556}, tclass: 'greek'}, + {c: 'κ', a:0, tclass: 'greek'}, + {c: 'λ', tclass: 'greek'}, + {c: 'μ', a:0, d:.2, krn: {'127': 0.0278}, tclass: 'greek'}, + {c: 'ν', a:0, ic: 0.0637, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}, tclass: 'greek'}, + {c: 'ξ', d:.2, ic: 0.046, krn: {'127': 0.111}, tclass: 'greek'}, + {c: 'π', a:0, ic: 0.0359, tclass: 'greek'}, + {c: 'ρ', a:0, d:.2, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'σ', a:0, ic: 0.0359, krn: {'59': -0.0556, '58': -0.0556}, tclass: 'greek'}, + {c: 'τ', a:0, ic: 0.113, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}, tclass: 'greek'}, + {c: 'υ', a:0, ic: 0.0359, krn: {'127': 0.0278}, tclass: 'greek'}, + {c: 'φ', a:.1, d:.2, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'χ', a:0, d:.2, krn: {'127': 0.0556}, tclass: 'greek'}, + // 20 - 2F + {c: 'ψ', a:.1, d:.2, ic: 0.0359, krn: {'127': 0.111}, tclass: 'greek'}, + {c: 'ω', a:0, ic: 0.0359, tclass: 'greek'}, + {c: 'ε', a:0, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'ϑ', krn: {'127': 0.0833}, tclass: 'lucida'}, + {c: 'ϖ', a:0, ic: 0.0278, tclass: 'lucida'}, + {c: 'ϱ', a:0, d:.2, krn: {'127': 0.0833}, tclass: 'lucida'}, + {c: 'ς', a:0, d:.2, ic: 0.0799, krn: {'127': 0.0833}, tclass: 'lucida'}, + {c: 'ϕ', a:.1, d:.2, krn: {'127': 0.0833}, tclass: 'lucida'}, + {c: '↼', a:0, d:-.2, tclass: 'arrows'}, + {c: '↽', a:0, d:-.1, tclass: 'arrows'}, + {c: '⇀', a:0, d:-.2, tclass: 'arrows'}, + {c: '⇁', a:0, d:-.1, tclass: 'arrows'}, + {c: '˓', a:.1, tclass: 'symbol'}, + {c: '˒', a:.1, tclass: 'symbol'}, + {c: '▹', tclass: 'symbol'}, + {c: '◃', tclass: 'symbol'}, + // 30 - 3F + {c: '0', tclass: 'normal'}, + {c: '1', tclass: 'normal'}, + {c: '2', tclass: 'normal'}, + {c: '3', tclass: 'normal'}, + {c: '4', tclass: 'normal'}, + {c: '5', tclass: 'normal'}, + {c: '6', tclass: 'normal'}, + {c: '7', tclass: 'normal'}, + {c: '8', tclass: 'normal'}, + {c: '9', tclass: 'normal'}, + {c: '.', a:-.3, tclass: 'normal'}, + {c: ',', a:-.3, d:.2, tclass: 'normal'}, + {c: '<', a:.1, tclass: 'normal'}, + {c: '/', d:.1, krn: {'1': -0.0556, '65': -0.0556, '77': -0.0556, '78': -0.0556, '89': 0.0556, '90': -0.0556}, tclass: 'normal'}, + {c: '>', a:.1, tclass: 'normal'}, + {c: '⋆', a:0, tclass: 'arial'}, + // 40 - 4F + {c: '∂', ic: 0.0556, krn: {'127': 0.0833}, tclass: 'normal'}, + {c: 'A', krn: {'127': 0.139}, tclass: 'italic'}, + {c: 'B', ic: 0.0502, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'C', ic: 0.0715, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'D', ic: 0.0278, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 'E', ic: 0.0576, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'F', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}, tclass: 'italic'}, + {c: 'G', krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'H', ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'italic'}, + {c: 'I', ic: 0.0785, krn: {'127': 0.111}, tclass: 'italic'}, + {c: 'J', ic: 0.0962, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.167}, tclass: 'italic'}, + {c: 'K', ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'italic'}, + {c: 'L', krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'M', ic: 0.109, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'N', ic: 0.109, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'O', ic: 0.0278, krn: {'127': 0.0833}, tclass: 'italic'}, + // 50 - 5F + {c: 'P', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}, tclass: 'italic'}, + {c: 'Q', d:.2, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'R', ic: 0.00773, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'S', ic: 0.0576, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'T', ic: 0.139, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'U', ic: 0.109, krn: {'59': -0.111, '58': -0.111, '61': -0.0556, '127': 0.0278}, tclass: 'italic'}, + {c: 'V', ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}, tclass: 'italic'}, + {c: 'W', ic: 0.139, krn: {'59': -0.167, '58': -0.167, '61': -0.111}, tclass: 'italic'}, + {c: 'X', ic: 0.0785, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'Y', ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}, tclass: 'italic'}, + {c: 'Z', ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: '♭', tclass: 'symbol'}, + {c: '♮', tclass: 'symbol'}, + {c: '♯', tclass: 'symbol'}, + {c: '', a:0, d:-.1, tclass: 'arial'}, + {c: '', a:0, d:-.1, tclass: 'arial'}, + // 60 - 6F + {c: 'ℓ', krn: {'127': 0.111}, tclass: 'italic'}, + {c: 'a', a:0, tclass: 'italic'}, + {c: 'b', tclass: 'italic'}, + {c: 'c', a:0, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 'd', krn: {'89': 0.0556, '90': -0.0556, '106': -0.111, '102': -0.167, '127': 0.167}, tclass: 'italic'}, + {c: 'e', a:0, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 'f', d:.2, ic: 0.108, krn: {'59': -0.0556, '58': -0.0556, '127': 0.167}, tclass: 'italic'}, + {c: 'g', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'h', krn: {'127': -0.0278}, tclass: 'italic'}, + {c: 'i', tclass: 'italic'}, + {c: 'j', d:.2, ic: 0.0572, krn: {'59': -0.0556, '58': -0.0556}, tclass: 'italic'}, + {c: 'k', ic: 0.0315, tclass: 'italic'}, + {c: 'l', ic: 0.0197, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'm', a:0, tclass: 'italic'}, + {c: 'n', a:0, tclass: 'italic'}, + {c: 'o', a:0, krn: {'127': 0.0556}, tclass: 'italic'}, + // 70 - 7F + {c: 'p', a:0, d:.2, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'q', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'r', a:0, ic: 0.0278, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'italic'}, + {c: 's', a:0, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 't', krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'u', a:0, krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'v', a:0, ic: 0.0359, krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'w', a:0, ic: 0.0269, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'x', a:0, krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'y', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 'z', a:0, ic: 0.044, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 'ı', a:0, krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'j', d:.2, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: '℘', a:0, d:.2, krn: {'127': 0.111}, tclass: 'arial'}, + {c: '', ic: 0.154, tclass: 'symbol'}, + {c: '̑', ic: 0.399, tclass: 'normal'} + ], + + cmsy10: [ + // 00 - 0F + {c: '', a:.1, tclass: 'symbol'}, + {c: '·', a:0, d:-.2, tclass: 'normal'}, + {c: '×', a:0, tclass: 'normal'}, + {c: '*', a:0, tclass: 'normal'}, + {c: '÷', a:0, tclass: 'normal'}, + {c: '◊', tclass: 'symbol'}, + {c: '±', a:.1, tclass: 'normal'}, + {c: '∓', tclass: 'symbol'}, + {c: '⊕', tclass: 'symbol'}, + {c: '⊖', tclass: 'symbol'}, + {c: '⊗', tclass: 'symbol'}, + {c: '⊘', tclass: 'symbol'}, + {c: '⊙', tclass: 'symbol'}, + {c: '◯', tclass: 'arial'}, + {c: '∘', a:0, d:-.1, tclass: 'symbol2'}, + {c: '•', a:0, d:-.2, tclass: 'symbol'}, + // 10 - 1F + {c: '≍', a:.1, tclass: 'symbol2'}, + {c: '≡', a:.1, tclass: 'symbol2'}, + {c: '⊆', tclass: 'symbol'}, + {c: '⊇', tclass: 'symbol'}, + {c: '≤', tclass: 'symbol'}, + {c: '≥', tclass: 'symbol'}, + {c: '≼', tclass: 'symbol'}, + {c: '≽', tclass: 'symbol'}, + {c: '~', a:0, d: -.2, tclass: 'normal'}, + {c: '≈', a:.1, d:-.1, tclass: 'symbol'}, + {c: '⊂', tclass: 'symbol'}, + {c: '⊃', tclass: 'symbol'}, + {c: '≪', tclass: 'symbol'}, + {c: '≫', tclass: 'symbol'}, + {c: '≺', tclass: 'symbol'}, + {c: '≻', tclass: 'symbol'}, + // 20 - 2F + {c: '←', a:-.1, tclass: 'arrow1'}, + {c: '→', a:-.1, tclass: 'arrow1'}, + {c: '↑', a:.2, d:0, tclass: 'arrow1a'}, + {c: '↓', a:.2, d:0, tclass: 'arrow1a'}, + {c: '↔', a:-.1, tclass: 'arrow1'}, + {c: '↗', a:.1, tclass: 'arrows'}, + {c: '↘', a:.1, tclass: 'arrows'}, + {c: '≃', a: .1, tclass: 'symbol2'}, + {c: '⇐', a:-.1, tclass: 'arrow2'}, + {c: '⇒', a:-.1, tclass: 'arrow2'}, + {c: '⇑', a:.2, d:.1, tclass: 'arrow1a'}, + {c: '⇓', a:.2, d:.1, tclass: 'arrow1a'}, + {c: '⇔', a:-.1, tclass: 'arrow2'}, + {c: '↖', a:.1, tclass: 'arrows'}, + {c: '↙', a:.1, tclass: 'arrows'}, + {c: '∝', a:.1, tclass: 'normal'}, + // 30 - 3F + {c: '', a: 0, tclass: 'lucida'}, + {c: '∞', a:.1, tclass: 'symbol'}, + {c: '∈', tclass: 'symbol'}, + {c: '∋', tclass: 'symbol'}, + {c: '', tclass: 'symbol'}, + {c: '', tclass: 'symbol'}, + {c: '/', d:.2, tclass: 'normal'}, + {c: '', tclass: 'symbol'}, + {c: '∀', tclass: 'symbol'}, + {c: '∃', tclass: 'symbol'}, + {c: '¬', a:0, d:-.1, tclass: 'symbol'}, + {c: '∅', tclass: 'symbol'}, + {c: 'ℜ', tclass: 'symbol'}, + {c: 'ℑ', tclass: 'symbol'}, + {c: '⊤', tclass: 'symbol'}, + {c: '⊥', tclass: 'symbol'}, + // 40 - 4F + {c: 'ℵ', tclass: 'symbol'}, + {c: 'A', krn: {'48': 0.194}, tclass: 'cal'}, + {c: 'B', ic: 0.0304, krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'C', ic: 0.0583, krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'D', ic: 0.0278, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'E', ic: 0.0894, krn: {'48': 0.111}, tclass: 'cal'}, + {c: 'F', ic: 0.0993, krn: {'48': 0.111}, tclass: 'cal'}, + {c: 'G', d:.2, ic: 0.0593, krn: {'48': 0.111}, tclass: 'cal'}, + {c: 'H', ic: 0.00965, krn: {'48': 0.111}, tclass: 'cal'}, + {c: 'I', ic: 0.0738, krn: {'48': 0.0278}, tclass: 'cal'}, + {c: 'J', d:.2, ic: 0.185, krn: {'48': 0.167}, tclass: 'cal'}, + {c: 'K', ic: 0.0144, krn: {'48': 0.0556}, tclass: 'cal'}, + {c: 'L', krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'M', krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'N', ic: 0.147, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'O', ic: 0.0278, krn: {'48': 0.111}, tclass: 'cal'}, + // 50 - 5F + {c: 'P', ic: 0.0822, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'Q', d:.2, krn: {'48': 0.111}, tclass: 'cal'}, + {c: 'R', krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'S', ic: 0.075, krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'T', ic: 0.254, krn: {'48': 0.0278}, tclass: 'cal'}, + {c: 'U', ic: 0.0993, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'V', ic: 0.0822, krn: {'48': 0.0278}, tclass: 'cal'}, + {c: 'W', ic: 0.0822, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'X', ic: 0.146, krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'Y', ic: 0.0822, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'Z', ic: 0.0794, krn: {'48': 0.139}, tclass: 'cal'}, + {c: '⋃', tclass: 'symbol'}, + {c: '⋂', tclass: 'symbol'}, + {c: '⊎', tclass: 'symbol'}, + {c: '⋀', tclass: 'symbol'}, + {c: '⋁', tclass: 'symbol'}, + // 60 - 6F + {c: '⊢', tclass: 'symbol'}, + {c: '⊣', tclass: 'symbol'}, + {c: '⌊', a:.3, d:.2, tclass: 'arial'}, + {c: '⌋', a:.3, d:.2, tclass: 'arial'}, + {c: '⌈', a:.3, d:.2, tclass: 'arial'}, + {c: '⌉', a:.3, d:.2, tclass: 'arial'}, + {c: '{', d:.2, tclass: 'normal'}, + {c: '}', d:.2, tclass: 'normal'}, + {c: '〈', a:.3, d:.2, tclass: 'symbol'}, + {c: '〉', a:.3, d:.2, tclass: 'symbol'}, + {c: '∣', d:.1, tclass: 'symbol'}, + {c: '∥', d:.1, tclass: 'symbol'}, + {c: '↕', a:.2, d:0, tclass: 'arrow1a'}, + {c: '⇕', a:.3, d:0, tclass: 'arrow1a'}, + {c: '∖', a:.3, d:.1, tclass: 'symbol'}, + {c: '≀', tclass: 'symbol'}, + // 70 - 7F + {c: '', h:.04, d:.8, tclass: 'symbol'}, + {c: '∐', a:.4, tclass: 'symbol'}, + {c: '∇', tclass: 'symbol'}, + {c: '', a:.4, d:.1, ic: 0.111, tclass: 'lucida'}, + {c: '⊔', tclass: 'symbol'}, + {c: '⊓', tclass: 'symbol'}, + {c: '⊑', tclass: 'symbol'}, + {c: '⊒', tclass: 'symbol'}, + {c: '§', d:.1, tclass: 'normal'}, + {c: '†', d:.1, tclass: 'normal'}, + {c: '‡', d:.1, tclass: 'normal'}, + {c: '¶', a:.3, d:.1, tclass: 'lucida'}, + {c: '♣', tclass: 'arial'}, + {c: '♢', tclass: 'arial'}, + {c: '♡', tclass: 'arial'}, + {c: '♠', tclass: 'arial'} + ], + + cmex10: [ + // 00 - 0F + {c: '(', h: 0.04, d: 1.16, n: 16, tclass: 'delim1'}, + {c: ')', h: 0.04, d: 1.16, n: 17, tclass: 'delim1'}, + {c: '[', h: 0.04, d: 1.16, n: 104, tclass: 'delim1'}, + {c: ']', h: 0.04, d: 1.16, n: 105, tclass: 'delim1'}, + {c: '⌈', h: 0.04, d: 1.16, n: 106, tclass: 'delim1a'}, + {c: '⌉', h: 0.04, d: 1.16, n: 107, tclass: 'delim1a'}, + {c: '⌊', h: 0.04, d: 1.16, n: 108, tclass: 'delim1a'}, + {c: '⌋', h: 0.04, d: 1.16, n: 109, tclass: 'delim1a'}, + {c: '{', h: 0.04, d: 1.16, n: 110, tclass: 'delim1'}, + {c: '}', h: 0.04, d: 1.16, n: 111, tclass: 'delim1'}, + {c: '〈', h: 0.04, d: 1.16, n: 68, tclass: 'delim1b'}, + {c: '〉', h: 0.04, d: 1.16, n: 69, tclass: 'delim1b'}, + {c: '∣', h:.7, d:.1, delim: {rep: 12}, tclass: 'symbol'}, + {c: '∥', h:.7, d:.1, delim: {rep: 13}, tclass: 'symbol'}, + {c: '/', h: 0.04, d: 1.16, n: 46, tclass: 'delim1a'}, + {c: '∖', h: 0.04, d: 1.16, n: 47, tclass: 'delim1a'}, + // 10 - 1F + {c: '(', h: 0.04, d: 1.76, n: 18, tclass: 'delim2'}, + {c: ')', h: 0.04, d: 1.76, n: 19, tclass: 'delim2'}, + {c: '(', h: 0.04, d: 2.36, n: 32, tclass: 'delim3'}, + {c: ')', h: 0.04, d: 2.36, n: 33, tclass: 'delim3'}, + {c: '[', h: 0.04, d: 2.36, n: 34, tclass: 'delim3'}, + {c: ']', h: 0.04, d: 2.36, n: 35, tclass: 'delim3'}, + {c: '⌈', h: 0.04, d: 2.36, n: 36, tclass: 'delim3a'}, + {c: '⌉', h: 0.04, d: 2.36, n: 37, tclass: 'delim3a'}, + {c: '⌊', h: 0.04, d: 2.36, n: 38, tclass: 'delim3a'}, + {c: '⌋', h: 0.04, d: 2.36, n: 39, tclass: 'delim3a'}, + {c: '{', h: 0.04, d: 2.36, n: 40, tclass: 'delim3'}, + {c: '}', h: 0.04, d: 2.36, n: 41, tclass: 'delim3'}, + {c: '〈', h: 0.04, d: 2.36, n: 42, tclass: 'delim3b'}, + {c: '〉', h: 0.04, d: 2.36, n: 43, tclass: 'delim3b'}, + {c: '/', h: 0.04, d: 2.36, n: 44, tclass: 'delim3a'}, + {c: '∖', h: 0.04, d: 2.36, n: 45, tclass: 'delim3a'}, + // 20 - 2F + {c: '(', h: 0.04, d: 2.96, n: 48, tclass: 'delim4'}, + {c: ')', h: 0.04, d: 2.96, n: 49, tclass: 'delim4'}, + {c: '[', h: 0.04, d: 2.96, n: 50, tclass: 'delim4'}, + {c: ']', h: 0.04, d: 2.96, n: 51, tclass: 'delim4'}, + {c: '⌈', h: 0.04, d: 2.96, n: 52, tclass: 'delim4a'}, + {c: '⌉', h: 0.04, d: 2.96, n: 53, tclass: 'delim4a'}, + {c: '⌊', h: 0.04, d: 2.96, n: 54, tclass: 'delim4a'}, + {c: '⌋', h: 0.04, d: 2.96, n: 55, tclass: 'delim4a'}, + {c: '{', h: 0.04, d: 2.96, n: 56, tclass: 'delim4'}, + {c: '}', h: 0.04, d: 2.96, n: 57, tclass: 'delim4'}, + {c: '〈', h: 0.04, d: 2.96, tclass: 'delim4b'}, + {c: '〉', h: 0.04, d: 2.96, tclass: 'delim4b'}, + {c: '/', h: 0.04, d: 2.96, tclass: 'delim4a'}, + {c: '∖', h: 0.04, d: 2.96, tclass: 'delim4a'}, + {c: '/', h: 0.04, d: 1.76, n: 30, tclass: 'delim2a'}, + {c: '∖', h: 0.04, d: 1.76, n: 31, tclass: 'delim2a'}, + // 30 - 3F + {c: 'æ', h: .8, d: .2, delim: {top: 48, bot: 64, rep: 66}, tclass: 'delimx'}, + {c: 'ö', h: .8, d: .2, delim: {top: 49, bot: 65, rep: 67}, tclass: 'delimx'}, + {c: 'é', h: .8, d: .2, delim: {top: 50, bot: 52, rep: 54}, tclass: 'delimx'}, + {c: 'ù', h: .8, d: .2, delim: {top: 51, bot: 53, rep: 55}, tclass: 'delimx'}, + {c: 'ë', h: .8, d: .2, delim: {bot: 52, rep: 54}, tclass: 'delimx'}, + {c: 'û', h: .8, d: .2, delim: {bot: 53, rep: 55}, tclass: 'delimx'}, + {c: 'ê', h: .8, d: .2, delim: {top: 50, rep: 54}, tclass: 'delimx'}, + {c: 'ú', h: .8, d: .2, delim: {top: 51, rep: 55}, tclass: 'delimx'}, + {c: 'ì', h: .8, d: .2, delim: {top: 56, mid: 60, bot: 58, rep: 62}, tclass: 'delimx'}, + {c: 'ü', h: .8, d: .2, delim: {top: 57, mid: 61, bot: 59, rep: 62}, tclass: 'delimx'}, + {c: 'î', h: .8, d: .2, delim: {top: 56, bot: 58, rep: 62}, tclass: 'delimx'}, + {c: 'þ', h: .8, d: .2, delim: {top: 57, bot: 59, rep: 62}, tclass: 'delimx'}, + {c: 'í', h: .8, d: .2, delim: {rep: 63}, tclass: 'delimx'}, + {c: 'ý', h: .8, d: .2, delim: {rep: 119}, tclass: 'delimx'}, + {c: 'ï', h: .8, d: .2, delim: {rep: 62}, tclass: 'delimx'}, + {c: '|', h: .8, d: 0, delim: {top: 120, bot: 121, rep: 63}, tclass: 'normal'}, + // 40 - 4F + {c: 'è', h: .8, d: .2, delim: {top: 56, bot: 59, rep: 62}, tclass: 'delimx'}, + {c: 'ø', h: .8, d: .2, delim: {top: 57, bot: 58, rep: 62}, tclass: 'delimx'}, + {c: 'ç', h: .8, d: .2, delim: {rep: 66}, tclass: 'delimx'}, + {c: '÷', h: .8, d: .2, delim: {rep: 67}, tclass: 'delimx'}, + {c: '〈', h: 0.04, d: 1.76, n: 28, tclass: 'delim2b'}, + {c: '〉', h: 0.04, d: 1.76, n: 29, tclass: 'delim2b'}, + {c: '⊔', h: 0, d: 1, n: 71, tclass: 'bigop1'}, + {c: '⊔', h: 0.1, d: 1.5, tclass: 'bigop2'}, + {c: '∮', h: 0, d: 1.11, ic: 0.095, n: 73, tclass: 'bigop1c'}, + {c: '∮', h: 0, d: 2.22, ic: 0.222, tclass: 'bigop2c'}, + {c: '⊙', h: 0, d: 1, n: 75, tclass: 'bigop1'}, + {c: '⊙', h: 0.1, d: 1.5, tclass: 'bigop2'}, + {c: '⊕', h: 0, d: 1, n: 77, tclass: 'bigop1'}, + {c: '⊕', h: 0.1, d: 1.5, tclass: 'bigop2'}, + {c: '⊗', h: 0, d: 1, n: 79, tclass: 'bigop1'}, + {c: '⊗', h: 0.1, d: 1.5, tclass: 'bigop2'}, + // 50 - 5F + {c: '∑', h: 0, d: 1, n: 88, tclass: 'bigop1a'}, + {c: '∏', h: 0, d: 1, n: 89, tclass: 'bigop1a'}, + {c: '∫', h: 0, d: 1.11, ic: 0.095, n: 90, tclass: 'bigop1c'}, + {c: '∪', h: 0, d: 1, n: 91, tclass: 'bigop1b'}, + {c: '∩', h: 0, d: 1, n: 92, tclass: 'bigop1b'}, + {c: '⊎', h: 0, d: 1, n: 93, tclass: 'bigop1b'}, + {c: '⋀', h: 0, d: 1, n: 94, tclass: 'bigop1'}, + {c: '⋁', h: 0, d: 1, n: 95, tclass: 'bigop1'}, + {c: '∑', h: 0.1, d: 1.6, tclass: 'bigop2a'}, + {c: '∏', h: 0.1, d: 1.5, tclass: 'bigop2a'}, + {c: '∫', h: 0, d: 2.22, ic: 0.222, tclass: 'bigop2c'}, + {c: '∪', h: 0.1, d: 1.5, tclass: 'bigop2b'}, + {c: '∩', h: 0.1, d: 1.5, tclass: 'bigop2b'}, + {c: '⊎', h: 0.1, d: 1.5, tclass: 'bigop2b'}, + {c: '⋀', h: 0.1, d: 1.5, tclass: 'bigop2'}, + {c: '⋁', h: 0.1, d: 1.5, tclass: 'bigop2'}, + // 60 - 6F + {c: '∐', h: 0, d: 1, n: 97, tclass: 'bigop1a'}, + {c: '∐', h: 0.1, d: 1.5, tclass: 'bigop2a'}, + {c: '︿', h: 0.722, w: .65, n: 99, tclass: 'wide1'}, + {c: '︿', h: 0.85, w: 1.1, n: 100, tclass: 'wide2'}, + {c: '︿', h: 0.99, w: 1.65, tclass: 'wide3'}, + {c: '~', h: 0.722, w: .5, n: 102, tclass: 'wide1a'}, + {c: '~', h: 0.8, w: .8, n: 103, tclass: 'wide2a'}, + {c: '~', h: 0.99, w: 1.3, tclass: 'wide3a'}, + {c: '[', h: 0.04, d: 1.76, n: 20, tclass: 'delim2'}, + {c: ']', h: 0.04, d: 1.76, n: 21, tclass: 'delim2'}, + {c: '⌈', h: 0.04, d: 1.76, n: 22, tclass: 'delim2a'}, + {c: '⌉', h: 0.04, d: 1.76, n: 23, tclass: 'delim2a'}, + {c: '⌊', h: 0.04, d: 1.76, n: 24, tclass: 'delim2a'}, + {c: '⌋', h: 0.04, d: 1.76, n: 25, tclass: 'delim2a'}, + {c: '{', h: 0.04, d: 1.76, n: 26, tclass: 'delim2'}, + {c: '}', h: 0.04, d: 1.76, n: 27, tclass: 'delim2'}, + // 70 - 7F + {c: '', h: 0.04, d: 1.16, n: 113, tclass: 'root'}, + {c: '', h: 0.04, d: 1.76, n: 114, tclass: 'root'}, + {c: '', h: 0.06, d: 2.36, n: 115, tclass: 'root'}, + {c: '', h: 0.08, d: 2.96, n: 116, tclass: 'root'}, + {c: '', h: 0.1, d: 3.75, n: 117, tclass: 'root'}, + {c: '', h: .12, d: 4.5, n: 118, tclass: 'root'}, + {c: '', h: .14, d: 5.7, tclass: 'root'}, + {c: '||', h:.8, d:0, delim: {top: 126, bot: 127, rep: 119}, tclass: 'normal'}, + {c: '↑', h:.7, d:0, delim: {top: 120, rep: 63}, tclass: 'arrow1a'}, + {c: '↓', h:.65, d:0, delim: {bot: 121, rep: 63}, tclass: 'arrow1a'}, + {c: '', h: 0.05, tclass: 'symbol'}, + {c: '', h: 0.05, tclass: 'symbol'}, + {c: '', h: 0.05, tclass: 'symbol'}, + {c: '', h: 0.05, tclass: 'symbol'}, + {c: '⇑', h: .7, d:0, delim: {top: 126, rep: 119}, tclass: 'arrow1a'}, + {c: '⇓', h: .7, d:0, delim: {bot: 127, rep: 119}, tclass: 'arrow1a'} + ], + + cmti10: [ + // 00 - 0F + {c: 'Γ', ic: 0.133, tclass: 'igreek'}, + {c: 'Δ', tclass: 'igreek'}, + {c: 'Θ', ic: 0.094, tclass: 'igreek'}, + {c: 'Λ', tclass: 'igreek'}, + {c: 'Ξ', ic: 0.153, tclass: 'igreek'}, + {c: 'Π', ic: 0.164, tclass: 'igreek'}, + {c: 'Σ', ic: 0.12, tclass: 'igreek'}, + {c: 'Υ', ic: 0.111, tclass: 'igreek'}, + {c: 'Φ', ic: 0.0599, tclass: 'igreek'}, + {c: 'Ψ', ic: 0.111, tclass: 'igreek'}, + {c: 'Ω', ic: 0.103, tclass: 'igreek'}, + {c: 'ff', ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 14, '108': 15}, tclass: 'italic'}, + {c: 'fi', ic: 0.103, tclass: 'italic'}, + {c: 'fl', ic: 0.103, tclass: 'italic'}, + {c: 'ffi', ic: 0.103, tclass: 'italic'}, + {c: 'ffl', ic: 0.103, tclass: 'italic'}, + // 10 - 1F + {c: 'ı', a:0, ic: 0.0767, tclass: 'italic'}, + {c: 'j', d:.2, ic: 0.0374, tclass: 'italic'}, + {c: 'ˋ', tclass: 'iaccent'}, + {c: 'ˊ', ic: 0.0969, tclass: 'iaccent'}, + {c: 'ˇ', ic: 0.083, tclass: 'iaccent'}, + {c: '˘', ic: 0.108, tclass: 'iaccent'}, + {c: 'ˉ', ic: 0.103, tclass: 'iaccent'}, + {c: '˚', tclass: 'iaccent'}, + {c: '?', d: 0.17, w: 0.46, tclass: 'italic'}, + {c: 'ß', ic: 0.105, tclass: 'italic'}, + {c: 'æ', a:0, ic: 0.0751, tclass: 'italic'}, + {c: 'œ', a:0, ic: 0.0751, tclass: 'italic'}, + {c: 'ø', ic: 0.0919, tclass: 'italic'}, + {c: 'Æ', ic: 0.12, tclass: 'italic'}, + {c: 'Œ', ic: 0.12, tclass: 'italic'}, + {c: 'Ø', ic: 0.094, tclass: 'italic'}, + // 20 - 2F + {c: '?', krn: {'108': -0.256, '76': -0.321}, tclass: 'italic'}, + {c: '!', ic: 0.124, lig: {'96': 60}, tclass: 'italic'}, + {c: '”', ic: 0.0696, tclass: 'italic'}, + {c: '#', ic: 0.0662, tclass: 'italic'}, + {c: '$', tclass: 'italic'}, + {c: '%', ic: 0.136, tclass: 'italic'}, + {c: '&', ic: 0.0969, tclass: 'italic'}, + {c: '’', ic: 0.124, krn: {'63': 0.102, '33': 0.102}, lig: {'39': 34}, tclass: 'italic'}, + {c: '(', d:.2, ic: 0.162, tclass: 'italic'}, + {c: ')', d:.2, ic: 0.0369, tclass: 'italic'}, + {c: '*', ic: 0.149, tclass: 'italic'}, + {c: '+', a:.1, ic: 0.0369, tclass: 'italic'}, + {c: ',', a:-.3, d:.2, w: 0.278, tclass: 'italic'}, + {c: '-', a:0, ic: 0.0283, lig: {'45': 123}, tclass: 'italic'}, + {c: '.', a:-.25, tclass: 'italic'}, + {c: '/', ic: 0.162, tclass: 'italic'}, + // 30 - 3F + {c: '0', ic: 0.136, tclass: 'italic'}, + {c: '1', ic: 0.136, tclass: 'italic'}, + {c: '2', ic: 0.136, tclass: 'italic'}, + {c: '3', ic: 0.136, tclass: 'italic'}, + {c: '4', ic: 0.136, tclass: 'italic'}, + {c: '5', ic: 0.136, tclass: 'italic'}, + {c: '6', ic: 0.136, tclass: 'italic'}, + {c: '7', ic: 0.136, tclass: 'italic'}, + {c: '8', ic: 0.136, tclass: 'italic'}, + {c: '9', ic: 0.136, tclass: 'italic'}, + {c: ':', ic: 0.0582, tclass: 'italic'}, + {c: ';', ic: 0.0582, tclass: 'italic'}, + {c: '¡', ic: 0.0756, tclass: 'italic'}, + {c: '=', a:0, d:-.1, ic: 0.0662, tclass: 'italic'}, + {c: '¿', tclass: 'italic'}, + {c: '?', ic: 0.122, lig: {'96': 62}, tclass: 'italic'}, + // 40 - 4F + {c: '@', ic: 0.096, tclass: 'italic'}, + {c: 'A', krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'B', ic: 0.103, tclass: 'italic'}, + {c: 'C', ic: 0.145, tclass: 'italic'}, + {c: 'D', ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}, tclass: 'italic'}, + {c: 'E', ic: 0.12, tclass: 'italic'}, + {c: 'F', ic: 0.133, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'}, + {c: 'G', ic: 0.0872, tclass: 'italic'}, + {c: 'H', ic: 0.164, tclass: 'italic'}, + {c: 'I', ic: 0.158, tclass: 'italic'}, + {c: 'J', ic: 0.14, tclass: 'italic'}, + {c: 'K', ic: 0.145, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'}, + {c: 'L', krn: {'84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'M', ic: 0.164, tclass: 'italic'}, + {c: 'N', ic: 0.164, tclass: 'italic'}, + {c: 'O', ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}, tclass: 'italic'}, + // 50 - 5F + {c: 'P', ic: 0.103, krn: {'65': -0.0767}, tclass: 'italic'}, + {c: 'Q', d:.2, ic: 0.094, tclass: 'italic'}, + {c: 'R', ic: 0.0387, krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'S', ic: 0.12, tclass: 'italic'}, + {c: 'T', ic: 0.133, krn: {'121': -0.0767, '101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}, tclass: 'italic'}, + {c: 'U', ic: 0.164, tclass: 'italic'}, + {c: 'V', ic: 0.184, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'}, + {c: 'W', ic: 0.184, krn: {'65': -0.0767}, tclass: 'italic'}, + {c: 'X', ic: 0.158, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'}, + {c: 'Y', ic: 0.194, krn: {'101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}, tclass: 'italic'}, + {c: 'Z', ic: 0.145, tclass: 'italic'}, + {c: '[', d:.1, ic: 0.188, tclass: 'italic'}, + {c: '“', ic: 0.169, tclass: 'italic'}, + {c: ']', d:.1, ic: 0.105, tclass: 'italic'}, + {c: 'ˆ', ic: 0.0665, tclass: 'iaccent'}, + {c: '˙', ic: 0.118, tclass: 'iaccent'}, + // 60 - 6F + {c: '‘', ic: 0.124, lig: {'96': 92}, tclass: 'italic'}, + {c: 'a', a:0, ic: 0.0767, tclass: 'italic'}, + {c: 'b', ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'c', a:0, ic: 0.0565, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'd', ic: 0.103, krn: {'108': 0.0511}, tclass: 'italic'}, + {c: 'e', a:0, ic: 0.0751, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'f', ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 12, '102': 11, '108': 13}, tclass: 'italic'}, + {c: 'g', a:0, d:.2, ic: 0.0885, tclass: 'italic'}, + {c: 'h', ic: 0.0767, tclass: 'italic'}, + {c: 'i', ic: 0.102, tclass: 'italic'}, + {c: 'j', d:.2, ic: 0.145, tclass: 'italic'}, + {c: 'k', ic: 0.108, tclass: 'italic'}, + {c: 'l', ic: 0.103, krn: {'108': 0.0511}, tclass: 'italic'}, + {c: 'm', a:0, ic: 0.0767, tclass: 'italic'}, + {c: 'n', a:0, ic: 0.0767, krn: {'39': -0.102}, tclass: 'italic'}, + {c: 'o', a:0, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + // 70 - 7F + {c: 'p', a:0, d:.2, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'q', a:0, d:.2, ic: 0.0885, tclass: 'italic'}, + {c: 'r', a:0, ic: 0.108, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 's', a:0, ic: 0.0821, tclass: 'italic'}, + {c: 't', ic: 0.0949, tclass: 'italic'}, + {c: 'u', a:0, ic: 0.0767, tclass: 'italic'}, + {c: 'v', a:0, ic: 0.108, tclass: 'italic'}, + {c: 'w', a:0, ic: 0.108, krn: {'108': 0.0511}, tclass: 'italic'}, + {c: 'x', a:0, ic: 0.12, tclass: 'italic'}, + {c: 'y', a:0, d:.2, ic: 0.0885, tclass: 'italic'}, + {c: 'z', a:0, ic: 0.123, tclass: 'italic'}, + {c: '–', a:.1, ic: 0.0921, lig: {'45': 124}, tclass: 'italic'}, + {c: '—', a:.1, ic: 0.0921, tclass: 'italic'}, + {c: '˝', ic: 0.122, tclass: 'iaccent'}, + {c: '˜', ic: 0.116, tclass: 'iaccent'}, + {c: '¨', tclass: 'iaccent'} + ], + + cmbx10: [ + // 00 - 0F + {c: 'Γ', tclass: 'bgreek'}, + {c: 'Δ', tclass: 'bgreek'}, + {c: 'Θ', tclass: 'bgreek'}, + {c: 'Λ', tclass: 'bgreek'}, + {c: 'Ξ', tclass: 'bgreek'}, + {c: 'Π', tclass: 'bgreek'}, + {c: 'Σ', tclass: 'bgreek'}, + {c: 'Υ', tclass: 'bgreek'}, + {c: 'Φ', tclass: 'bgreek'}, + {c: 'Ψ', tclass: 'bgreek'}, + {c: 'Ω', tclass: 'bgreek'}, + {c: 'ff', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 14, '108': 15}, tclass: 'bold'}, + {c: 'fi', tclass: 'bold'}, + {c: 'fl', tclass: 'bold'}, + {c: 'ffi', tclass: 'bold'}, + {c: 'ffl', tclass: 'bold'}, + // 10 - 1F + {c: 'ı', a:0, tclass: 'bold'}, + {c: 'j', d:.2, tclass: 'bold'}, + {c: 'ˋ', tclass: 'baccent'}, + {c: 'ˊ', tclass: 'baccent'}, + {c: 'ˇ', tclass: 'baccent'}, + {c: '˘', tclass: 'baccent'}, + {c: 'ˉ', tclass: 'baccent'}, + {c: '˚', tclass: 'baccent'}, + {c: '?', tclass: 'bold'}, + {c: 'ß', tclass: 'bold'}, + {c: 'æ', a:0, tclass: 'bold'}, + {c: 'œ', a:0, tclass: 'bold'}, + {c: 'ø', tclass: 'bold'}, + {c: 'Æ', tclass: 'bold'}, + {c: 'Œ', tclass: 'bold'}, + {c: 'Ø', tclass: 'bold'}, + // 20 - 2F + {c: '?', krn: {'108': -0.278, '76': -0.319}, tclass: 'bold'}, + {c: '!', lig: {'96': 60}, tclass: 'bold'}, + {c: '”', tclass: 'bold'}, + {c: '#', tclass: 'bold'}, + {c: '$', tclass: 'bold'}, + {c: '%', tclass: 'bold'}, + {c: '&', tclass: 'bold'}, + {c: '’', krn: {'63': 0.111, '33': 0.111}, lig: {'39': 34}, tclass: 'bold'}, + {c: '(', d:.2, tclass: 'bold'}, + {c: ')', d:.2, tclass: 'bold'}, + {c: '*', tclass: 'bold'}, + {c: '+', a:.1, tclass: 'bold'}, + {c: ',', a:-.3, d:.2, w: 0.278, tclass: 'bold'}, + {c: '-', a:0, lig: {'45': 123}, tclass: 'bold'}, + {c: '.', a:-.25, tclass: 'bold'}, + {c: '/', tclass: 'bold'}, + // 30 - 3F + {c: '0', tclass: 'bold'}, + {c: '1', tclass: 'bold'}, + {c: '2', tclass: 'bold'}, + {c: '3', tclass: 'bold'}, + {c: '4', tclass: 'bold'}, + {c: '5', tclass: 'bold'}, + {c: '6', tclass: 'bold'}, + {c: '7', tclass: 'bold'}, + {c: '8', tclass: 'bold'}, + {c: '9', tclass: 'bold'}, + {c: ':', tclass: 'bold'}, + {c: ';', tclass: 'bold'}, + {c: '¡', tclass: 'bold'}, + {c: '=', a:0, d:-.1, tclass: 'bold'}, + {c: '¿', tclass: 'bold'}, + {c: '?', lig: {'96': 62}, tclass: 'bold'}, + // 40 - 4F + {c: '@', tclass: 'bold'}, + {c: 'A', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'bold'}, + {c: 'B', tclass: 'bold'}, + {c: 'C', tclass: 'bold'}, + {c: 'D', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'bold'}, + {c: 'E', tclass: 'bold'}, + {c: 'F', krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'}, + {c: 'G', tclass: 'bold'}, + {c: 'H', tclass: 'bold'}, + {c: 'I', krn: {'73': 0.0278}, tclass: 'bold'}, + {c: 'J', tclass: 'bold'}, + {c: 'K', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'}, + {c: 'L', krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'bold'}, + {c: 'M', tclass: 'bold'}, + {c: 'N', tclass: 'bold'}, + {c: 'O', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'bold'}, + // 50 - 5F + {c: 'P', krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'bold'}, + {c: 'Q', d:.2, tclass: 'bold'}, + {c: 'R', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'bold'}, + {c: 'S', tclass: 'bold'}, + {c: 'T', krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'bold'}, + {c: 'U', tclass: 'bold'}, + {c: 'V', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'}, + {c: 'W', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'}, + {c: 'X', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'}, + {c: 'Y', ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'bold'}, + {c: 'Z', tclass: 'bold'}, + {c: '[', d:.1, tclass: 'bold'}, + {c: '“', tclass: 'bold'}, + {c: ']', d:.1, tclass: 'bold'}, + {c: 'ˆ', tclass: 'baccent'}, + {c: '˙', tclass: 'baccent'}, + // 60 - 6F + {c: '‘', lig: {'96': 92}, tclass: 'bold'}, + {c: 'a', a:0, krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'b', krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'c', a:0, krn: {'104': -0.0278, '107': -0.0278}, tclass: 'bold'}, + {c: 'd', tclass: 'bold'}, + {c: 'e', a:0, tclass: 'bold'}, + {c: 'f', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}, tclass: 'bold'}, + {c: 'g', a:0, d:.2, ic: 0.0139, krn: {'106': 0.0278}, tclass: 'bold'}, + {c: 'h', krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'i', tclass: 'bold'}, + {c: 'j', d:.2, tclass: 'bold'}, + {c: 'k', krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'bold'}, + {c: 'l', tclass: 'bold'}, + {c: 'm', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'n', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'o', a:0, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'}, + // 70 - 7F + {c: 'p', a:0, d:.2, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'q', a:0, d:.2, tclass: 'bold'}, + {c: 'r', a:0, tclass: 'bold'}, + {c: 's', a:0, tclass: 'bold'}, + {c: 't', krn: {'121': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'u', a:0, krn: {'119': -0.0278}, tclass: 'bold'}, + {c: 'v', a:0, ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'bold'}, + {c: 'w', a:0, ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'bold'}, + {c: 'x', a:0, tclass: 'bold'}, + {c: 'y', a:0, d:.2, ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'bold'}, + {c: 'z', a:0, tclass: 'bold'}, + {c: '–', a:.1, ic: 0.0278, lig: {'45': 124}, tclass: 'bold'}, + {c: '—', a:.1, ic: 0.0278, tclass: 'bold'}, + {c: '˝', tclass: 'baccent'}, + {c: '˜', tclass: 'baccent'}, + {c: '¨', tclass: 'baccent'} + ] +}); + + +jsMath.Setup.Styles({ + '.typeset .cmr10': "font-family: serif", + '.typeset .italic': "font-style: italic", + '.typeset .bold': "font-weight: bold", + '.typeset .lucida': "font-family: 'lucida sans unicode'", + '.typeset .arial': "font-family: 'Arial unicode MS'", + '.typeset .cal': "font-family: 'Script MT', 'Script MT Bold', cursive", + '.typeset .arrows': "font-family: 'Arial unicode MS'", + '.typeset .arrow1': "font-family: 'Arial unicode MS'", + '.typeset .arrow1a': "font-family: 'Arial unicode MS'; position:relative; top:.05em;left:-.15em; margin-right:-.15em", + '.typeset .arrow2': "font-family: 'Arial unicode MS'; position:relative; top:-.1em;", + '.typeset .arrow3': "font-family: 'Arial unicode MS'; margin:.1em", + '.typeset .symbol': "font-family: 'Arial unicode MS'", + '.typeset .symbol2': "font-family: 'Arial unicode MS'", + '.typeset .delim1': "font-family: 'Times New Roman'; font-size: 133%; position:relative; top:.7em", + '.typeset .delim1a': "font-family: 'Lucida sans unicode'; font-size: 133%; position:relative; top:.8em", + '.typeset .delim1b': "font-family: 'Arial unicode MS'; font-size: 133%; position:relative; top:.8em", + '.typeset .delim2': "font-family: 'Times New Roman'; font-size: 180%; position:relative; top:.75em", + '.typeset .delim2a': "font-family: 'Lucida sans unicode'; font-size: 180%; position:relative; top:.8em", + '.typeset .delim2b': "font-family: 'Arial unicode MS'; font-size: 180%; position:relative; top:.8em", + '.typeset .delim3': "font-family: 'Times New Roman'; font-size: 250%; position:relative; top:.725em", + '.typeset .delim3a': "font-family: 'Lucida sans unicode'; font-size: 250%; position:relative; top:.775em", + '.typeset .delim3b': "font-family: 'Arial unicode MS'; font-size: 250%; position:relative; top:.8em", + '.typeset .delim4': "font-family: 'Times New Roman'; font-size: 325%; position:relative; top:.7em", + '.typeset .delim4a': "font-family: 'Lucida sans unicode'; font-size: 325%; position:relative; top:.775em", + '.typeset .delim4b': "font-family: 'Arial unicode MS'; font-size: 325%; position:relative; top:.8em", + '.typeset .delimx': "font-family: Symbol; position:relative; top:.2em", + '.typeset .greek': "font-family: 'Times New Roman'", + '.typeset .igreek': "font-family: 'Times New Roman'; font-style:italic", + '.typeset .bgreek': "font-family: 'Times New Roman'; font-weight:bold", + '.typeset .bigop1': "font-family: 'Arial unicode MS'; font-size: 130%; position: relative; top: .7em; margin:-.05em", + '.typeset .bigop1a': "font-family: 'Arial unicode MS'; font-size: 110%; position: relative; top: .85em;", + '.typeset .bigop1b': "font-family: 'Arial unicode MS'; font-size: 180%; position: relative; top: .6em", + '.typeset .bigop1c': "font-family: 'Arial unicode MS'; font-size: 85%; position: relative; top: 1em", + '.typeset .bigop2': "font-family: 'Arial unicode MS'; font-size: 230%; position: relative; top: .6em; margin:-.05em", + '.typeset .bigop2a': "font-family: 'Arial unicode MS'; font-size: 185%; position: relative; top: .75em", + '.typeset .bigop2b': "font-family: 'Arial unicode MS'; font-size: 275%; position: relative; top: .55em", + '.typeset .bigop2c': "font-family: 'Arial unicode MS'; font-size: 185%; position: relative; top: 1em; margin-right:-.1em", + '.typeset .wide1': "font-size: 67%; position: relative; top:-.5em;", + '.typeset .wide2': "font-size: 110%; position: relative; top:-.2em;", + '.typeset .wide3': "font-size: 175%;", + '.typeset .wide1a': "font-family: 'Times New Roman'; font-size: 75%; position: relative; top:-.5em", + '.typeset .wide2a': "font-family: 'Times New Roman'; font-size: 133%; position: relative; top:-.2em", + '.typeset .wide3a': "font-family: 'Times New Roman'; font-size: 200%; position: relative; top:-.1em", + '.typeset .root': "font-family: 'Arial unicode MS'; margin-right:-.075em", + '.typeset .accent': "font-family: 'Arial unicode MS'; position:relative; top:.05em; left:.15em", + '.typeset .iaccent': "font-family: 'Arial unicode MS'; position:relative; top:.05em; left:.15em; font-style:italic", + '.typeset .baccent': "font-family: 'Arial unicode MS'; position:relative; top:.05em; left:.15em; font-weight:bold" +}); + +// +// adjust for Mozilla +// +if (jsMath.browser == 'Mozilla') { + jsMath.Update.TeXfonts({ + cmex10: { + '48': {c: ''}, + '49': {c: ''}, + '50': {c: ''}, + '51': {c: ''}, + '52': {c: ''}, + '53': {c: ''}, + '54': {c: ''}, + '55': {c: ''}, + '56': {c: ''}, + '57': {c: ''}, + '58': {c: ''}, + '59': {c: ''}, + '60': {c: ''}, + '61': {c: ''}, + '62': {c: ''}, + '64': {c: ''}, + '65': {c: ''}, + '66': {c: ''}, + '67': {c: ''} + } + }); + jsMath.Setup.Styles({ + '.typeset .accent': 'font-family: Arial unicode MS; position:relative; top:.05em; left:.05em' + }); +} + +// +// adjust for MSIE +// +if (jsMath.browser == "MSIE") { + jsMath.Browser.msieFontBug = 1; + jsMath.Update.TeXfonts({ + cmex10: { + '63': {c: '|'}, + '119': {c: '||'} + } + }); +} + +/* + * No access to TeX "not" character, so fake this + * Also ajust the bowtie spacing + */ +jsMath.Macro('not','\\mathrel{\\rlap{\\kern 3mu/}}'); +jsMath.Macro('bowtie','\\mathrel\\triangleright\\kern-6mu\\mathrel\\triangleleft'); + +jsMath.Box.defaultH = 0.8; diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/jsMath-fallback-symbols.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/jsMath-fallback-symbols.js new file mode 100644 index 0000000..05e56e6 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/jsMath-fallback-symbols.js @@ -0,0 +1,415 @@ +/* + * jsMath-fallback-symbols.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file makes changes needed to use image fonts for symbols + * but standard native fonts for letters and numbers. + * + * --------------------------------------------------------------------- + * + * Copyright 2004-2006 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +jsMath.Add(jsMath.Img,{ + UpdateTeXFonts: function (change) { + for (var font in change) { + for (var code in change[font]) { + jsMath.TeX[font][code] = change[font][code]; + jsMath.TeX[font][code].tclass = 'i' + font; + } + } + } +}); + + +jsMath.Img.UpdateTeXFonts({ + cmr10: { + '33': {c: '!', lig: {'96': 60}}, + '35': {c: '#'}, + '36': {c: '$'}, + '37': {c: '%'}, + '38': {c: '&'}, + '40': {c: '(', d:.2}, + '41': {c: ')', d:.2}, + '42': {c: '*', d:-.3}, + '43': {c: '+', a:.1}, + '44': {c: ',', a:-.3}, + '45': {c: '-', a:0, lig: {'45': 123}}, + '46': {c: '.', a:-.25}, + '47': {c: '/'}, + '48': {c: '0'}, + '49': {c: '1'}, + '50': {c: '2'}, + '51': {c: '3'}, + '52': {c: '4'}, + '53': {c: '5'}, + '54': {c: '6'}, + '55': {c: '7'}, + '56': {c: '8'}, + '57': {c: '9'}, + '58': {c: ':'}, + '59': {c: ';'}, + '61': {c: '=', a:0, d:-.1}, + '63': {c: '?', lig: {'96': 62}}, + '64': {c: '@'}, + '65': {c: 'A', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}}, + '66': {c: 'B'}, + '67': {c: 'C'}, + '68': {c: 'D', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}}, + '69': {c: 'E'}, + '70': {c: 'F', krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}, + '71': {c: 'G'}, + '72': {c: 'H'}, + '73': {c: 'I', krn: {'73': 0.0278}}, + '74': {c: 'J'}, + '75': {c: 'K', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}, + '76': {c: 'L', krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}}, + '77': {c: 'M'}, + '78': {c: 'N'}, + '79': {c: 'O', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}}, + '80': {c: 'P', krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}}, + '81': {c: 'Q', d: 1}, + '82': {c: 'R', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}}, + '83': {c: 'S'}, + '84': {c: 'T', krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}}, + '85': {c: 'U'}, + '86': {c: 'V', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}, + '87': {c: 'W', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}, + '88': {c: 'X', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}, + '89': {c: 'Y', ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}}, + '90': {c: 'Z'}, + '91': {c: '[', d:.1}, + '93': {c: ']', d:.1}, + '97': {c: 'a', a:0, krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}, + '98': {c: 'b', krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}, + '99': {c: 'c', a:0, krn: {'104': -0.0278, '107': -0.0278}}, + '100': {c: 'd'}, + '101': {c: 'e', a:0}, + '102': {c: 'f', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}}, + '103': {c: 'g', a:0, d:.2, ic: 0.0139, krn: {'106': 0.0278}}, + '104': {c: 'h', krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}}, + '105': {c: 'i'}, + '106': {c: 'j', d:1}, + '107': {c: 'k', krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}}, + '108': {c: 'l'}, + '109': {c: 'm', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}}, + '110': {c: 'n', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}}, + '111': {c: 'o', a:0, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}, + '112': {c: 'p', a:0, d:.2, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}, + '113': {c: 'q', a:0, d:1}, + '114': {c: 'r', a:0}, + '115': {c: 's', a:0}, + '116': {c: 't', krn: {'121': -0.0278, '119': -0.0278}}, + '117': {c: 'u', a:0, krn: {'119': -0.0278}}, + '118': {c: 'v', a:0, ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}}, + '119': {c: 'w', a:0, ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}}, + '120': {c: 'x', a:0}, + '121': {c: 'y', a:0, d:.2, ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}}, + '122': {c: 'z', a:0} + }, + cmmi10: { + '65': {c: 'A', krn: {'127': 0.139}}, + '66': {c: 'B', ic: 0.0502, krn: {'127': 0.0833}}, + '67': {c: 'C', ic: 0.0715, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}, + '68': {c: 'D', ic: 0.0278, krn: {'127': 0.0556}}, + '69': {c: 'E', ic: 0.0576, krn: {'127': 0.0833}}, + '70': {c: 'F', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}}, + '71': {c: 'G', krn: {'127': 0.0833}}, + '72': {c: 'H', ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}}, + '73': {c: 'I', ic: 0.0785, krn: {'127': 0.111}}, + '74': {c: 'J', ic: 0.0962, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.167}}, + '75': {c: 'K', ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}}, + '76': {c: 'L', krn: {'127': 0.0278}}, + '77': {c: 'M', ic: 0.109, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}}, + '78': {c: 'N', ic: 0.109, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}, + '79': {c: 'O', ic: 0.0278, krn: {'127': 0.0833}}, + '80': {c: 'P', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}}, + '81': {c: 'Q', d:.2, krn: {'127': 0.0833}}, + '82': {c: 'R', ic: 0.00773, krn: {'127': 0.0833}}, + '83': {c: 'S', ic: 0.0576, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}}, + '84': {c: 'T', ic: 0.139, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}, + '85': {c: 'U', ic: 0.109, krn: {'59': -0.111, '58': -0.111, '61': -0.0556, '127': 0.0278}}, + '86': {c: 'V', ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}}, + '87': {c: 'W', ic: 0.139, krn: {'59': -0.167, '58': -0.167, '61': -0.111}}, + '88': {c: 'X', ic: 0.0785, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}, + '89': {c: 'Y', ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}}, + '90': {c: 'Z', ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}}, + '97': {c: 'a', a:0}, + '98': {c: 'b'}, + '99': {c: 'c', a:0, krn: {'127': 0.0556}}, + '100': {c: 'd', krn: {'89': 0.0556, '90': -0.0556, '106': -0.111, '102': -0.167, '127': 0.167}}, + '101': {c: 'e', a:0, krn: {'127': 0.0556}}, + '102': {c: 'f', d:.2, ic: 0.108, krn: {'59': -0.0556, '58': -0.0556, '127': 0.167}}, + '103': {c: 'g', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0278}}, + '104': {c: 'h', krn: {'127': -0.0278}}, + '105': {c: 'i'}, + '106': {c: 'j', d:.2, ic: 0.0572, krn: {'59': -0.0556, '58': -0.0556}}, + '107': {c: 'k', ic: 0.0315}, + '108': {c: 'l', ic: 0.0197, krn: {'127': 0.0833}}, + '109': {c: 'm', a:0}, + '110': {c: 'n', a:0}, + '111': {c: 'o', a:0, krn: {'127': 0.0556}}, + '112': {c: 'p', a:0, d:.2, krn: {'127': 0.0833}}, + '113': {c: 'q', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0833}}, + '114': {c: 'r', a:0, ic: 0.0278, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}}, + '115': {c: 's', a:0, krn: {'127': 0.0556}}, + '116': {c: 't', krn: {'127': 0.0833}}, + '117': {c: 'u', a:0, krn: {'127': 0.0278}}, + '118': {c: 'v', a:0, ic: 0.0359, krn: {'127': 0.0278}}, + '119': {c: 'w', a:0, ic: 0.0269, krn: {'127': 0.0833}}, + '120': {c: 'x', a:0, krn: {'127': 0.0278}}, + '121': {c: 'y', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0556}}, + '122': {c: 'z', a:0, ic: 0.044, krn: {'127': 0.0556}} + }, + cmsy10: { + '0': {c:'−', a:.1} + }, + cmti10: { + '33': {c: '!', lig: {'96': 60}}, + '35': {c: '#', ic: 0.0662}, + '37': {c: '%', ic: 0.136}, + '38': {c: '&', ic: 0.0969}, + '40': {c: '(', d:.2, ic: 0.162}, + '41': {c: ')', d:.2, ic: 0.0369}, + '42': {c: '*', ic: 0.149}, + '43': {c: '+', a:.1, ic: 0.0369}, + '44': {c: ',', a:-.3, d:.2, w: 0.278}, + '45': {c: '-', a:0, ic: 0.0283, lig: {'45': 123}}, + '46': {c: '.', a:-.25}, + '47': {c: '/', ic: 0.162}, + '48': {c: '0', ic: 0.136}, + '49': {c: '1', ic: 0.136}, + '50': {c: '2', ic: 0.136}, + '51': {c: '3', ic: 0.136}, + '52': {c: '4', ic: 0.136}, + '53': {c: '5', ic: 0.136}, + '54': {c: '6', ic: 0.136}, + '55': {c: '7', ic: 0.136}, + '56': {c: '8', ic: 0.136}, + '57': {c: '9', ic: 0.136}, + '58': {c: ':', ic: 0.0582}, + '59': {c: ';', ic: 0.0582}, + '61': {c: '=', a:0, d:-.1, ic: 0.0662}, + '63': {c: '?', ic: 0.122, lig: {'96': 62}}, + '64': {c: '@', ic: 0.096}, + '65': {c: 'A', krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}, + '66': {c: 'B', ic: 0.103}, + '67': {c: 'C', ic: 0.145}, + '68': {c: 'D', ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}}, + '69': {c: 'E', ic: 0.12}, + '70': {c: 'F', ic: 0.133, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}, + '71': {c: 'G', ic: 0.0872}, + '72': {c: 'H', ic: 0.164}, + '73': {c: 'I', ic: 0.158}, + '74': {c: 'J', ic: 0.14}, + '75': {c: 'K', ic: 0.145, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}, + '76': {c: 'L', krn: {'84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}, + '77': {c: 'M', ic: 0.164}, + '78': {c: 'N', ic: 0.164}, + '79': {c: 'O', ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}}, + '80': {c: 'P', ic: 0.103, krn: {'65': -0.0767}}, + '81': {c: 'Q', d:.2, ic: 0.094}, + '82': {c: 'R', ic: 0.0387, krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}, + '83': {c: 'S', ic: 0.12}, + '84': {c: 'T', ic: 0.133, krn: {'121': -0.0767, '101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}}, + '85': {c: 'U', ic: 0.164}, + '86': {c: 'V', ic: 0.184, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}, + '87': {c: 'W', ic: 0.184, krn: {'65': -0.0767}}, + '88': {c: 'X', ic: 0.158, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}, + '89': {c: 'Y', ic: 0.194, krn: {'101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}}, + '90': {c: 'Z', ic: 0.145}, + '91': {c: '[', d:.1, ic: 0.188}, + '93': {c: ']', d:.1, ic: 0.105}, + '97': {c: 'a', a:0, ic: 0.0767}, + '98': {c: 'b', ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}, + '99': {c: 'c', a:0, ic: 0.0565, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}, + '100': {c: 'd', ic: 0.103, krn: {'108': 0.0511}}, + '101': {c: 'e', a:0, ic: 0.0751, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}, + '102': {c: 'f', ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 12, '102': 11, '108': 13}}, + '103': {c: 'g', a:0, d:.2, ic: 0.0885}, + '104': {c: 'h', ic: 0.0767}, + '105': {c: 'i', ic: 0.102}, + '106': {c: 'j', d:.2, ic: 0.145}, + '107': {c: 'k', ic: 0.108}, + '108': {c: 'l', ic: 0.103, krn: {'108': 0.0511}}, + '109': {c: 'm', a:0, ic: 0.0767}, + '110': {c: 'n', a:0, ic: 0.0767, krn: {'39': -0.102}}, + '111': {c: 'o', a:0, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}, + '112': {c: 'p', a:0, d:.2, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}, + '113': {c: 'q', a:0, d:.2, ic: 0.0885}, + '114': {c: 'r', a:0, ic: 0.108, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}, + '115': {c: 's', a:0, ic: 0.0821}, + '116': {c: 't', ic: 0.0949}, + '117': {c: 'u', a:0, ic: 0.0767}, + '118': {c: 'v', a:0, ic: 0.108}, + '119': {c: 'w', a:0, ic: 0.108, krn: {'108': 0.0511}}, + '120': {c: 'x', a:0, ic: 0.12}, + '121': {c: 'y', a:0, d:.2, ic: 0.0885}, + '122': {c: 'z', a:0, ic: 0.123} + }, + cmbx10: { + '33': {c: '!', lig: {'96': 60}}, + '35': {c: '#'}, + '36': {c: '$'}, + '37': {c: '%'}, + '38': {c: '&'}, + '40': {c: '(', d:.2}, + '41': {c: ')', d:.2}, + '42': {c: '*'}, + '43': {c: '+', a:.1}, + '44': {c: ',', a:-.3, d:.2, w: 0.278}, + '45': {c: '-', a:0, lig: {'45': 123}}, + '46': {c: '.', a:-.25}, + '47': {c: '/'}, + '48': {c: '0'}, + '49': {c: '1'}, + '50': {c: '2'}, + '51': {c: '3'}, + '52': {c: '4'}, + '53': {c: '5'}, + '54': {c: '6'}, + '55': {c: '7'}, + '56': {c: '8'}, + '57': {c: '9'}, + '58': {c: ':'}, + '59': {c: ';'}, + '61': {c: '=', a:0, d:-.1}, + '63': {c: '?', lig: {'96': 62}}, + '64': {c: '@'}, + '65': {c: 'A', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}}, + '66': {c: 'B'}, + '67': {c: 'C'}, + '68': {c: 'D', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}}, + '69': {c: 'E'}, + '70': {c: 'F', krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}, + '71': {c: 'G'}, + '72': {c: 'H'}, + '73': {c: 'I', krn: {'73': 0.0278}}, + '74': {c: 'J'}, + '75': {c: 'K', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}, + '76': {c: 'L', krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}}, + '77': {c: 'M'}, + '78': {c: 'N'}, + '79': {c: 'O', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}}, + '80': {c: 'P', krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}}, + '81': {c: 'Q', d: 1}, + '82': {c: 'R', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}}, + '83': {c: 'S'}, + '84': {c: 'T', krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}}, + '85': {c: 'U'}, + '86': {c: 'V', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}, + '87': {c: 'W', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}, + '88': {c: 'X', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}, + '89': {c: 'Y', ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}}, + '90': {c: 'Z'}, + '91': {c: '[', d:.1}, + '93': {c: ']', d:.1}, + '97': {c: 'a', a:0, krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}, + '98': {c: 'b', krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}, + '99': {c: 'c', a:0, krn: {'104': -0.0278, '107': -0.0278}}, + '100': {c: 'd'}, + '101': {c: 'e', a:0}, + '102': {c: 'f', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}}, + '103': {c: 'g', a:0, d:.2, ic: 0.0139, krn: {'106': 0.0278}}, + '104': {c: 'h', krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}}, + '105': {c: 'i'}, + '106': {c: 'j', d:1}, + '107': {c: 'k', krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}}, + '108': {c: 'l'}, + '109': {c: 'm', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}}, + '110': {c: 'n', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}}, + '111': {c: 'o', a:0, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}, + '112': {c: 'p', a:0, d:.2, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}, + '113': {c: 'q', a:0, d:1}, + '114': {c: 'r', a:0}, + '115': {c: 's', a:0}, + '116': {c: 't', krn: {'121': -0.0278, '119': -0.0278}}, + '117': {c: 'u', a:0, krn: {'119': -0.0278}}, + '118': {c: 'v', a:0, ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}}, + '119': {c: 'w', a:0, ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}}, + '120': {c: 'x', a:0}, + '121': {c: 'y', a:0, d:.2, ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}}, + '122': {c: 'z', a:0} + } +}); + + +if (jsMath.browser == 'MSIE' && jsMath.platform == 'mac') { + jsMath.Setup.Styles({ + '.typeset .math': 'font-style: normal', + '.typeset .typeset': 'font-style: normal', + '.typeset .icmr10': 'font-family: Times', + '.typeset .icmmi10': 'font-family: Times; font-style: italic', + '.typeset .icmbx10': 'font-family: Times; font-weight: bold', + '.typeset .icmti10': 'font-family: Times; font-style: italic' + }); +} else { + jsMath.Setup.Styles({ + '.typeset .math': 'font-style: normal', + '.typeset .typeset': 'font-style: normal', + '.typeset .icmr10': 'font-family: serif', + '.typeset .icmmi10': 'font-family: serif; font-style: italic', + '.typeset .icmbx10': 'font-family: serif; font-weight: bold', + '.typeset .icmti10': 'font-family: serif; font-style: italic' + }); +} + + +jsMath.Add(jsMath.Img,{ + symbols: [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 34, 39, + 60, 62, + + 92, 94, 95, + 96, + 123,124,125,126,127 + ] +}); + +/* + * for now, use images for everything + */ +jsMath.Img.SetFont({ + cmr10: jsMath.Img.symbols, + cmmi10: [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, + 91, 92, 93, 94, 95, + 96, + 123,124,125,126,127 + ], + cmsy10: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119, 120,121,122,123,124,125,126,127 + ], + cmex10: ['all'], + cmti10: jsMath.Img.symbols.concat(36), + cmbx10: jsMath.Img.symbols +}); + +jsMath.Img.LoadFont('cm-fonts'); + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/jsMath-fallback-unix.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/jsMath-fallback-unix.js new file mode 100644 index 0000000..63e7856 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/jsMath-fallback-unix.js @@ -0,0 +1,935 @@ +/* + * jsMath-fallback-mac.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file makes changes needed for when the TeX fonts are not available + * with a browser on the Mac. + * + * --------------------------------------------------------------------- + * + * Copyright 2004-2006 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +/******************************************************************** + * + * Here we replace the TeX character mappings by equivalent unicode + * points when possible, and adjust the character dimensions + * based on the fonts we hope we get them from (the styles are set + * to try to use the best characters available in the standard + * fonts). + */ + +jsMath.Add(jsMath.TeX,{ + + cmr10: [ + // 00 - 0F + {c: 'Γ', tclass: 'greek'}, + {c: 'Δ', tclass: 'greek'}, + {c: 'Θ', tclass: 'greek'}, + {c: 'Λ', tclass: 'greek'}, + {c: 'Ξ', tclass: 'greek'}, + {c: 'Π', tclass: 'greek'}, + {c: 'Σ', tclass: 'greek'}, + {c: 'Υ', tclass: 'greek'}, + {c: 'Φ', tclass: 'greek'}, + {c: 'Ψ', tclass: 'greek'}, + {c: 'Ω', tclass: 'greek'}, + {c: 'ff', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 14, '108': 15}, tclass: 'normal'}, + {c: 'fi', tclass: 'normal'}, + {c: 'fl', tclass: 'normal'}, + {c: 'ffi', tclass: 'normal'}, + {c: 'ffl', tclass: 'normal'}, + // 10 - 1F + {c: 'ı', a:0, tclass: 'normal'}, + {c: 'j', d:.2, tclass: 'normal'}, + {c: '`', tclass: 'accent'}, + {c: '´', tclass: 'accent'}, + {c: 'ˇ', tclass: 'accent'}, + {c: '˘', tclass: 'accent'}, + {c: 'ˉ', tclass: 'accent'}, + {c: '˚', tclass: 'accent'}, + {c: '̧', tclass: 'normal'}, + {c: 'ß', tclass: 'normal'}, + {c: 'æ', a:0, tclass: 'normal'}, + {c: 'œ', a:0, tclass: 'normal'}, + {c: 'ø', tclass: 'normal'}, + {c: 'Æ', tclass: 'normal'}, + {c: 'Œ', tclass: 'normal'}, + {c: 'Ø', tclass: 'normal'}, + // 20 - 2F + {c: '?', krn: {'108': -0.278, '76': -0.319}, tclass: 'normal'}, + {c: '!', lig: {'96': 60}, tclass: 'normal'}, + {c: '”', tclass: 'normal'}, + {c: '#', tclass: 'normal'}, + {c: '$', tclass: 'normal'}, + {c: '%', tclass: 'normal'}, + {c: '&', tclass: 'normal'}, + {c: '’', krn: {'63': 0.111, '33': 0.111}, lig: {'39': 34}, tclass: 'normal'}, + {c: '(', d:.2, tclass: 'normal'}, + {c: ')', d:.2, tclass: 'normal'}, + {c: '*', tclass: 'normal'}, + {c: '+', a:.1, tclass: 'normal'}, + {c: ',', a:-.3, d:.2, w: 0.278, tclass: 'normal'}, + {c: '-', a:0, lig: {'45': 123}, tclass: 'normal'}, + {c: '.', a:-.25, tclass: 'normal'}, + {c: '/', tclass: 'normal'}, + // 30 - 3F + {c: '0', tclass: 'normal'}, + {c: '1', tclass: 'normal'}, + {c: '2', tclass: 'normal'}, + {c: '3', tclass: 'normal'}, + {c: '4', tclass: 'normal'}, + {c: '5', tclass: 'normal'}, + {c: '6', tclass: 'normal'}, + {c: '7', tclass: 'normal'}, + {c: '8', tclass: 'normal'}, + {c: '9', tclass: 'normal'}, + {c: ':', tclass: 'normal'}, + {c: ';', tclass: 'normal'}, + {c: '¡', tclass: 'normal'}, + {c: '=', a:0, d:-.1, tclass: 'normal'}, + {c: '¿', tclass: 'normal'}, + {c: '?', lig: {'96': 62}, tclass: 'normal'}, + // 40 - 4F + {c: '@', tclass: 'normal'}, + {c: 'A', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'normal'}, + {c: 'B', tclass: 'normal'}, + {c: 'C', tclass: 'normal'}, + {c: 'D', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'normal'}, + {c: 'E', tclass: 'normal'}, + {c: 'F', krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'}, + {c: 'G', tclass: 'normal'}, + {c: 'H', tclass: 'normal'}, + {c: 'I', krn: {'73': 0.0278}, tclass: 'normal'}, + {c: 'J', tclass: 'normal'}, + {c: 'K', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'}, + {c: 'L', krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'normal'}, + {c: 'M', tclass: 'normal'}, + {c: 'N', tclass: 'normal'}, + {c: 'O', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'normal'}, + // 50 - 5F + {c: 'P', krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'normal'}, + {c: 'Q', d: 1, tclass: 'normal'}, + {c: 'R', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'normal'}, + {c: 'S', tclass: 'normal'}, + {c: 'T', krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'normal'}, + {c: 'U', tclass: 'normal'}, + {c: 'V', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'}, + {c: 'W', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'}, + {c: 'X', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'}, + {c: 'Y', ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'normal'}, + {c: 'Z', tclass: 'normal'}, + {c: '[', d:.1, tclass: 'normal'}, + {c: '“', tclass: 'normal'}, + {c: ']', d:.1, tclass: 'normal'}, + {c: 'ˆ', tclass: 'accent'}, + {c: '˙', tclass: 'accent'}, + // 60 - 6F + {c: '‘', lig: {'96': 92}, tclass: 'normal'}, + {c: 'a', a:0, krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'b', krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'c', a:0, krn: {'104': -0.0278, '107': -0.0278}, tclass: 'normal'}, + {c: 'd', tclass: 'normal'}, + {c: 'e', a:0, tclass: 'normal'}, + {c: 'f', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}, tclass: 'normal'}, + {c: 'g', a:0, d:.2, ic: 0.0139, krn: {'106': 0.0278}, tclass: 'normal'}, + {c: 'h', krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'i', tclass: 'normal'}, + {c: 'j', d:.2, tclass: 'normal'}, + {c: 'k', krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'normal'}, + {c: 'l', tclass: 'normal'}, + {c: 'm', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'n', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'o', a:0, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'}, + // 70 - 7F + {c: 'p', a:0, d:.2, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'q', a:0, d:.2, tclass: 'normal'}, + {c: 'r', a:0, tclass: 'normal'}, + {c: 's', a:0, tclass: 'normal'}, + {c: 't', krn: {'121': -0.0278, '119': -0.0278}, tclass: 'normal'}, + {c: 'u', a:0, krn: {'119': -0.0278}, tclass: 'normal'}, + {c: 'v', a:0, ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'normal'}, + {c: 'w', a:0, ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'normal'}, + {c: 'x', a:0, tclass: 'normal'}, + {c: 'y', a:0, d:.2, ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'normal'}, + {c: 'z', a:0, tclass: 'normal'}, + {c: '–', a:.1, ic: 0.0278, lig: {'45': 124}, tclass: 'normal'}, + {c: '—', a:.1, ic: 0.0278, tclass: 'normal'}, + {c: '˝', tclass: 'accent'}, + {c: '˜', tclass: 'accent'}, + {c: '¨', tclass: 'accent'} + ], + + cmmi10: [ + // 00 - 0F + {c: 'Γ', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}, tclass: 'igreek'}, + {c: 'Δ', krn: {'127': 0.167}, tclass: 'igreek'}, + {c: 'Θ', ic: 0.0278, krn: {'127': 0.0833}, tclass: 'igreek'}, + {c: 'Λ', krn: {'127': 0.167}, tclass: 'igreek'}, + {c: 'Ξ', ic: 0.0757, krn: {'127': 0.0833}, tclass: 'igreek'}, + {c: 'Π', ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'igreek'}, + {c: 'Σ', ic: 0.0576, krn: {'127': 0.0833}, tclass: 'igreek'}, + {c: 'Υ', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0556}, tclass: 'igreek'}, + {c: 'Φ', krn: {'127': 0.0833}, tclass: 'igreek'}, + {c: 'Ψ', ic: 0.11, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'igreek'}, + {c: 'Ω', ic: 0.0502, krn: {'127': 0.0833}, tclass: 'igreek'}, + {c: 'α', a:0, ic: 0.0037, krn: {'127': 0.0278}, tclass: 'greek'}, + {c: 'β', d:.2, ic: 0.0528, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'γ', a:0, d:.2, ic: 0.0556, tclass: 'greek'}, + {c: 'δ', ic: 0.0378, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'greek'}, + {c: 'ε', a:0, krn: {'127': 0.0556}, tclass: 'symbol'}, + // 10 - 1F + {c: 'ζ', d:.2, ic: 0.0738, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'η', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0556}, tclass: 'greek'}, + {c: 'θ', ic: 0.0278, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'ι', a:0, krn: {'127': 0.0556}, tclass: 'greek'}, + {c: 'κ', a:0, tclass: 'greek'}, + {c: 'λ', tclass: 'greek'}, + {c: 'μ', a:0, d:.2, krn: {'127': 0.0278}, tclass: 'greek'}, + {c: 'ν', a:0, ic: 0.0637, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}, tclass: 'greek'}, + {c: 'ξ', d:.2, ic: 0.046, krn: {'127': 0.111}, tclass: 'greek'}, + {c: 'π', a:0, ic: 0.0359, tclass: 'greek'}, + {c: 'ρ', a:0, d:.2, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'σ', a:0, ic: 0.0359, krn: {'59': -0.0556, '58': -0.0556}, tclass: 'greek'}, + {c: 'τ', a:0, ic: 0.113, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}, tclass: 'greek'}, + {c: 'υ', a:0, ic: 0.0359, krn: {'127': 0.0278}, tclass: 'greek'}, + {c: 'φ', a:.1, d:.2, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'χ', a:0, d:.2, krn: {'127': 0.0556}, tclass: 'greek'}, + // 20 - 2F + {c: 'ψ', a:.1, d:.2, ic: 0.0359, krn: {'127': 0.111}, tclass: 'greek'}, + {c: 'ω', a:0, ic: 0.0359, tclass: 'greek'}, + {c: 'ε', a:0, krn: {'127': 0.0833}, tclass: 'greek'}, + {c: 'ϑ', krn: {'127': 0.0833}, tclass: 'normal'}, + {c: 'ϖ', a:0, ic: 0.0278, tclass: 'normal'}, + {c: 'ϱ', a:0, d:.2, krn: {'127': 0.0833}, tclass: 'normal'}, + {c: 'ς', a:0, d:.2, ic: 0.0799, krn: {'127': 0.0833}, tclass: 'normal'}, + {c: 'ϕ', a:.1, d:.2, krn: {'127': 0.0833}, tclass: 'normal'}, + {c: '↼', a:0, d:-.2, tclass: 'harpoon'}, + {c: '↽', a:0, d:-.1, tclass: 'harpoon'}, + {c: '⇀', a:0, d:-.2, tclass: 'harpoon'}, + {c: '⇁', a:0, d:-.1, tclass: 'harpoon'}, + {c: '˓', a:.1, tclass: 'symbol'}, + {c: '˒', a:.1, tclass: 'symbol'}, + {c: '', tclass: 'symbol'}, + {c: '', tclass: 'symbol'}, + // 30 - 3F + {c: '0', tclass: 'normal'}, + {c: '1', tclass: 'normal'}, + {c: '2', tclass: 'normal'}, + {c: '3', tclass: 'normal'}, + {c: '4', tclass: 'normal'}, + {c: '5', tclass: 'normal'}, + {c: '6', tclass: 'normal'}, + {c: '7', tclass: 'normal'}, + {c: '8', tclass: 'normal'}, + {c: '9', tclass: 'normal'}, + {c: '.', a:-.3, tclass: 'normal'}, + {c: ',', a:-.3, d:.2, tclass: 'normal'}, + {c: '<', a:.1, tclass: 'normal'}, + {c: '/', krn: {'1': -0.0556, '65': -0.0556, '77': -0.0556, '78': -0.0556, '89': 0.0556, '90': -0.0556}, tclass: 'normal'}, + {c: '>', a:.1, tclass: 'normal'}, + {c: '', a:0, tclass: 'symbol'}, + // 40 - 4F + {c: '∂', ic: 0.0556, krn: {'127': 0.0833}, tclass: 'normal'}, + {c: 'A', krn: {'127': 0.139}, tclass: 'italic'}, + {c: 'B', ic: 0.0502, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'C', ic: 0.0715, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'D', ic: 0.0278, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 'E', ic: 0.0576, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'F', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}, tclass: 'italic'}, + {c: 'G', krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'H', ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'italic'}, + {c: 'I', ic: 0.0785, krn: {'127': 0.111}, tclass: 'italic'}, + {c: 'J', ic: 0.0962, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.167}, tclass: 'italic'}, + {c: 'K', ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'italic'}, + {c: 'L', krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'M', ic: 0.109, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'N', ic: 0.109, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'O', ic: 0.0278, krn: {'127': 0.0833}, tclass: 'italic'}, + // 50 - 5F + {c: 'P', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}, tclass: 'italic'}, + {c: 'Q', d:.2, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'R', ic: 0.00773, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'S', ic: 0.0576, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'T', ic: 0.139, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'U', ic: 0.109, krn: {'59': -0.111, '58': -0.111, '61': -0.0556, '127': 0.0278}, tclass: 'italic'}, + {c: 'V', ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}, tclass: 'italic'}, + {c: 'W', ic: 0.139, krn: {'59': -0.167, '58': -0.167, '61': -0.111}, tclass: 'italic'}, + {c: 'X', ic: 0.0785, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: 'Y', ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}, tclass: 'italic'}, + {c: 'Z', ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'}, + {c: '♭', tclass: 'symbol2'}, + {c: '♮', tclass: 'symbol2'}, + {c: '♯', tclass: 'symbol2'}, + {c: '⌣', a:0, d:-.1, tclass: 'normal'}, + {c: '⌢', a:0, d:-.1, tclass: 'normal'}, + // 60 - 6F + {c: 'ℓ', krn: {'127': 0.111}, tclass: 'symbol'}, + {c: 'a', a:0, tclass: 'italic'}, + {c: 'b', tclass: 'italic'}, + {c: 'c', a:0, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 'd', krn: {'89': 0.0556, '90': -0.0556, '106': -0.111, '102': -0.167, '127': 0.167}, tclass: 'italic'}, + {c: 'e', a:0, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 'f', d:.2, ic: 0.108, krn: {'59': -0.0556, '58': -0.0556, '127': 0.167}, tclass: 'italic'}, + {c: 'g', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'h', krn: {'127': -0.0278}, tclass: 'italic'}, + {c: 'i', tclass: 'italic'}, + {c: 'j', d:.2, ic: 0.0572, krn: {'59': -0.0556, '58': -0.0556}, tclass: 'italic'}, + {c: 'k', ic: 0.0315, tclass: 'italic'}, + {c: 'l', ic: 0.0197, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'm', a:0, tclass: 'italic'}, + {c: 'n', a:0, tclass: 'italic'}, + {c: 'o', a:0, krn: {'127': 0.0556}, tclass: 'italic'}, + // 70 - 7F + {c: 'p', a:0, d:.2, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'q', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'r', a:0, ic: 0.0278, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'italic'}, + {c: 's', a:0, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 't', krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'u', a:0, krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'v', a:0, ic: 0.0359, krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'w', a:0, ic: 0.0269, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: 'x', a:0, krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'y', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 'z', a:0, ic: 0.044, krn: {'127': 0.0556}, tclass: 'italic'}, + {c: 'ı', a:0, krn: {'127': 0.0278}, tclass: 'italic'}, + {c: 'j', d:.2, krn: {'127': 0.0833}, tclass: 'italic'}, + {c: '℘', a:0, d:.2, krn: {'127': 0.111}, tclass: 'normal'}, + {c: '', ic: 0.154, tclass: 'symbol'}, + {c: '̑', ic: 0.399, tclass: 'normal'} + ], + + cmsy10: [ + // 00 - 0F + {c: '−', a:.1, tclass: 'symbol'}, + {c: '·', a:0, d:-.2, tclass: 'symbol'}, + {c: '×', a:0, tclass: 'symbol'}, + {c: '*', a:0, tclass: 'symbol'}, + {c: '÷', a:0, tclass: 'symbol'}, + {c: '◊', tclass: 'symbol'}, + {c: '±', a:.1, tclass: 'symbol'}, + {c: '∓', tclass: 'symbol'}, + {c: '⊕', tclass: 'symbol'}, + {c: '⊖', tclass: 'symbol'}, + {c: '⊗', tclass: 'symbol'}, + {c: '⊘', tclass: 'symbol'}, + {c: '⊙', tclass: 'symbol'}, + {c: '◯', tclass: 'symbol'}, + {c: '°', a:0, d:-.1, tclass: 'symbol'}, + {c: '•', a:0, d:-.2, tclass: 'symbol'}, + // 10 - 1F + {c: '≍', a:.1, tclass: 'symbol'}, + {c: '≡', a:.1, tclass: 'symbol'}, + {c: '⊆', tclass: 'symbol'}, + {c: '⊇', tclass: 'symbol'}, + {c: '≤', tclass: 'symbol'}, + {c: '≥', tclass: 'symbol'}, + {c: '≼', tclass: 'symbol'}, + {c: '≽', tclass: 'symbol'}, + {c: '~', a:0, d: -.2, tclass: 'normal'}, + {c: '≈', a:.1, d:-.1, tclass: 'symbol'}, + {c: '⊂', tclass: 'symbol'}, + {c: '⊃', tclass: 'symbol'}, + {c: '≪', tclass: 'symbol'}, + {c: '≫', tclass: 'symbol'}, + {c: '≺', tclass: 'symbol'}, + {c: '≻', tclass: 'symbol'}, + // 20 - 2F + {c: '←', a:0, d:-.15, tclass: 'arrows'}, + {c: '→', a:0, d:-.15, tclass: 'arrows'}, + {c: '↑', h:1, tclass: 'arrows'}, + {c: '↓', h:1, tclass: 'arrows'}, + {c: '↔', a:0, tclass: 'arrows'}, + {c: '↗', h:1, tclass: 'arrows'}, + {c: '↘', h:1, tclass: 'arrows'}, + {c: '≃', a: .1, tclass: 'symbol'}, + {c: '⇐', a:.1, tclass: 'arrows'}, + {c: '⇒', a:.1, tclass: 'arrows'}, + {c: '⇑', h:.9, d:.1, tclass: 'arrows'}, + {c: '⇓', h:.9, d:.1, tclass: 'arrows'}, + {c: '⇔', a:.1, tclass: 'arrows'}, + {c: '↖', h:1, tclass: 'arrows'}, + {c: '↙', h:1, tclass: 'arrows'}, + {c: '∝', a:.1, tclass: 'symbol'}, + // 30 - 3F + {c: '', a: 0, tclass: 'symbol'}, + {c: '∞', a:.1, tclass: 'symbol'}, + {c: '∈', tclass: 'symbol'}, + {c: '∋', tclass: 'symbol'}, + {c: '△', tclass: 'symbol'}, + {c: '▽', tclass: 'symbol'}, + {c: '/', tclass: 'symbol'}, + {c: '|', a:0, tclass: 'normal'}, + {c: '∀', tclass: 'symbol'}, + {c: '∃', tclass: 'symbol'}, + {c: '¬', a:0, d:-.1, tclass: 'symbol1'}, + {c: '∅', tclass: 'symbol'}, + {c: 'ℜ', tclass: 'symbol'}, + {c: 'ℑ', tclass: 'symbol'}, + {c: '⊤', tclass: 'symbol'}, + {c: '⊥', tclass: 'symbol'}, + // 40 - 4F + {c: 'ℵ', tclass: 'symbol'}, + {c: 'A', krn: {'48': 0.194}, tclass: 'cal'}, + {c: 'B', ic: 0.0304, krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'C', ic: 0.0583, krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'D', ic: 0.0278, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'E', ic: 0.0894, krn: {'48': 0.111}, tclass: 'cal'}, + {c: 'F', ic: 0.0993, krn: {'48': 0.111}, tclass: 'cal'}, + {c: 'G', d:.2, ic: 0.0593, krn: {'48': 0.111}, tclass: 'cal'}, + {c: 'H', ic: 0.00965, krn: {'48': 0.111}, tclass: 'cal'}, + {c: 'I', ic: 0.0738, krn: {'48': 0.0278}, tclass: 'cal'}, + {c: 'J', d:.2, ic: 0.185, krn: {'48': 0.167}, tclass: 'cal'}, + {c: 'K', ic: 0.0144, krn: {'48': 0.0556}, tclass: 'cal'}, + {c: 'L', krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'M', krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'N', ic: 0.147, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'O', ic: 0.0278, krn: {'48': 0.111}, tclass: 'cal'}, + // 50 - 5F + {c: 'P', ic: 0.0822, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'Q', d:.2, krn: {'48': 0.111}, tclass: 'cal'}, + {c: 'R', krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'S', ic: 0.075, krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'T', ic: 0.254, krn: {'48': 0.0278}, tclass: 'cal'}, + {c: 'U', ic: 0.0993, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'V', ic: 0.0822, krn: {'48': 0.0278}, tclass: 'cal'}, + {c: 'W', ic: 0.0822, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'X', ic: 0.146, krn: {'48': 0.139}, tclass: 'cal'}, + {c: 'Y', ic: 0.0822, krn: {'48': 0.0833}, tclass: 'cal'}, + {c: 'Z', ic: 0.0794, krn: {'48': 0.139}, tclass: 'cal'}, + {c: '⋃', tclass: 'symbol'}, + {c: '⋂', tclass: 'symbol'}, + {c: '⊎', tclass: 'symbol'}, + {c: '⋀', tclass: 'symbol'}, + {c: '⋁', tclass: 'symbol'}, + // 60 - 6F + {c: '⊢', tclass: 'symbol'}, + {c: '⊣', tclass: 'symbol2'}, + {c: '', a:.3, d:.2, tclass: 'normal'}, + {c: '', a:.3, d:.2, tclass: 'normal'}, + {c: '', a:.3, d:.2, tclass: 'normal'}, + {c: '', a:.3, d:.2, tclass: 'normal'}, + {c: '{', d:.2, tclass: 'normal'}, + {c: '}', d:.2, tclass: 'normal'}, + {c: '〈', a:.3, d:.2, tclass: 'normal'}, + {c: '〉', a:.3, d:.2, tclass: 'normal'}, + {c: '|', d:.1, tclass: 'vertical'}, + {c: '||', d:0, tclass: 'vertical'}, + {c: '↕', h:1, d:.15, tclass: 'arrows'}, + {c: '⇕', a:.2, d:.1, tclass: 'arrows'}, + {c: '∖', a:.3, d:.1, tclass: 'normal'}, + {c: '≀', tclass: 'symbol'}, + // 70 - 7F + {c: '', h:.04, d:.9, tclass: 'normal'}, + {c: '∐', a:.4, tclass: 'symbol'}, + {c: '∇', tclass: 'symbol'}, + {c: '∫', h:1, d:.1, ic: 0.111, tclass: 'root'}, + {c: '⊔', tclass: 'symbol'}, + {c: '⊓', tclass: 'symbol'}, + {c: '⊑', tclass: 'symbol'}, + {c: '⊒', tclass: 'symbol'}, + {c: '§', d:.1, tclass: 'normal'}, + {c: '†', d:.1, tclass: 'normal'}, + {c: '‡', d:.1, tclass: 'normal'}, + {c: '¶', a:.3, d:.1, tclass: 'normal'}, + {c: '♣', tclass: 'symbol'}, + {c: '♦', tclass: 'symbol'}, + {c: '♥', tclass: 'symbol'}, + {c: '♠', tclass: 'symbol'} + ], + + cmex10: [ + // 00 - 0F + {c: '(', h: 0.04, d: 1.16, n: 16, tclass: 'delim1'}, + {c: ')', h: 0.04, d: 1.16, n: 17, tclass: 'delim1'}, + {c: '[', h: 0.04, d: 1.16, n: 104, tclass: 'delim1'}, + {c: ']', h: 0.04, d: 1.16, n: 105, tclass: 'delim1'}, + {c: '', h: 0.04, d: 1.16, n: 106, tclass: 'delim1'}, + {c: '', h: 0.04, d: 1.16, n: 107, tclass: 'delim1'}, + {c: '', h: 0.04, d: 1.16, n: 108, tclass: 'delim1'}, + {c: '', h: 0.04, d: 1.16, n: 109, tclass: 'delim1'}, + {c: '{', h: 0.04, d: 1.16, n: 110, tclass: 'delim1'}, + {c: '}', h: 0.04, d: 1.16, n: 111, tclass: 'delim1'}, + {c: '〈', h: 0.04, d: 1.16, n: 68, tclass: 'delim1c'}, + {c: '〉', h: 0.04, d: 1.16, n: 69, tclass: 'delim1c'}, + {c: '|', h:.7, d:0, delim: {rep: 12}, tclass: 'vertical'}, + {c: '||', h:.7, d:0, delim: {rep: 13}, tclass: 'vertical'}, + {c: '/', h: 0.04, d: 1.16, n: 46, tclass: 'delim1b'}, + {c: '∖', h: 0.04, d: 1.16, n: 47, tclass: 'delim1b'}, + // 10 - 1F + {c: '(', h: 0.04, d: 1.76, n: 18, tclass: 'delim2'}, + {c: ')', h: 0.04, d: 1.76, n: 19, tclass: 'delim2'}, + {c: '(', h: 0.04, d: 2.36, n: 32, tclass: 'delim3'}, + {c: ')', h: 0.04, d: 2.36, n: 33, tclass: 'delim3'}, + {c: '[', h: 0.04, d: 2.36, n: 34, tclass: 'delim3'}, + {c: ']', h: 0.04, d: 2.36, n: 35, tclass: 'delim3'}, + {c: '', h: 0.04, d: 2.36, n: 36, tclass: 'delim3'}, + {c: '', h: 0.04, d: 2.36, n: 37, tclass: 'delim3'}, + {c: '', h: 0.04, d: 2.36, n: 38, tclass: 'delim3'}, + {c: '', h: 0.04, d: 2.36, n: 39, tclass: 'delim3'}, + {c: '{', h: 0.04, d: 2.36, n: 40, tclass: 'delim3'}, + {c: '}', h: 0.04, d: 2.36, n: 41, tclass: 'delim3'}, + {c: '〈', h: 0.04, d: 2.36, n: 42, tclass: 'delim3c'}, + {c: '〉', h: 0.04, d: 2.36, n: 43, tclass: 'delim3c'}, + {c: '/', h: 0.04, d: 2.36, n: 44, tclass: 'delim3b'}, + {c: '∖', h: 0.04, d: 2.36, n: 45, tclass: 'delim3b'}, + // 20 - 2F + {c: '(', h: 0.04, d: 2.96, n: 48, tclass: 'delim4'}, + {c: ')', h: 0.04, d: 2.96, n: 49, tclass: 'delim4'}, + {c: '[', h: 0.04, d: 2.96, n: 50, tclass: 'delim4'}, + {c: ']', h: 0.04, d: 2.96, n: 51, tclass: 'delim4'}, + {c: '', h: 0.04, d: 2.96, n: 52, tclass: 'delim4'}, + {c: '', h: 0.04, d: 2.96, n: 53, tclass: 'delim4'}, + {c: '', h: 0.04, d: 2.96, n: 54, tclass: 'delim4'}, + {c: '', h: 0.04, d: 2.96, n: 55, tclass: 'delim4'}, + {c: '{', h: 0.04, d: 2.96, n: 56, tclass: 'delim4'}, + {c: '}', h: 0.04, d: 2.96, n: 57, tclass: 'delim4'}, + {c: '〈', h: 0.04, d: 2.96, tclass: 'delim4c'}, + {c: '〉', h: 0.04, d: 2.96, tclass: 'delim4c'}, + {c: '/', h: 0.04, d: 2.96, tclass: 'delim4b'}, + {c: '∖', h: 0.04, d: 2.96, tclass: 'delim4b'}, + {c: '/', h: 0.04, d: 1.76, n: 30, tclass: 'delim2b'}, + {c: '∖', h: 0.04, d: 1.76, n: 31, tclass: 'delim2b'}, + // 30 - 3F + {c: '', h: .8, d: .15, delim: {top: 48, bot: 64, rep: 66}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {top: 49, bot: 65, rep: 67}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {top: 50, bot: 52, rep: 54}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {top: 51, bot: 53, rep: 55}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {bot: 52, rep: 54}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {bot: 53, rep: 55}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {top: 50, rep: 54}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {top: 51, rep: 55}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {top: 56, mid: 60, bot: 58, rep: 62}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {top: 57, mid: 61, bot: 59, rep: 62}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {top: 56, bot: 58, rep: 62}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {top: 57, bot: 59, rep: 62}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {rep: 63}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {rep: 119}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {rep: 62}, tclass: 'delim'}, + {c: '|', h: .65, d: 0, delim: {top: 120, bot: 121, rep: 63}, tclass: 'vertical'}, + // 40 - 4F + {c: '', h: .8, d: .15, delim: {top: 56, bot: 59, rep: 62}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {top: 57, bot: 58, rep: 62}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {rep: 66}, tclass: 'delim'}, + {c: '', h: .8, d: .15, delim: {rep: 67}, tclass: 'delim'}, + {c: '〈', h: 0.04, d: 1.76, n: 28, tclass: 'delim2c'}, + {c: '〉', h: 0.04, d: 1.76, n: 29, tclass: 'delim2c'}, + {c: '⊔', h: 0, d: 1, n: 71, tclass: 'bigop1'}, + {c: '⊔', h: 0.1, d: 1.5, tclass: 'bigop2'}, + {c: '∮', h: 0, d: 1.11, ic: 0.095, n: 73, tclass: 'bigop1c'}, + {c: '∮', h: 0, d: 2.22, ic: 0.222, tclass: 'bigop2c'}, + {c: '⊙', h: 0, d: 1, n: 75, tclass: 'bigop1'}, + {c: '⊙', h: 0.1, d: 1.5, tclass: 'bigop2'}, + {c: '⊕', h: 0, d: 1, n: 77, tclass: 'bigop1'}, + {c: '⊕', h: 0.1, d: 1.5, tclass: 'bigop2'}, + {c: '⊗', h: 0, d: 1, n: 79, tclass: 'bigop1'}, + {c: '⊗', h: 0.1, d: 1.5, tclass: 'bigop2'}, + // 50 - 5F + {c: '∑', h: 0, d: 1, n: 88, tclass: 'bigop1a'}, + {c: '∏', h: 0, d: 1, n: 89, tclass: 'bigop1a'}, + {c: '∫', h: 0, d: 1.11, ic: 0.095, n: 90, tclass: 'bigop1c'}, + {c: '∪', h: 0, d: 1, n: 91, tclass: 'bigop1b'}, + {c: '∩', h: 0, d: 1, n: 92, tclass: 'bigop1b'}, + {c: '⊎', h: 0, d: 1, n: 93, tclass: 'bigop1b'}, + {c: '∧', h: 0, d: 1, n: 94, tclass: 'bigop1'}, + {c: '∨', h: 0, d: 1, n: 95, tclass: 'bigop1'}, + {c: '∑', h: 0.1, d: 1.6, tclass: 'bigop2a'}, + {c: '∏', h: 0.1, d: 1.5, tclass: 'bigop2a'}, + {c: '∫', h: 0, d: 2.22, ic: 0.222, tclass: 'bigop2c'}, + {c: '∪', h: 0.1, d: 1.5, tclass: 'bigop2b'}, + {c: '∩', h: 0.1, d: 1.5, tclass: 'bigop2b'}, + {c: '⊎', h: 0.1, d: 1.5, tclass: 'bigop2b'}, + {c: '∧', h: 0.1, d: 1.5, tclass: 'bigop2'}, + {c: '∨', h: 0.1, d: 1.5, tclass: 'bigop2'}, + // 60 - 6F + {c: '∐', h: 0, d: 1, n: 97, tclass: 'bigop1a'}, + {c: '∐', h: 0.1, d: 1.5, tclass: 'bigop2a'}, + {c: '︿', h: 0.722, w: .65, n: 99, tclass: 'wide1'}, + {c: '︿', h: 0.85, w: 1.1, n: 100, tclass: 'wide2'}, + {c: '︿', h: 0.99, w: 1.65, tclass: 'wide3'}, + {c: '⁓', h: 0.722, w: .75, n: 102, tclass: 'wide1a'}, + {c: '⁓', h: 0.8, w: 1.35, n: 103, tclass: 'wide2a'}, + {c: '⁓', h: 0.99, w: 2, tclass: 'wide3a'}, + {c: '[', h: 0.04, d: 1.76, n: 20, tclass: 'delim2'}, + {c: ']', h: 0.04, d: 1.76, n: 21, tclass: 'delim2'}, + {c: '', h: 0.04, d: 1.76, n: 22, tclass: 'delim2'}, + {c: '', h: 0.04, d: 1.76, n: 23, tclass: 'delim2'}, + {c: '', h: 0.04, d: 1.76, n: 24, tclass: 'delim2'}, + {c: '', h: 0.04, d: 1.76, n: 25, tclass: 'delim2'}, + {c: '{', h: 0.04, d: 1.76, n: 26, tclass: 'delim2'}, + {c: '}', h: 0.04, d: 1.76, n: 27, tclass: 'delim2'}, + // 70 - 7F + {c: '', h: 0.04, d: 1.16, n: 113, tclass: 'root'}, + {c: '', h: 0.04, d: 1.76, n: 114, tclass: 'root'}, + {c: '', h: 0.06, d: 2.36, n: 115, tclass: 'root'}, + {c: '', h: 0.08, d: 2.96, n: 116, tclass: 'root'}, + {c: '', h: 0.1, d: 3.75, n: 117, tclass: 'root'}, + {c: '', h: .12, d: 4.5, n: 118, tclass: 'root'}, + {c: '', h: .14, d: 5.7, tclass: 'root'}, + {c: '||', h:.65, d:0, delim: {top: 126, bot: 127, rep: 119}, tclass: 'vertical'}, + {c: '▵', h:.45, delim: {top: 120, rep: 63}, tclass: 'arrow1'}, + {c: '▿', h:.45, delim: {bot: 121, rep: 63}, tclass: 'arrow1'}, + {c: '', h:.1, tclass: 'symbol'}, + {c: '', h:.1, tclass: 'symbol'}, + {c: '', h:.1, tclass: 'symbol'}, + {c: '', h:.1, tclass: 'symbol'}, + {c: '▵', h:.5, delim: {top: 126, rep: 119}, tclass: 'arrow2'}, + {c: '▿', h:.5, delim: {bot: 127, rep: 119}, tclass: 'arrow2'} + ], + + cmti10: [ + // 00 - 0F + {c: 'Γ', ic: 0.133, tclass: 'igreek'}, + {c: 'Δ', tclass: 'igreek'}, + {c: 'Θ', ic: 0.094, tclass: 'igreek'}, + {c: 'Λ', tclass: 'igreek'}, + {c: 'Ξ', ic: 0.153, tclass: 'igreek'}, + {c: 'Π', ic: 0.164, tclass: 'igreek'}, + {c: 'Σ', ic: 0.12, tclass: 'igreek'}, + {c: 'Υ', ic: 0.111, tclass: 'igreek'}, + {c: 'Φ', ic: 0.0599, tclass: 'igreek'}, + {c: 'Ψ', ic: 0.111, tclass: 'igreek'}, + {c: 'Ω', ic: 0.103, tclass: 'igreek'}, + {c: 'ff', ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 14, '108': 15}, tclass: 'italic'}, + {c: 'fi', ic: 0.103, tclass: 'italic'}, + {c: 'fl', ic: 0.103, tclass: 'italic'}, + {c: 'ffi', ic: 0.103, tclass: 'italic'}, + {c: 'ffl', ic: 0.103, tclass: 'italic'}, + // 10 - 1F + {c: 'ı', a:0, ic: 0.0767, tclass: 'italic'}, + {c: 'j', d:.2, ic: 0.0374, tclass: 'italic'}, + {c: '`', tclass: 'iaccent'}, + {c: '´', ic: 0.0969, tclass: 'iaccent'}, + {c: 'ˇ', ic: 0.083, tclass: 'iaccent'}, + {c: '˘', ic: 0.108, tclass: 'iaccent'}, + {c: 'ˉ', ic: 0.103, tclass: 'iaccent'}, + {c: '˚', tclass: 'iaccent'}, + {c: '?', d: 0.17, w: 0.46, tclass: 'italic'}, + {c: 'ß', ic: 0.105, tclass: 'italic'}, + {c: 'æ', a:0, ic: 0.0751, tclass: 'italic'}, + {c: 'œ', a:0, ic: 0.0751, tclass: 'italic'}, + {c: 'ø', ic: 0.0919, tclass: 'italic'}, + {c: 'Æ', ic: 0.12, tclass: 'italic'}, + {c: 'Œ', ic: 0.12, tclass: 'italic'}, + {c: 'Ø', ic: 0.094, tclass: 'italic'}, + // 20 - 2F + {c: '?', krn: {'108': -0.256, '76': -0.321}, tclass: 'italic'}, + {c: '!', ic: 0.124, lig: {'96': 60}, tclass: 'italic'}, + {c: '”', ic: 0.0696, tclass: 'italic'}, + {c: '#', ic: 0.0662, tclass: 'italic'}, + {c: '$', tclass: 'italic'}, + {c: '%', ic: 0.136, tclass: 'italic'}, + {c: '&', ic: 0.0969, tclass: 'italic'}, + {c: '’', ic: 0.124, krn: {'63': 0.102, '33': 0.102}, lig: {'39': 34}, tclass: 'italic'}, + {c: '(', d:.2, ic: 0.162, tclass: 'italic'}, + {c: ')', d:.2, ic: 0.0369, tclass: 'italic'}, + {c: '*', ic: 0.149, tclass: 'italic'}, + {c: '+', a:.1, ic: 0.0369, tclass: 'italic'}, + {c: ',', a:-.3, d:.2, w: 0.278, tclass: 'italic'}, + {c: '-', a:0, ic: 0.0283, lig: {'45': 123}, tclass: 'italic'}, + {c: '.', a:-.25, tclass: 'italic'}, + {c: '/', ic: 0.162, tclass: 'italic'}, + // 30 - 3F + {c: '0', ic: 0.136, tclass: 'italic'}, + {c: '1', ic: 0.136, tclass: 'italic'}, + {c: '2', ic: 0.136, tclass: 'italic'}, + {c: '3', ic: 0.136, tclass: 'italic'}, + {c: '4', ic: 0.136, tclass: 'italic'}, + {c: '5', ic: 0.136, tclass: 'italic'}, + {c: '6', ic: 0.136, tclass: 'italic'}, + {c: '7', ic: 0.136, tclass: 'italic'}, + {c: '8', ic: 0.136, tclass: 'italic'}, + {c: '9', ic: 0.136, tclass: 'italic'}, + {c: ':', ic: 0.0582, tclass: 'italic'}, + {c: ';', ic: 0.0582, tclass: 'italic'}, + {c: '¡', ic: 0.0756, tclass: 'italic'}, + {c: '=', a:0, d:-.1, ic: 0.0662, tclass: 'italic'}, + {c: '¿', tclass: 'italic'}, + {c: '?', ic: 0.122, lig: {'96': 62}, tclass: 'italic'}, + // 40 - 4F + {c: '@', ic: 0.096, tclass: 'italic'}, + {c: 'A', krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'B', ic: 0.103, tclass: 'italic'}, + {c: 'C', ic: 0.145, tclass: 'italic'}, + {c: 'D', ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}, tclass: 'italic'}, + {c: 'E', ic: 0.12, tclass: 'italic'}, + {c: 'F', ic: 0.133, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'}, + {c: 'G', ic: 0.0872, tclass: 'italic'}, + {c: 'H', ic: 0.164, tclass: 'italic'}, + {c: 'I', ic: 0.158, tclass: 'italic'}, + {c: 'J', ic: 0.14, tclass: 'italic'}, + {c: 'K', ic: 0.145, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'}, + {c: 'L', krn: {'84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'M', ic: 0.164, tclass: 'italic'}, + {c: 'N', ic: 0.164, tclass: 'italic'}, + {c: 'O', ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}, tclass: 'italic'}, + // 50 - 5F + {c: 'P', ic: 0.103, krn: {'65': -0.0767}, tclass: 'italic'}, + {c: 'Q', d: 1, ic: 0.094, tclass: 'italic'}, + {c: 'R', ic: 0.0387, krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'S', ic: 0.12, tclass: 'italic'}, + {c: 'T', ic: 0.133, krn: {'121': -0.0767, '101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}, tclass: 'italic'}, + {c: 'U', ic: 0.164, tclass: 'italic'}, + {c: 'V', ic: 0.184, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'}, + {c: 'W', ic: 0.184, krn: {'65': -0.0767}, tclass: 'italic'}, + {c: 'X', ic: 0.158, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'}, + {c: 'Y', ic: 0.194, krn: {'101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}, tclass: 'italic'}, + {c: 'Z', ic: 0.145, tclass: 'italic'}, + {c: '[', d:.1, ic: 0.188, tclass: 'italic'}, + {c: '“', ic: 0.169, tclass: 'italic'}, + {c: ']', d:.1, ic: 0.105, tclass: 'italic'}, + {c: 'ˆ', ic: 0.0665, tclass: 'iaccent'}, + {c: '˙', ic: 0.118, tclass: 'iaccent'}, + // 60 - 6F + {c: '‘', ic: 0.124, lig: {'96': 92}, tclass: 'italic'}, + {c: 'a', a:0, ic: 0.0767, tclass: 'italic'}, + {c: 'b', ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'c', a:0, ic: 0.0565, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'd', ic: 0.103, krn: {'108': 0.0511}, tclass: 'italic'}, + {c: 'e', a:0, ic: 0.0751, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'f', ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 12, '102': 11, '108': 13}, tclass: 'italic'}, + {c: 'g', a:0, d:.2, ic: 0.0885, tclass: 'italic'}, + {c: 'h', ic: 0.0767, tclass: 'italic'}, + {c: 'i', ic: 0.102, tclass: 'italic'}, + {c: 'j', d:.2, ic: 0.145, tclass: 'italic'}, + {c: 'k', ic: 0.108, tclass: 'italic'}, + {c: 'l', ic: 0.103, krn: {'108': 0.0511}, tclass: 'italic'}, + {c: 'm', a:0, ic: 0.0767, tclass: 'italic'}, + {c: 'n', a:0, ic: 0.0767, krn: {'39': -0.102}, tclass: 'italic'}, + {c: 'o', a:0, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + // 70 - 7F + {c: 'p', a:0, d:.2, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 'q', a:0, d:.2, ic: 0.0885, tclass: 'italic'}, + {c: 'r', a:0, ic: 0.108, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'}, + {c: 's', a:0, ic: 0.0821, tclass: 'italic'}, + {c: 't', ic: 0.0949, tclass: 'italic'}, + {c: 'u', a:0, ic: 0.0767, tclass: 'italic'}, + {c: 'v', a:0, ic: 0.108, tclass: 'italic'}, + {c: 'w', a:0, ic: 0.108, krn: {'108': 0.0511}, tclass: 'italic'}, + {c: 'x', a:0, ic: 0.12, tclass: 'italic'}, + {c: 'y', a:0, d:.2, ic: 0.0885, tclass: 'italic'}, + {c: 'z', a:0, ic: 0.123, tclass: 'italic'}, + {c: '–', a:.1, ic: 0.0921, lig: {'45': 124}, tclass: 'italic'}, + {c: '—', a:.1, ic: 0.0921, tclass: 'italic'}, + {c: '˝', ic: 0.122, tclass: 'iaccent'}, + {c: '˜', ic: 0.116, tclass: 'iaccent'}, + {c: '¨', tclass: 'iaccent'} + ], + + cmbx10: [ + // 00 - 0F + {c: 'Γ', tclass: 'bgreek'}, + {c: 'Δ', tclass: 'bgreek'}, + {c: 'Θ', tclass: 'bgreek'}, + {c: 'Λ', tclass: 'bgreek'}, + {c: 'Ξ', tclass: 'bgreek'}, + {c: 'Π', tclass: 'bgreek'}, + {c: 'Σ', tclass: 'bgreek'}, + {c: 'Υ', tclass: 'bgreek'}, + {c: 'Φ', tclass: 'bgreek'}, + {c: 'Ψ', tclass: 'bgreek'}, + {c: 'Ω', tclass: 'bgreek'}, + {c: 'ff', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 14, '108': 15}, tclass: 'bold'}, + {c: 'fi', tclass: 'bold'}, + {c: 'fl', tclass: 'bold'}, + {c: 'ffi', tclass: 'bold'}, + {c: 'ffl', tclass: 'bold'}, + // 10 - 1F + {c: 'ı', a:0, tclass: 'bold'}, + {c: 'j', d:.2, tclass: 'bold'}, + {c: '`', tclass: 'baccent'}, + {c: '´', tclass: 'baccent'}, + {c: 'ˇ', tclass: 'baccent'}, + {c: '˘', tclass: 'baccent'}, + {c: 'ˉ', tclass: 'baccent'}, + {c: '˚', tclass: 'baccent'}, + {c: '?', tclass: 'bold'}, + {c: 'ß', tclass: 'bold'}, + {c: 'æ', a:0, tclass: 'bold'}, + {c: 'œ', a:0, tclass: 'bold'}, + {c: 'ø', tclass: 'bold'}, + {c: 'Æ', tclass: 'bold'}, + {c: 'Œ', tclass: 'bold'}, + {c: 'Ø', tclass: 'bold'}, + // 20 - 2F + {c: '?', krn: {'108': -0.278, '76': -0.319}, tclass: 'bold'}, + {c: '!', lig: {'96': 60}, tclass: 'bold'}, + {c: '”', tclass: 'bold'}, + {c: '#', tclass: 'bold'}, + {c: '$', tclass: 'bold'}, + {c: '%', tclass: 'bold'}, + {c: '&', tclass: 'bold'}, + {c: '’', krn: {'63': 0.111, '33': 0.111}, lig: {'39': 34}, tclass: 'bold'}, + {c: '(', d:.2, tclass: 'bold'}, + {c: ')', d:.2, tclass: 'bold'}, + {c: '*', tclass: 'bold'}, + {c: '+', a:.1, tclass: 'bold'}, + {c: ',', a:-.3, d:.2, w: 0.278, tclass: 'bold'}, + {c: '-', a:0, lig: {'45': 123}, tclass: 'bold'}, + {c: '.', a:-.25, tclass: 'bold'}, + {c: '/', tclass: 'bold'}, + // 30 - 3F + {c: '0', tclass: 'bold'}, + {c: '1', tclass: 'bold'}, + {c: '2', tclass: 'bold'}, + {c: '3', tclass: 'bold'}, + {c: '4', tclass: 'bold'}, + {c: '5', tclass: 'bold'}, + {c: '6', tclass: 'bold'}, + {c: '7', tclass: 'bold'}, + {c: '8', tclass: 'bold'}, + {c: '9', tclass: 'bold'}, + {c: ':', tclass: 'bold'}, + {c: ';', tclass: 'bold'}, + {c: '¡', tclass: 'bold'}, + {c: '=', a:0, d:-.1, tclass: 'bold'}, + {c: '¿', tclass: 'bold'}, + {c: '?', lig: {'96': 62}, tclass: 'bold'}, + // 40 - 4F + {c: '@', tclass: 'bold'}, + {c: 'A', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'bold'}, + {c: 'B', tclass: 'bold'}, + {c: 'C', tclass: 'bold'}, + {c: 'D', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'bold'}, + {c: 'E', tclass: 'bold'}, + {c: 'F', krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'}, + {c: 'G', tclass: 'bold'}, + {c: 'H', tclass: 'bold'}, + {c: 'I', krn: {'73': 0.0278}, tclass: 'bold'}, + {c: 'J', tclass: 'bold'}, + {c: 'K', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'}, + {c: 'L', krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'bold'}, + {c: 'M', tclass: 'bold'}, + {c: 'N', tclass: 'bold'}, + {c: 'O', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'bold'}, + // 50 - 5F + {c: 'P', krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'bold'}, + {c: 'Q', d: 1, tclass: 'bold'}, + {c: 'R', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'bold'}, + {c: 'S', tclass: 'bold'}, + {c: 'T', krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'bold'}, + {c: 'U', tclass: 'bold'}, + {c: 'V', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'}, + {c: 'W', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'}, + {c: 'X', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'}, + {c: 'Y', ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'bold'}, + {c: 'Z', tclass: 'bold'}, + {c: '[', d:.1, tclass: 'bold'}, + {c: '“', tclass: 'bold'}, + {c: ']', d:.1, tclass: 'bold'}, + {c: 'ˆ', tclass: 'baccent'}, + {c: '˙', tclass: 'baccent'}, + // 60 - 6F + {c: '‘', lig: {'96': 92}, tclass: 'bold'}, + {c: 'a', a:0, krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'b', krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'c', a:0, krn: {'104': -0.0278, '107': -0.0278}, tclass: 'bold'}, + {c: 'd', tclass: 'bold'}, + {c: 'e', a:0, tclass: 'bold'}, + {c: 'f', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}, tclass: 'bold'}, + {c: 'g', a:0, d:.2, ic: 0.0139, krn: {'106': 0.0278}, tclass: 'bold'}, + {c: 'h', krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'i', tclass: 'bold'}, + {c: 'j', d:.2, tclass: 'bold'}, + {c: 'k', krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'bold'}, + {c: 'l', tclass: 'bold'}, + {c: 'm', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'n', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'o', a:0, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'}, + // 70 - 7F + {c: 'p', a:0, d:.2, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'q', a:0, d:.2, tclass: 'bold'}, + {c: 'r', a:0, tclass: 'bold'}, + {c: 's', a:0, tclass: 'bold'}, + {c: 't', krn: {'121': -0.0278, '119': -0.0278}, tclass: 'bold'}, + {c: 'u', a:0, krn: {'119': -0.0278}, tclass: 'bold'}, + {c: 'v', a:0, ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'bold'}, + {c: 'w', a:0, ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'bold'}, + {c: 'x', a:0, tclass: 'bold'}, + {c: 'y', a:0, d:.2, ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'bold'}, + {c: 'z', a:0, tclass: 'bold'}, + {c: '–', a:.1, ic: 0.0278, lig: {'45': 124}, tclass: 'bold'}, + {c: '—', a:.1, ic: 0.0278, tclass: 'bold'}, + {c: '˝', tclass: 'baccent'}, + {c: '˜', tclass: 'baccent'}, + {c: '¨', tclass: 'baccent'} + ] +}); + +jsMath.Setup.Styles({ + '.typeset .math': 'font-style: normal', + '.typeset .italic': 'font-style: italic', + '.typeset .bold': 'font-weight: bold', + '.typeset .cmr10': 'font-family: serif', + '.typeset .cal': 'font-family: cursive', + '.typeset .arrows': '', + '.typeset .arrow1': '', + '.typeset .arrow2': '', + '.typeset .harpoon': 'font-size: 125%', + '.typeset .symbol': '', + '.typeset .symbol2': '', + '.typeset .delim1': 'font-size: 133%; position:relative; top:.75em', + '.typeset .delim1b': 'font-size: 133%; position:relative; top:.8em; margin: -.1em', + '.typeset .delim1c': 'font-size: 120%; position:relative; top:.8em;', + '.typeset .delim2': 'font-size: 180%; position:relative; top:.75em', + '.typeset .delim2b': 'font-size: 190%; position:relative; top:.8em; margin: -.1em', + '.typeset .delim2c': 'font-size: 167%; position:relative; top:.8em;', + '.typeset .delim3': 'font-size: 250%; position:relative; top:.725em', + '.typeset .delim3b': 'font-size: 250%; position:relative; top:.8em; margin: -.1em', + '.typeset .delim3c': 'font-size: 240%; position:relative; top:.775em;', + '.typeset .delim4': 'font-size: 325%; position:relative; top:.7em', + '.typeset .delim4b': 'font-size: 325%; position:relative; top:.8em; margin: -.1em', + '.typeset .delim4c': 'font-size: 300%; position:relative; top:.8em;', + '.typeset .delim': '', + '.typeset .vertical': '', + '.typeset .greek': '', + '.typeset .igreek': 'font-style: italic', + '.typeset .bgreek': 'font-weight: bold', + '.typeset .bigop1': 'font-size: 133%; position: relative; top: .85em; margin:-.05em', + '.typeset .bigop1a': 'font-size: 100%; position: relative; top: .775em;', + '.typeset .bigop1b': 'font-size: 160%; position: relative; top: .7em; margin:-.1em', + '.typeset .bigop1c': 'font-size: 125%; position: relative; top: .75em; margin:-.1em;', + '.typeset .bigop2': 'font-size: 200%; position: relative; top: .8em; margin:-.07em', + '.typeset .bigop2a': 'font-size: 175%; position: relative; top: .7em;', + '.typeset .bigop2b': 'font-size: 270%; position: relative; top: .62em; margin:-.1em', + '.typeset .bigop2c': 'font-size: 250%; position: relative; top: .7em; margin:-.17em;', + '.typeset .wide1': 'font-size: 67%; position: relative; top:-.8em', + '.typeset .wide2': 'font-size: 110%; position: relative; top:-.5em', + '.typeset .wide3': 'font-size: 175%; position: relative; top:-.32em', + '.typeset .wide1a': 'font-size: 75%; position: relative; top:-.5em', + '.typeset .wide2a': 'font-size: 133%; position: relative; top: -.15em', + '.typeset .wide3a': 'font-size: 200%; position: relative; top: -.05em', + '.typeset .root': '', + '.typeset .accent': 'position: relative; top: .02em', + '.typeset .iaccent': 'position: relative; top: .02em; font-style: italic', + '.typeset .baccent': 'position: relative; top: .02em; font-weight: bold' +}); + + +jsMath.Setup.Styles(); + +/* + * No access to TeX "not" character, so fake this + */ +jsMath.Macro('not','\\mathrel{\\rlap{\\kern 4mu/}}'); +jsMath.Macro('joinrel','\\mathrel{\\kern-2mu}'); + + +jsMath.Box.DelimExtend = jsMath.Box.DelimExtendRelative; + +jsMath.Box.defaultH = 0.8; diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/jsMath.js b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/jsMath.js new file mode 100644 index 0000000..566d0d9 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/jsMath/uncompressed/jsMath.js @@ -0,0 +1,6569 @@ +/***************************************************************************** + * + * jsMath: Mathematics on the Web + * + * This jsMath package makes it possible to display mathematics in HTML pages + * that are viewable by a wide range of browsers on both the Mac and the IBM PC, + * including browsers that don't process MathML. See + * + * http://www.math.union.edu/locate/jsMath + * + * for the latest version, and for documentation on how to use jsMath. + * + * Copyright 2004-2008 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *****************************************************************************/ + +/* + * Prevent running everything again if this file is loaded twice + */ +if (!window.jsMath || !window.jsMath.loaded) { + +var jsMath_old = window.jsMath; // save user customizations + +// +// debugging routine +// +/* + * function ShowObject (obj,spaces) { + * var s = ''; if (!spaces) {spaces = ""} + * for (var i in obj) { + * if (obj[i] != null) { + * if (typeof(obj[i]) == "object") { + * s += spaces + i + ": {\n" + * + ShowObject(obj[i],spaces + ' ') + * + spaces + "}\n"; + * } else if (typeof(obj[i]) != "function") { + * s += spaces + i + ': ' + obj[i] + "\n"; + * } + * } + * } + * return s; + * } + */ + +/***************************************************************************/ +// +// Check for DOM support +// +if (!document.getElementById || !document.childNodes || !document.createElement) { + alert('The mathematics on this page requires W3C DOM support in its JavaScript. ' + + 'Unfortunately, your browser doesn\'t seem to have this.'); +} else { + +/***************************************************************************/ + +window.jsMath = { + + version: "3.6c", // change this if you edit the file, but don't edit this file + + document: document, // the document loading jsMath + window: window, // the window of the of loading document + + platform: (navigator.platform.match(/Mac/) ? "mac" : + navigator.platform.match(/Win/) ? "pc" : "unix"), + + // Font sizes for \tiny, \small, etc. (must match styles below) + sizes: [50, 60, 70, 85, 100, 120, 144, 173, 207, 249], + + // + // The styles needed for the TeX fonts and other jsMath elements + // + styles: { + '.math': { // unprocessed mathematics + 'font-family': 'serif', + 'font-style': 'normal', + 'font-weight': 'normal' + }, + + '.typeset': { // final typeset mathematics + 'font-family': 'serif', + 'font-style': 'normal', + 'font-weight': 'normal', + 'line-height': 'normal', + 'text-indent': '0px', + 'white-space': 'normal' + }, + + '.typeset .normal': { // \hbox contents style + 'font-family': 'serif', + 'font-style': 'normal', + 'font-weight': 'normal' + }, + + 'div.typeset': { // display mathematics + 'text-align': 'center', + margin: '1em 0px' + }, + + 'span.typeset': { // in-line mathematics + 'text-align': 'left' + }, + + '.typeset span': { // prevent outside CSS from setting these + 'text-align': 'left', + border: '0px', + margin: '0px', + padding: '0px' + }, + + 'a .typeset img, .typeset a img': { // links in image mode + border: '0px', + 'border-bottom': '1px solid blue;' + }, + + // Font sizes + '.typeset .size0': {'font-size': '50%'}, // tiny (\scriptscriptsize) + '.typeset .size1': {'font-size': '60%'}, // (50% of \large for consistency) + '.typeset .size2': {'font-size': '70%'}, // scriptsize + '.typeset .size3': {'font-size': '85%'}, // small (70% of \large for consistency) + '.typeset .size4': {'font-size': '100%'}, // normalsize + '.typeset .size5': {'font-size': '120%'}, // large + '.typeset .size6': {'font-size': '144%'}, // Large + '.typeset .size7': {'font-size': '173%'}, // LARGE + '.typeset .size8': {'font-size': '207%'}, // huge + '.typeset .size9': {'font-size': '249%'}, // Huge + + // TeX fonts + '.typeset .cmr10': {'font-family': 'jsMath-cmr10, serif'}, + '.typeset .cmbx10': {'font-family': 'jsMath-cmbx10, jsMath-cmr10'}, + '.typeset .cmti10': {'font-family': 'jsMath-cmti10, jsMath-cmr10'}, + '.typeset .cmmi10': {'font-family': 'jsMath-cmmi10'}, + '.typeset .cmsy10': {'font-family': 'jsMath-cmsy10'}, + '.typeset .cmex10': {'font-family': 'jsMath-cmex10'}, + + '.typeset .textit': {'font-family': 'serif', 'font-style': 'italic'}, + '.typeset .textbf': {'font-family': 'serif', 'font-weight': 'bold'}, + + '.typeset .link': {'text-decoration': 'none'}, // links in mathematics + + '.typeset .error': { // in-line error messages + 'font-size': '90%', + 'font-style': 'italic', + 'background-color': '#FFFFCC', + padding: '1px', + border: '1px solid #CC0000' + }, + + '.typeset .blank': { // internal use + display: 'inline-block', + overflow: 'hidden', + border: '0px none', + width: '0px', + height: '0px' + }, + '.typeset .spacer': { // internal use + display: 'inline-block' + }, + + '#jsMath_hiddenSpan': { // used for measuring BBoxes + visibility: 'hidden', + position: 'absolute', + top: '0px', + left: '0px', + 'line-height': 'normal', + 'text-indent': '0px' + }, + + '#jsMath_message': { // percentage complete message + position: 'fixed', + bottom: '1px', + left: '2px', + 'background-color': '#E6E6E6', + border: 'solid 1px #959595', + margin: '0px', + padding: '1px 8px', + 'z-index': '102', + color: 'black', + 'font-size': 'small', + width: 'auto' + }, + + '#jsMath_panel': { // control panel + position: 'fixed', + bottom: '1.75em', + right: '1.5em', + padding: '.8em 1.6em', + 'background-color': '#DDDDDD', + border: 'outset 2px', + 'z-index': '103', + width: 'auto', + color: 'black', + 'font-size': '10pt', + 'font-style': 'normal' + }, + '#jsMath_panel .disabled': {color: '#888888'}, // disabled items in the panel + '#jsMath_panel .infoLink': {'font-size': '85%'}, // links to web pages + + // avoid CSS polution from outside the panel + '#jsMath_panel *': { + 'font-size': 'inherit', + 'font-style': 'inherit', + 'font-family': 'inherit', + 'line-height': 'normal' + }, + '#jsMath_panel div': {'background-color': 'inherit', color: 'inherit'}, + '#jsMath_panel span': {'background-color': 'inherit', color: 'inherit'}, + '#jsMath_panel td': { + border: '0px', padding: '0px', margin: '0px', + 'background-color': 'inherit', color: 'inherit' + }, + '#jsMath_panel tr': { + border: '0px', padding: '0px', margin: '0px', + 'background-color': 'inherit', color: 'inherit' + }, + '#jsMath_panel table': { + border: '0px', padding: '0px', margin: '0px', + 'background-color': 'inherit', color: 'inherit', + height: 'auto', width: 'auto' + }, + + '#jsMath_button': { // the jsMath floating button (to open control panel) + position: 'fixed', + bottom: '1px', + right: '2px', + 'background-color': 'white', + border: 'solid 1px #959595', + margin: '0px', + padding: '0px 3px 1px 3px', + 'z-index': '102', + color: 'black', + 'text-decoration': 'none', + 'font-size': 'x-small', + width: 'auto', + cursor: 'hand' + }, + '#jsMath_button *': { + padding: '0px', border: '0px', margin: '0px', 'line-height': 'normal', + 'font-size': 'inherit', 'font-style': 'inherit', 'font-family': 'inherit' + }, + + '#jsMath_global': {'font-style': 'italic'}, // 'global' in jsMath button + + '#jsMath_noFont .message': { // missing font message window + 'text-align': 'center', + padding: '.8em 1.6em', + border: '3px solid #DD0000', + 'background-color': '#FFF8F8', + color: '#AA0000', + 'font-size': 'small', + width: 'auto' + }, + '#jsMath_noFont .link': { + padding: '0px 5px 2px 5px', + border: '2px outset', + 'background-color': '#E8E8E8', + color: 'black', + 'font-size': '80%', + width: 'auto', + cursor: 'hand' + }, + + '#jsMath_PrintWarning .message': { // warning on print pages + 'text-align': 'center', + padding: '.8em 1.6em', + border: '3px solid #DD0000', + 'background-color': '#FFF8F8', + color: '#AA0000', + 'font-size': 'x-small', + width: 'auto' + }, + + '@media print': { + '#jsMath_button': {display: 'none'}, + '#jsMath_Warning': {display: 'none'} + }, + + '@media screen': { + '#jsMath_PrintWarning': {display:'none'} + } + + }, + + + /***************************************************************************/ + + /* + * Get a jsMath DOM element + */ + Element: function (name) {return jsMath.document.getElementById('jsMath_'+name)}, + + /* + * Get the width and height (in pixels) of an HTML string + */ + BBoxFor: function (s) { + this.hidden.innerHTML = + ''+s+''; + var bbox = {w: this.hidden.offsetWidth, h: this.hidden.offsetHeight}; + this.hidden.innerHTML = ''; + return bbox; + }, + + /* + * Get the width and height (in ems) of an HTML string. + * Check the cache first to see if we've already measured it. + */ + EmBoxFor: function (s) { + var cache = jsMath.Global.cache.R; + if (!cache[this.em]) {cache[this.em] = {}} + if (!cache[this.em][s]) { + var bbox = this.BBoxFor(s); + cache[this.em][s] = {w: bbox.w/this.em, h: bbox.h/this.em}; + } + return cache[this.em][s]; + }, + + /* + * For browsers that don't handle sizes of italics properly (MSIE). + * Check the cache first to see if we've already measured it. + */ + EmBoxForItalics: function (s) { + var cache = jsMath.Global.cache.R; + if (!cache[this.em]) {cache[this.em] = {}} + if (!cache[this.em][s]) { + var bbox = this.BBoxFor(s); + if (s.match(/|class=\"(icm|italic|igreek|iaccent)/i)) { + bbox.w = bbox.Mw = this.BBoxFor(s+jsMath.Browser.italicString).w + - jsMath.Browser.italicCorrection; + } + cache[this.em][s] = {w: bbox.w/this.em, h: bbox.h/this.em}; + } + return cache[this.em][s]; + }, + + /* + * Initialize jsMath. This determines the em size, and a variety + * of other parameters used throughout jsMath. + */ + Init: function () { + if (jsMath.Setup.inited != 1) { + if (!jsMath.Setup.inited) {jsMath.Setup.Body()} + if (jsMath.Setup.inited != 1) { + if (jsMath.Setup.inited == -100) return; + alert("It looks like jsMath failed to set up properly (error code " + + jsMath.Setup.inited + "). " + + "I will try to keep going, but it could get ugly."); + jsMath.Setup.inited = 1; + } + } + this.em = this.CurrentEm(); + var cache = jsMath.Global.cache.B; + if (!cache[this.em]) { + cache[this.em] = {}; + cache[this.em].bb = this.BBoxFor('x'); var hh = cache[this.em].bb.h; + cache[this.em].d = this.BBoxFor('x'+jsMath.HTML.Rule(1,hh/jsMath.em)).h - hh; + if (jsMath.Browser.italicString) + {cache[this.em].ic = jsMath.BBoxFor(jsMath.Browser.italicString).w} + } + jsMath.Browser.italicCorrection = cache[this.em].ic; + var bb = cache[this.em].bb; var h = bb.h; var d = cache[this.em].d + this.h = (h-d)/this.em; this.d = d/this.em; + this.hd = this.h + this.d; + + this.Setup.TeXfonts(); + + var x_height = this.EmBoxFor('M').w/2; + this.TeX.M_height = x_height*(26/14); + this.TeX.h = this.h; this.TeX.d = this.d; this.TeX.hd = this.hd; + + this.Img.Scale(); + if (!this.initialized) { + this.Setup.Sizes(); + this.Img.UpdateFonts(); + } + + // factor for \big and its brethren + this.p_height = (this.TeX.cmex10[0].h + this.TeX.cmex10[0].d) / .85; + + this.initialized = 1; + }, + + /* + * Get the x size and if it has changed, reinitialize the sizes + */ + ReInit: function () { + if (this.em != this.CurrentEm()) {this.Init()} + }, + + /* + * Find the em size in effect at the current text location + */ + CurrentEm: function () { + var em = this.BBoxFor('').w/27; + if (em > 0) {return em} + // handle older browsers + return this.BBoxFor('').w/13; + }, + + /* + * Mark jsMath as loaded and copy any user-provided overrides + */ + Loaded: function () { + if (jsMath_old) { + var override = ['Process', 'ProcessBeforeShowing','ProcessElement', + 'ConvertTeX','ConvertTeX2','ConvertLaTeX','ConvertCustom', + 'CustomSearch', 'Synchronize', 'Macro', 'document']; + for (var i = 0; i < override.length; i++) { + if (jsMath_old[override[i]]) {delete jsMath_old[override[i]]} + } + } + if (jsMath_old) {this.Insert(jsMath,jsMath_old)} + jsMath_old = null; + jsMath.loaded = 1; + }, + + /* + * Manage JavaScript objects: + * + * Add: add/replace items in an object + * Insert: add items to an object + * Package: add items to an object prototype + */ + Add: function (dst,src) {for (var id in src) {dst[id] = src[id]}}, + Insert: function (dst,src) { + for (var id in src) { + if (dst[id] && typeof(src[id]) == 'object' + && (typeof(dst[id]) == 'object' + || typeof(dst[id]) == 'function')) { + this.Insert(dst[id],src[id]); + } else { + dst[id] = src[id]; + } + } + }, + Package: function (obj,def) {this.Insert(obj.prototype,def)} + +}; + + +/***************************************************************************/ + + /* + * Implements items associated with the global cache. + * + * This object will be replaced by a global version when + * (and if) jsMath-global.html is loaded. + */ +jsMath.Global = { + isLocal: 1, // a local copy if jsMath-global.html hasn't been loaded + cache: {T: {}, D: {}, R: {}, B: {}}, + + /* + * Clear the global (or local) cache + */ + ClearCache: function () {jsMath.Global.cache = {T: {}, D: {}, R: {}, B: {}}}, + + /* + * Initiate global mode + */ + GoGlobal: function (cookie) { + var url = String(jsMath.window.location); + var c = (jsMath.isCHMmode ? '#' : '?'); + if (cookie) {url = url.replace(/\?.*/,'') + '?' + cookie} + jsMath.Controls.Reload(jsMath.root + "jsMath-global.html" + c +escape(url)); + }, + + /* + * Check if we need to go to global mode + */ + Init: function () { + if (jsMath.Controls.cookie.global == "always" && !jsMath.noGoGlobal) { + if (navigator.accentColorName) return; // OmniWeb crashes on GoGlobal + if (!jsMath.window) {jsMath.window = window} + jsMath.Controls.loaded = 1; + jsMath.Controls.defaults.hiddenGlobal = null; + this.GoGlobal(jsMath.Controls.SetCookie(2)); + } + }, + + /* + * Try to register with a global.html window that contains us + */ + Register: function () { + var parent = jsMath.window.parent; + if (!jsMath.isCHMmode) + {jsMath.isCHMmode = (jsMath.window.location.protocol == 'mk:')} + try { + if (!jsMath.isCHMmode) this.Domain(); + if (parent.jsMath && parent.jsMath.isGlobal) + {parent.jsMath.Register(jsMath.window)} + } catch (err) {jsMath.noGoGlobal = 1} + }, + + /* + * If we're not the parent window, try to set the domain to + * match the parent's domain (so we can use the Global data + * if the surrounding frame is a Global frame). + */ + Domain: function () { + // MSIE/Mac can't do domain changes, so don't bother trying + if (navigator.appName == 'Microsoft Internet Explorer' && + jsMath.platform == 'mac' && navigator.userProfile != null) return; + // MSIE/PC can do domain change, but gets mixed up if we don't + // find a domain that works, and then can't look in window.location + // any longer. So don't try, since we can't afford to leave it confused. + if (jsMath.document.all && !jsMath.window.opera) return; + + if (window == parent) return; + var oldDomain = jsMath.document.domain; + try { + while (true) { + try {if (parent.document.title != null) return} catch (err) {} + if (!document.domain.match(/\..*\./)) break; + jsMath.document.domain = jsMath.document.domain.replace(/^[^.]*\./,''); + } + } catch (err) {} + jsMath.document.domain = oldDomain; + } + +}; + + + +/***************************************************************************/ + +/* + * + * Implement loading of remote scripts using XMLHttpRequest, if + * possible, otherwise use a hidden IFRAME and fake it. That + * method runs asynchronously, which causes lots of headaches. + * Solve these using Push command, which queues actions + * until files have loaded. + */ + +jsMath.Script = { + + request: null, // the XMLHttpRequest object + + /* + * Create the XMLHttpRequest object, if we can. + * Otherwise, use the iframe-based fallback method. + */ + Init: function () { + if (!(jsMath.Controls.cookie.asynch && jsMath.Controls.cookie.progress)) { + if (window.XMLHttpRequest) { + try {this.request = new XMLHttpRequest} catch (err) {} + // MSIE and FireFox3 can't use xmlRequest on local files, + // but we don't have jsMath.browser yet to tell, so use this check + if (this.request && jsMath.root.match(/^file:\/\//)) { + try { + this.request.open("GET",jsMath.root+"jsMath.js",false); + this.request.send(null); + } catch (err) { + this.request = null; + // Firefox3 has window.postMessage for inter-window communication. + // It can be used to handle the new file:// security model, + // so set up the listener. + if (window.postMessage && window.addEventListener) { + this.mustPost = 1; + jsMath.window.addEventListener("message",jsMath.Post.Listener,false); + } + } + } + } + if (!this.request && window.ActiveXObject && !this.mustPost) { + var xml = ["MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0", + "MSXML2.XMLHTTP","Microsoft.XMLHTTP"]; + for (var i = 0; i < xml.length && !this.request; i++) { + try {this.request = new ActiveXObject(xml[i])} catch (err) {} + } + } + } + // + // Use the delayed-script fallback for MSIE/Mac and old versions + // of several browsers (Opera 7.5, OmniWeb 4.5). + // + if (!this.request || jsMath.Setup.domainChanged) + {this.Load = this.delayedLoad; this.needsBody = 1} + }, + + /* + * Load a script and evaluate it in the window's context + */ + Load: function (url,show) { + if (show) { + jsMath.Message.Set("Loading "+url); + jsMath.Script.Delay(1); + jsMath.Script.Push(this,'xmlRequest',url); + jsMath.Script.Push(jsMath.Message,'Clear'); + } else { + jsMath.Script.Push(this,'xmlRequest',url); + } + }, + + /* + * Load a URL and run the contents of the file + */ + xmlRequest: function (url) { + this.blocking = 1; +// this.debug('xmlRequest: '+url); + try { + this.request.open("GET",url,false); + this.request.send(null); + } catch (err) { + this.blocking = 0; + if (jsMath.Translate.restart && jsMath.Translate.asynchronous) {return ""} + throw Error("jsMath can't load the file '"+url+"'\n" + + "Message: "+err.message); + } + if (this.request.status != null && (this.request.status >= 400 || this.request.status < 0)) { + // Do we need to deal with redirected links? + this.blocking = 0; + if (jsMath.Translate.restart && jsMath.Translate.asynchronous) {return ""} + throw Error("jsMath can't load the file '"+url+"'\n" + + "Error status: "+this.request.status); + } + if (!url.match(/\.js$/)) {return(this.request.responseText)} + var tmpQueue = this.queue; this.queue = []; +// this.debug('xml Eval ['+tmpQueue.length+']'); + jsMath.window.eval(this.request.responseText); +// this.debug('xml Done ['+this.queue.length+' + '+tmpQueue.length+']'); + this.blocking = 0; this.queue = this.queue.concat(tmpQueue); + this.Process(); + return ""; + }, + + /******************************************************************** + * + * Implement asynchronous loading and execution of scripts + * (via hidden IFRAME) interleved with other JavaScript commands + * that must be synchronized with the file loading. (Basically, this + * is for MSIE/Mac and Opera 7.5, which don't have XMLHttpRequest.) + */ + + cancelTimeout: 30*1000, // delay for canceling load (30 sec) + + blocking: 0, // true when an asynchronous action is being performed + cancelTimer: null, // timer to cancel load if it takes too long + needsBody: 0, // true if loading files requires BODY to be present + + queue: [], // the stack of pending actions + + /* + * Provide mechanism for synchronizing with the asynchronous jsMath + * file-loading mechanism. 'code' can be a string or a function. + */ + Synchronize: function (code,data) { + if (typeof(code) != 'string') {jsMath.Script.Push(null,code,data)} + else {jsMath.Script.Push(jsMath.window,'eval',code)} + }, + + /* + * Queue a function to be processed. + * If nothing is being loaded, do the pending commands. + */ + Push: function (object,method,data) { +// this.debug('Pushing: '+method+' at '+this.queue.length); // debug + this.queue[this.queue.length] = [object,method,data]; + if (!(this.blocking || (this.needsBody && !jsMath.document.body))) this.Process(); + }, + + /* + * Do any pending functions (stopping if a file load is started) + */ + Process: function () { + while (this.queue.length && !this.blocking) { + var call = this.queue[0]; this.queue = this.queue.slice(1); + var savedQueue = this.SaveQueue(); + var object = call[0]; var method = call[1]; var data = call[2]; +// this.debug('Calling: '+method+' ['+savedQueue.length+']'); // debug + if (object) {object[method](data)} else if (method) {method(data)} +// this.debug('Done: '+method+' ['+this.queue.length+' + '+savedQueue.length+'] ('+this.blocking+')'); // debug + this.RestoreQueue(savedQueue); + } + }, + + /* + * Allows pushes to occur at the FRONT of the queue + * (so a command acts as a single unit, including anything + * that it pushes on to the command stack) + */ + SaveQueue: function () { + var queue = this.queue; + this.queue = []; + return queue; + }, + RestoreQueue: function (queue) { + this.queue = this.queue.concat(queue); + }, + + /* + * Handle loading of scripts that run asynchronously + */ + delayedLoad: function (url) { +// this.debug('Loading: '+url); + this.Push(this,'startLoad',url); + }, + startLoad: function (url) { + var iframe = jsMath.document.createElement('iframe'); + iframe.style.visibility = 'hidden'; + iframe.style.position = 'absolute'; + iframe.style.width = '0px'; + iframe.style.height = '0px'; + if (jsMath.document.body.firstChild) { + jsMath.document.body.insertBefore(iframe,jsMath.document.body.firstChild); + } else { + jsMath.document.body.appendChild(iframe); + } + this.blocking = 1; this.url = url; + if (url.substr(0,jsMath.root.length) == jsMath.root) + {url = url.substr(jsMath.root.length)} + jsMath.Message.Set("Loading "+url); + this.cancelTimer = setTimeout('jsMath.Script.cancelLoad()',this.cancelTimeout); + if (this.mustPost) {iframe.src = jsMath.Post.startLoad(url,iframe)} + else if (url.match(/\.js$/)) {iframe.src = jsMath.root+"jsMath-loader.html"} + else {iframe.src = this.url} + }, + endLoad: function (action) { + if (this.cancelTimer) {clearTimeout(this.cancelTimer); this.cancelTimer = null} + jsMath.Post.endLoad(); + jsMath.Message.Clear(); + if (action != 'cancel') {this.blocking = 0; this.Process()} + }, + + Start: function () { +// this.debug('Starting: ['+this.queue.length+'] '+this.url); + this.tmpQueue = this.queue; this.queue = []; + }, + End: function () { +// this.debug('Ending: ['+this.queue.length+' + '+this.tmpQueue.length+'] '+this.url); + this.queue = this.queue.concat(this.tmpQueue); delete this.tmpQueue; + }, + + /* + * If the loading takes too long, cancel it and end the load. + */ + cancelLoad: function (message,delay) { + if (this.cancelTimer) {clearTimeout(this.cancelTimer); this.cancelTimer = null} + if (message == null) {message = "Can't load file"} + if (delay == null) {delay = 2000} + jsMath.Message.Set(message); + setTimeout('jsMath.Script.endLoad("cancel")',delay); + }, + + /* + * Perform a delay (to let the browser catch up) + */ + Delay: function (time) { + this.blocking = 1; + setTimeout('jsMath.Script.endDelay()',time); + }, + endDelay: function () { +// this.debug('endDelay'); + this.blocking = 0; + this.Process(); + }, + + /* + * Load an image and wait for it + * (so MSIE won't load extra copies of it) + */ + imageCount: 0, + WaitForImage: function (file) { + this.blocking = 1; this.imageCount++; + if (this.img == null) {this.img = []} + var img = new Image(); this.img[this.img.length] = img; + img.onload = function () {if (--jsMath.Script.imageCount == 0) jsMath.Script.endDelay()} + img.onerror = img.onload; img.onabort = img.onload; + img.src = file; + }, + + /* + * The code uncompressor + */ + Uncompress: function (data) { + for (var k = 0; k < data.length; k++) { + var d = data[k]; var n = d.length; + for (var i = 0; i < n; i++) {if (typeof(d[i]) == 'number') {d[i] = d[d[i]]}} + data[k] = d.join(''); + } + window.eval(data.join('')); + } + + /* + * for debugging the event queue + */ + /* + * ,debug: function (message) { + * if (jsMath.document.body && jsMath.window.debug) {jsMath.window.debug(message)} + * else {alert(message)} + * } + */ + +}; + +/***************************************************************************/ + +/* + * Handle window.postMessage() events in Firefox3 + */ + +jsMath.Post = { + window: null, // iframe we are listening to + + Listener: function (event) { + if (event.source != jsMath.Post.window) return; + var domain = event.origin.replace(/^file:\/\//,''); + var ddomain = document.domain.replace(/^file:\/\//,''); + if (domain == null || domain == "" || domain == "null") {domain = "localhost"} + if (ddomain == null || ddomain == "" || ddomain == "null") {ddomain = "localhost"} + if (domain != ddomain || !event.data.substr(0,6).match(/jsM(CP|LD|AL):/)) return; + var type = event.data.substr(6,3).replace(/ /g,''); + var message = event.data.substr(10); + if (jsMath.Post.Commands[type]) (jsMath.Post.Commands[type])(message); + // cancel event? + }, + + /* + * Commands that can be performed by the listener + */ + Commands: { + SCR: function (message) {jsMath.window.eval(message)}, + ERR: function (message) {jsMath.Script.cancelLoad(message,3000)}, + BGN: function (message) {jsMath.Script.Start()}, + END: function (message) {if (message) jsMath.Script.End(); jsMath.Script.endLoad()} + }, + + startLoad: function (url,iframe) { + this.window = iframe.contentWindow; + if (!url.match(/\.js$/)) {return jsMath.root+url} + return jsMath.root+"jsMath-loader-post.html?"+url; + }, + endLoad: function () {this.window = null} +}; + +/***************************************************************************/ + +/* + * Message and screen blanking facility + */ + +jsMath.Message = { + + blank: null, // the div to blank out the screen + message: null, // the div for the messages + text: null, // the text node for messages + clear: null, // timer for clearing message + + /* + * Create the elements needed for the message box + */ + Init: function () { + if (!jsMath.document.body || !jsMath.Controls.cookie.progress) return; + this.message = jsMath.Element('message'); + if (!this.message) { + if (jsMath.Setup.stylesReady) { + this.message = jsMath.Setup.DIV('message',{visibility:'hidden'},jsMath.fixedDiv); + } else { + this.message = jsMath.Setup.DIV('message',{ + visibility:'hidden', position:'absolute', bottom:'1px', left:'2px', + backgroundColor:'#E6E6E6', border:'solid 1px #959595', + margin:'0px', padding:'1px 8px', zIndex:102, + color:'black', fontSize:'small', width:'auto' + },jsMath.fixedDiv); + } + } + this.text = jsMath.document.createTextNode(''); + this.message.appendChild(this.text); + this.message.onmousedown = jsMath.Translate.Cancel; + }, + + /* + * Set the contents of the message box, or use the window status line + */ + Set: function (text,canCancel) { + if (this.clear) {clearTimeout(this.clear); this.clear = null} + if (jsMath.Controls.cookie.progress) { + if (!this.text) {this.Init(); if (!this.text) return} + if (jsMath.Browser.textNodeBug) {this.message.innerHTML = text} + else {this.text.nodeValue = text} + this.message.style.visibility = 'visible'; + if (canCancel) { + this.message.style.cursor = 'pointer'; + if (!this.message.style.cursor) {this.message.style.cursor = 'hand'} + this.message.title = ' Cancel Processing of Math '; + } else { + this.message.style.cursor = ''; + this.message.title = ''; + } + } else { + if (text.substr(0,8) != "Loading ") {jsMath.window.status = text} + } + }, + + /* + * Clear the message box or status line + */ + Clear: function () { + if (this.clear) {clearTimeout(this.clear)} + this.clear = setTimeout("jsMath.Message.doClear()",1000); + }, + doClear: function () { + if (this.clear) { + this.clear = null; + jsMath.window.status = ''; + if (this.text) {this.text.nodeValue = ''} + if (this.message) {this.message.style.visibility = 'hidden'} + } + }, + + + /* + * Put up a DIV that covers the window so that the + * "flicker" of processing the mathematics will not be visible + */ + Blank: function () { + if (this.blank || !jsMath.document.body) return; + this.blank = jsMath.Setup.DIV("blank",{ + position:(jsMath.Browser.msiePositionFixedBug? 'absolute': 'fixed'), + top:'0px', left:'0px', bottom:'0px', right:'0px', + zIndex:101, backgroundColor:'white' + },jsMath.fixedDiv); + if (jsMath.Browser.msieBlankBug) { + this.blank.innerHTML = ' '; + this.blank.style.width = "110%"; + this.blank.style.height = "110%"; + } + }, + + UnBlank: function () { + if (this.blank) {jsMath.document.body.removeChild(this.blank)} + this.blank = null; + } +}; + + +/***************************************************************************/ + +/* + * Miscellaneous setup and initialization + */ +jsMath.Setup = { + + loaded: [], // array of files already loaded + + /* + * Insert a DIV at the top of the page with given ID, + * attributes, and style settings + */ + DIV: function (id,styles,parent) { + if (parent == null) {parent = jsMath.document.body} + var div = jsMath.document.createElement('div'); + div.id = 'jsMath_'+id; + for (var i in styles) {div.style[i]= styles[i]} + if (!parent.hasChildNodes) {parent.appendChild(div)} + else {parent.insertBefore(div,parent.firstChild)} + return div; + }, + + /* + * Source a jsMath JavaScript file (only load any given file once) + */ + Script: function (file,show) { + if (this.loaded[file]) {return} else {this.loaded[file] = 1} + if (!file.match('^([a-zA-Z]+:/?)?/')) {file = jsMath.root + file} + jsMath.Script.Load(file,show); + }, + + /* + * Use a hidden
for measuring the BBoxes of things + */ + Hidden: function () { + jsMath.hidden = this.DIV("Hidden",{ + visibility: 'hidden', position:"absolute", + top:0, left:0, border:0, padding:0, margin:0 + }); + jsMath.hiddenTop = jsMath.hidden; + return; + }, + + /* + * Find the root URL for the jsMath files (so we can load + * the other .js and .gif files) + */ + Source: function () { + if (jsMath.Autoload && jsMath.Autoload.root) { + jsMath.root = jsMath.Autoload.root; + } else { + jsMath.root = ''; + var script = jsMath.document.getElementsByTagName('script'); + if (script) { + for (var i = 0; i < script.length; i++) { + var src = script[i].src; + if (src && src.match('(^|/|\\\\)jsMath.js$')) { + jsMath.root = src.replace(/jsMath.js$/,''); + break; + } + } + } + } + if (jsMath.root.charAt(0) == '\\') {jsMath.root = jsMath.root.replace(/\\/g,'/')} + if (jsMath.root.charAt(0) == '/') { + if (jsMath.root.charAt(1) != '/') + {jsMath.root = '//' + jsMath.document.location.host + jsMath.root} + jsMath.root = jsMath.document.location.protocol + jsMath.root; + } else if (!jsMath.root.match(/^[a-z]+:/i)) { + var src = new String(jsMath.document.location); + var pattern = new RegExp('/[^/]*/\\.\\./') + jsMath.root = src.replace(new RegExp('[^/]*$'),'') + jsMath.root; + while (jsMath.root.match(pattern)) + {jsMath.root = jsMath.root.replace(pattern,'/')} + } + jsMath.Img.root = jsMath.root + "fonts/"; + jsMath.blank = jsMath.root + "blank.gif"; + this.Domain(); + }, + + /* + * Find the most restricted common domain for the main + * page and jsMath. Report an error if jsMath is outside + * the domain of the calling page. + */ + Domain: function () { + try {jsMath.document.domain} catch (err) {return} + var jsDomain = ''; var pageDomain = jsMath.document.domain; + if (jsMath.root.match('://([^/]*)/')) {jsDomain = RegExp.$1} + jsDomain = jsDomain.replace(/:\d+$/,''); + if (jsDomain == "" || jsDomain == pageDomain) return; + // + // MSIE on the Mac can't change jsMath.document.domain and 'try' won't + // catch the error (Grrr!), so exit for them. + // + if (navigator.appName == 'Microsoft Internet Explorer' && + jsMath.platform == 'mac' && navigator.onLine && + navigator.userProfile && jsMath.document.all) return; + jsDomain = jsDomain.split(/\./); pageDomain = pageDomain.split(/\./); + if (jsDomain.length < 2 || pageDomain.length < 2 || + jsDomain[jsDomain.length-1] != pageDomain[pageDomain.length-1] || + jsDomain[jsDomain.length-2] != pageDomain[pageDomain.length-2]) { + this.DomainWarning(); + return; + } + var domain = jsDomain[jsDomain.length-2] + '.' + jsDomain[jsDomain.length-1]; + for (var i = 3; i <= jsDomain.length && i <= pageDomain.length; i++) { + if (jsDomain[jsDomain.length-i] != pageDomain[pageDomain.length-i]) break; + domain = jsDomain[jsDomain.length-i] + '.' + domain; + } + jsMath.document.domain = domain; + this.domainChanged = 1; + }, + + DomainWarning: function () { + alert("In order for jsMath to be able to load the additional " + + "components that it may need, the jsMath.js file must be " + + "loaded from a server in the same domain as the page that " + + "contains it. Because that is not the case for this page, " + + "the mathematics displayed here may not appear correctly."); + }, + + /* + * Initialize a font's encoding array + */ + EncodeFont: function (name) { + var font = jsMath.TeX[name]; + if (font[0].c != null) return; + for (var k = 0; k < 128; k++) { + var data = font[k]; font[k] = data[3]; + if (font[k] == null) {font[k] = {}}; + font[k].w = data[0]; font[k].h = data[1]; + if (data[2] != null) {font[k].d = data[2]} + font[k].c = jsMath.TeX.encoding[k]; + } + }, + + /* + * Initialize the encodings for all fonts + */ + Fonts: function () { + for (var i = 0; i < jsMath.TeX.fam.length; i++) { + var name = jsMath.TeX.fam[i]; + if (name) {this.EncodeFont(name)} + } + }, + + /* + * Look up the default height and depth for a TeX font + * and set the skewchar + */ + TeXfont: function (name) { + var font = jsMath.TeX[name]; if (font == null) return; + var WH = jsMath.EmBoxFor(''+font[65].c+''); + font.hd = WH.h; + font.d = jsMath.EmBoxFor(''+ font[65].c + + jsMath.HTML.Rule(1,font.hd) + '').h - font.hd; + font.h = font.hd - font.d; + if (name == 'cmmi10') {font.skewchar = 0177} + else if (name == 'cmsy10') {font.skewchar = 060} + }, + + /* + * Init all the TeX fonts + */ + TeXfonts: function () { + for (var i = 0; i < jsMath.TeX.fam.length; i++) + {if (jsMath.TeX.fam[i]) {this.TeXfont(jsMath.TeX.fam[i])}} + }, + + /* + * Compute font parameters for various sizes + */ + Sizes: function () { + jsMath.TeXparams = []; var i; var j; + for (j=0; j < jsMath.sizes.length; j++) {jsMath.TeXparams[j] = {}} + for (i in jsMath.TeX) { + if (typeof(jsMath.TeX[i]) != 'object') { + for (j=0; j < jsMath.sizes.length; j++) { + jsMath.TeXparams[j][i] = jsMath.sizes[j]*jsMath.TeX[i]/100; + } + } + } + }, + + /* + * Send the style definitions to the browser (these may be adjusted + * by the browser-specific code) + */ + Styles: function (styles) { + if (!styles) { + styles = jsMath.styles; + styles['.typeset .scale'] = {'font-size': jsMath.Controls.cookie.scale+'%'}; + this.stylesReady = 1; + } + jsMath.Script.Push(this,'AddStyleSheet',styles); + if (jsMath.Browser.styleChangeDelay) {jsMath.Script.Push(jsMath.Script,'Delay',1)} + }, + + /* + * Make a style string from a hash of style definitions, which are + * either strings themselves or hashes of style settings. + */ + StyleString: function (styles) { + var styleString = {}, id; + for (id in styles) { + if (typeof styles[id] === 'string') { + styleString[id] = styles[id]; + } else if (id.substr(0,1) === '@') { + styleString[id] = this.StyleString(styles[id]); + } else if (styles[id] != null) { + var style = []; + for (var name in styles[id]) { + if (styles[id][name] != null) + {style[style.length] = name + ': ' + styles[id][name]} + } + styleString[id] = style.join('; '); + } + } + var string = ''; + for (id in styleString) {string += id + " {"+styleString[id]+"}\n"} + return string; + }, + + AddStyleSheet: function (styles) { + var head = jsMath.document.getElementsByTagName('head')[0]; + if (head) { + var string = this.StyleString(styles); + if (jsMath.document.createStyleSheet) {// check for MSIE + head.insertAdjacentHTML('beforeEnd', + 'x' // MSIE needs this for some reason + + ''); + } else { + var style = jsMath.document.createElement('style'); style.type = "text/css"; + style.appendChild(jsMath.document.createTextNode(string)); + head.appendChild(style); + } + } else if (!jsMath.noHEAD) { + jsMath.noHEAD = 1; + alert("Document is missing its section. Style sheet can't be created without it."); + } + }, + + /* + * Do the initialization that requires the to be in place. + */ + Body: function () { + if (this.inited) return; + + this.inited = -1; + + jsMath.Setup.Hidden(); this.inited = -2; + jsMath.Browser.Init(); this.inited = -3; + + // blank screen if necessary + if (jsMath.Controls.cookie.blank) {jsMath.Message.Blank()}; this.inited = -4; + + jsMath.Setup.Styles(); this.inited = -5; + jsMath.Controls.Init(); this.inited = -6; + + // do user-specific initialization + jsMath.Script.Push(jsMath.Setup,'User','pre-font'); this.inited = -7; + + // make sure browser-specific loads are done before this + jsMath.Script.Push(jsMath.Font,'Check'); + if (jsMath.Font.register.length) + {jsMath.Script.Push(jsMath.Font,'LoadRegistered')} + + this.inited = 1; + }, + + /* + * Web page author can override the entries to the UserEvent hash + * functions that will be run at various times during jsMath's setup + * process. + */ + User: function (when) { + if (jsMath.Setup.UserEvent[when]) {(jsMath.Setup.UserEvent[when])()} + }, + + UserEvent: { + "pre-font": null, // after browser is set up but before fonts are tested + "onload": null // after jsMath.js is loaded and finished running + } + +}; + +jsMath.Update = { + + /* + * Update specific parameters for a limited number of font entries + */ + TeXfonts: function (change) { + for (var font in change) { + for (var code in change[font]) { + for (var id in change[font][code]) { + jsMath.TeX[font][code][id] = change[font][code][id]; + } + } + } + }, + + /* + * Update the character code for every character in a list + * of fonts + */ + TeXfontCodes: function (change) { + for (var font in change) { + for (var i = 0; i < change[font].length; i++) { + jsMath.TeX[font][i].c = change[font][i]; + } + } + } + +}; + +/***************************************************************************/ + +/* + * Implement browser-specific checks + */ + +jsMath.Browser = { + + allowAbsolute: 1, // tells if browser can nest absolutely positioned + // SPANs inside relative SPANs + allowAbsoluteDelim: 0, // OK to use absolute placement for building delims? + separateSkips: 0, // MSIE doesn't do negative left margins, and + // Netscape doesn't combine skips well + + valignBug: 0, // Konqueror doesn't nest vertical-align + operaHiddenFix: '', // for Opera to fix bug with math in tables + msieCenterBugFix: '', // for MSIE centering bug with image fonts + msieInlineBlockFix: '', // for MSIE alignment bug in non-quirks mode + msieSpaceFix: '', // for MSIE to avoid dropping empty spans + imgScale: 1, // MSI scales images for 120dpi screens, so compensate + + renameOK: 1, // tells if brower will find a tag whose name + // has been set via setAttributes + styleChangeDelay: 0, // true if style changes need a delay in order + // for them to be available + + delay: 1, // delay for asynchronous math processing + + version: 0, // browser version number (when needed) + + /* + * Determine if the "top" of a is always at the same height + * or varies with the height of the rest of the line (MSIE). + */ + TestSpanHeight: function () { + jsMath.hidden.innerHTML = ''; + var span = jsMath.hidden.firstChild; + var img = span.firstChild; + this.spanHeightVaries = (span.offsetHeight >= img.offsetHeight && span.offsetHeight > 0); + this.spanHeightTooBig = (span.offsetHeight > img.offsetHeight); + jsMath.hidden.innerHTML = ''; + }, + + /* + * Determine if an inline-block with 0 width is OK or not + * and decide whether to use spans or images for spacing + */ + TestInlineBlock: function () { + this.block = "display:-moz-inline-box"; + this.hasInlineBlock = jsMath.BBoxFor('').w > 0; + if (this.hasInlineBlock) { + jsMath.styles['.typeset .blank'].display = '-moz-inline-box'; + delete jsMath.styles['.typeset .spacer'].display; + } else { + this.block = "display:inline-block"; + this.hasInlineBlock = jsMath.BBoxFor('').w > 0; + if (!this.hasInlineBlock) return; + } + this.block += ';overflow:hidden'; + var h = jsMath.BBoxFor('x').h; + this.mozInlineBlockBug = jsMath.BBoxFor( + 'x'+ + '').h > 2*h; + this.widthAddsBorder = jsMath.BBoxFor('').w > 10; + this.msieBorderBug = + jsMath.BBoxFor('x').h != + jsMath.BBoxFor('x').h; + this.blankWidthBug = this.msieBorderBug || + jsMath.BBoxFor('').h == 0; + }, + + /* + * Determine if the NAME attribute of a tag can be changed + * using the setAttribute function, and then be properly + * returned by getElementByName. + */ + TestRenameOK: function () { + jsMath.hidden.innerHTML = ''; + var test = jsMath.hidden.firstChild; + test.setAttribute('name','jsMath_test'); + this.renameOK = (jsMath.document.getElementsByName('jsMath_test').length > 0); + jsMath.hidden.innerHTML = ''; + }, + + /* + * See if style changes occur immediately, or if we need to delay + * in order to let them take effect. + */ + TestStyleChange: function () { + jsMath.hidden.innerHTML = 'x'; + var span = jsMath.hidden.firstChild; + var w = span.offsetWidth; + jsMath.Setup.AddStyleSheet({'#jsMath_test': 'font-size:200%'}); + this.styleChangeDelay = (span.offsetWidth == w); + jsMath.hidden.innerHTML = ''; + }, + + /* + * Perform a version check on a standard version string + */ + VersionAtLeast: function (v) { + var bv = new String(this.version).split('.'); + v = new String(v).split('.'); if (v[1] == null) {v[1] = '0'} + return bv[0] > v[0] || (bv[0] == v[0] && bv[1] >= v[1]); + }, + + /* + * Test for browser characteristics, and adjust things + * to overcome specific browser bugs + */ + Init: function () { + jsMath.browser = 'unknown'; + this.TestInlineBlock(); + this.TestSpanHeight(); + this.TestRenameOK(); + this.TestStyleChange(); + + this.MSIE(); + this.Mozilla(); + this.Opera(); + this.OmniWeb(); + this.Safari(); + this.Konqueror(); + + // + // Change some routines depending on the browser + // + if (this.allowAbsoluteDelim) { + jsMath.Box.DelimExtend = jsMath.Box.DelimExtendAbsolute; + jsMath.Box.Layout = jsMath.Box.LayoutAbsolute; + } else { + jsMath.Box.DelimExtend = jsMath.Box.DelimExtendRelative; + jsMath.Box.Layout = jsMath.Box.LayoutRelative; + } + + if (this.separateSkips) { + jsMath.HTML.Place = jsMath.HTML.PlaceSeparateSkips; + jsMath.Typeset.prototype.Place = jsMath.Typeset.prototype.PlaceSeparateSkips; + } + }, + + // + // Handle bug-filled Internet Explorer + // + MSIE: function () { + if (this.spanHeightVaries && !this.spanHeightTooBig) { + jsMath.browser = 'MSIE'; + if (jsMath.platform == 'pc') { + this.IE7 = (window.XMLHttpRequest != null); + this.quirks = (jsMath.document.compatMode == "BackCompat"); + this.msieStandard6 = !this.quirks && !this.IE7; + this.allowAbsoluteDelim = 1; this.separateSkips = 1; + this.buttonCheck = 1; this.msieBlankBug = 1; + this.msieAccentBug = 1; this.msieRelativeClipBug = 1; + this.msieDivWidthBug = 1; this.msiePositionFixedBug = 1; + this.msieIntegralBug = 1; this.waitForImages = 1; + this.msieAlphaBug = !this.IE7; this.alphaPrintBug = !this.IE7; + this.msieCenterBugFix = 'position:relative; '; + this.msieInlineBlockFix = ' display:inline-block;'; + this.msieTeXfontBaselineBug = !this.quirks; + this.msieBorderBug = this.blankWidthBug = 1; // force these, since IE7 doesn't register it + this.msieSpaceFix = ''; + jsMath.Macro('joinrel','\\mathrel{\\kern-5mu}'), + jsMath.Parser.prototype.mathchardef.mapstocharOrig = jsMath.Parser.prototype.mathchardef.mapstochar; + delete jsMath.Parser.prototype.mathchardef.mapstochar; + jsMath.Macro('mapstochar','\\rlap{\\mapstocharOrig\\,}\\kern1mu'), + jsMath.styles['.typeset .arial'] = {'font-family': "'Arial unicode MS'"}; + if (!this.IE7 || this.quirks) { + // MSIE doesn't implement fixed positioning, so use absolute + jsMath.styles['#jsMath_message'].position = 'absolute'; + delete jsMath.styles['#jsMath_message'].width; + jsMath.styles['#jsMath_panel'].position = 'absolute'; + delete jsMath.styles['#jsMath_panel'].width; + jsMath.styles['#jsMath_button'].width = '1px'; + jsMath.styles['#jsMath_button'].position = 'absolute' + delete jsMath.styles['#jsMath_button'].width; + jsMath.fixedDiv = jsMath.Setup.DIV("fixedDiv",{position:'absolute', zIndex: 101}); + jsMath.window.attachEvent("onscroll",jsMath.Controls.MoveButton); + jsMath.window.attachEvent("onresize",jsMath.Controls.MoveButton); + jsMath.Controls.MoveButton(); + } + // Make MSIE put borders around the whole button + jsMath.styles['#jsMath_noFont .link'].display = "inline-block"; + // MSIE needs this NOT to be inline-block + delete jsMath.styles['.typeset .spacer'].display; + // MSIE can't insert DIV's into text nodes, so tex2math must use SPAN's to fake DIV's + jsMath.styles['.tex2math_div'] = {}; jsMath.Add(jsMath.styles['.tex2math_div'],jsMath.styles['div.typeset']); + jsMath.styles['.tex2math_div'].width = '100%'; + jsMath.styles['.tex2math_div'].display = 'inline-block'; + // Reduce occurrance of zoom bug in IE7 + jsMath.styles['.typeset']['letter-spacing'] = '0'; + // MSIE will rescale images if the DPIs differ + if (screen.deviceXDPI && screen.logicalXDPI + && screen.deviceXDPI != screen.logicalXDPI) { + this.imgScale *= screen.logicalXDPI/screen.deviceXDPI; + jsMath.Controls.cookie.alpha = 0; + } + // Handle bug with getting width of italic text + this.italicString = 'x'; + jsMath.EmBoxFor = jsMath.EmBoxForItalics; + } else if (jsMath.platform == 'mac') { + this.msieAbsoluteBug = 1; this.msieButtonBug = 1; + this.msieDivWidthBug = 1; this.msieBlankBug = 1; + this.quirks = 1; + jsMath.Setup.Script('jsMath-msie-mac.js'); + jsMath.Parser.prototype.macros.angle = ['Replace','ord','','normal']; + jsMath.styles['#jsMath_panel'].width = '42em'; + jsMath.Controls.cookie.printwarn = 0; // MSIE/Mac doesn't handle '@media screen' + } + jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}'); + jsMath.Macro('angle','\\raise1.84pt{\\kern2.5mu\\rlap{\\scriptstyle/}\\kern.5pt\\rule{.4em}{-1.5pt}{1.84pt}\\kern2.5mu}'); + } + }, + + // + // Handle Netscape/Mozilla (any flavor) + // + Mozilla: function () { + if (jsMath.hidden.ATTRIBUTE_NODE && jsMath.window.directories) { + jsMath.browser = 'Mozilla'; + if (jsMath.platform == 'pc') {this.alphaPrintBug = 1} + this.allowAbsoluteDelim = 1; + jsMath.styles['#jsMath_button'].cursor = jsMath.styles['#jsMath_noFont .link'].cursor = 'pointer', + jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}'); + jsMath.Macro('angle','\\raise1.34pt{\\kern2.5mu\\rlap{\\scriptstyle/}\\rule{.4em}{-1pt}{1.34pt}\\kern2.5mu}'); + if (navigator.vendor == 'Firefox') { + this.version = navigator.vendorSub; + } else if (navigator.userAgent.match(' Firefox/([0-9.]+)([a-z ]|$)')) { + this.version = RegExp.$1; + } + if (this.VersionAtLeast("3.0")) {this.mozImageSizeBug = 1} + } + }, + + // + // Handle OmniWeb + // + OmniWeb: function () { + if (navigator.accentColorName) { + jsMath.browser = 'OmniWeb'; + this.allowAbsolute = this.hasInlineBlock; + this.allowAbsoluteDelim = this.allowAbsolute; + this.valignBug = !this.allowAbsolute; + this.buttonCheck = 1; this.textNodeBug = 1; + jsMath.noChangeGlobal = 1; // OmniWeb craches on GoGlobal + if (!this.hasInlineBlock) {jsMath.Setup.Script('jsMath-old-browsers.js')} + } + }, + + // + // Handle Opera + // + Opera: function () { + if (this.spanHeightTooBig) { + jsMath.browser = 'Opera'; + var isOld = navigator.userAgent.match("Opera 7"); + this.allowAbsolute = 0; + this.delay = 10; + this.operaHiddenFix = '[Processing]'; + if (isOld) {jsMath.Setup.Script('jsMath-old-browsers.js')} + var version = navigator.appVersion.match(/^(\d+\.\d+)/); + if (version) {this.version = version[1]} else {this.vesion = 0} + this.operaAbsoluteWidthBug = this.operaLineHeightBug = (version[1] >= 9.5 && version[1] < 9.6); + } + }, + + // + // Handle Safari + // + Safari: function () { + if (navigator.appVersion.match(/Safari\//)) { + jsMath.browser = 'Safari'; + if (navigator.vendor.match(/Google/)) {jsMath.browser = 'Chrome'} + var version = navigator.userAgent.match("Safari/([0-9]+)"); + version = (version)? version[1] : 400; this.version = version; + jsMath.TeX.axis_height += .05; + this.allowAbsoluteDelim = version >= 125; + this.safariIFRAMEbug = version >= 312 && version < 412; + this.safariButtonBug = version < 412; + this.safariImgBug = 1; this.textNodeBug = 1; + this.buttonCheck = version < 500; + this.styleChangeDelay = 1; + jsMath.Macro('not','\\mathrel{\\rlap{\\kern3.25mu/}}'); + } + }, + + // + // Handle Konqueror + // + Konqueror: function () { + if (navigator.product && navigator.product.match("Konqueror")) { + jsMath.browser = 'Konqueror'; + this.allowAbsolute = 0; + this.allowAbsoluteDelim = 0; + if (navigator.userAgent.match(/Konqueror\/(\d+)\.(\d+)/)) { + if (RegExp.$1 < 3 || (RegExp.$1 == 3 && RegExp.$2 < 3)) { + this.separateSkips = 1; + this.valignBug = 1; + jsMath.Setup.Script('jsMath-old-browsers.js'); + } + } + // Apparently, Konqueror wants the names without the hyphen + jsMath.Add(jsMath.styles,{ + '.typeset .cmr10': 'font-family: jsMath-cmr10, jsMath cmr10, serif', + '.typeset .cmbx10': 'font-family: jsMath-cmbx10, jsMath cmbx10, jsMath-cmr10, jsMath cmr10', + '.typeset .cmti10': 'font-family: jsMath-cmti10, jsMath cmti10, jsMath-cmr10, jsMath cmr10', + '.typeset .cmmi10': 'font-family: jsMath-cmmi10, jsMath cmmi10', + '.typeset .cmsy10': 'font-family: jsMath-cmsy10, jsMath cmsy10', + '.typeset .cmex10': 'font-family: jsMath-cmex10, jsMath cmex10' + }); + jsMath.Font.testFont = "jsMath-cmex10, jsMath cmex10"; + } + } + +}; + +/***************************************************************************/ + +/* + * Implement font check and messages + */ +jsMath.Font = { + + testFont: "jsMath-cmex10", + fallback: "symbol", // the default fallback method + register: [], // list of fonts registered before jsMath.Init() + + // the HTML for the missing font message + message: + 'No jsMath TeX fonts found -- using image fonts instead.
\n' + + 'These may be slow and might not print well.
\n' + + 'Use the jsMath control panel to get additional information.', + + extra_message: + 'Extra TeX fonts not found:
' + + 'Using image fonts instead. This may be slow and might not print well.
\n' + + 'Use the jsMath control panel to get additional information.', + + print_message: + 'To print higher-resolution math symbols, click the
\n' + + 'Hi-Res Fonts for Printing button on the jsMath control panel.
\n', + + alpha_message: + 'If the math symbols print as black boxes, turn off image alpha channels
\n' + + 'using the Options pane of the jsMath control panel.
\n', + + /* + * Look to see if a font is found. + * Check the character in a given position, and see if it is + * wider than the usual one in that position. + */ + Test1: function (name,n,factor,prefix) { + if (n == null) {n = 0x7C}; if (factor == null) {factor = 2}; if (prefix == null) {prefix = ''} + var wh1 = jsMath.BBoxFor(''+jsMath.TeX[name][n].c+''); + var wh2 = jsMath.BBoxFor(''+jsMath.TeX[name][n].c+''); + //alert([wh1.w,wh2.w,wh1.h,factor*wh2.w]); + return (wh1.w > factor*wh2.w && wh1.h != 0); + }, + + Test2: function (name,n,factor,prefix) { + if (n == null) {n = 0x7C}; if (factor == null) {factor = 2}; if (prefix == null) {prefix = ''} + var wh1 = jsMath.BBoxFor(''+jsMath.TeX[name][n].c+''); + var wh2 = jsMath.BBoxFor(''+jsMath.TeX[name][n].c+''); + //alert([wh2.w,wh1.w,wh1.h,factor*wh1.w]); + return (wh2.w > factor*wh1.w && wh1.h != 0); + }, + + /* + * Check for the new jsMath versions of the fonts (blacker with + * different encoding) and if not found, look for old-style fonts. + * If they are found, load the BaKoMa encoding information. + */ + CheckTeX: function () { + var wh = jsMath.BBoxFor(''+jsMath.TeX.cmex10[1].c+''); + jsMath.nofonts = ((wh.w*3 > wh.h || wh.h == 0) && !this.Test1('cmr10',null,null,'jsMath-')); + if (!jsMath.nofonts) return; + if (jsMath.browser != 'Mozilla' || + (jsMath.platform == "mac" && + (!jsMath.Browser.VersionAtLeast(1.5) || jsMath.Browser.VersionAtLeast(3.0))) || + (jsMath.platform != "mac" && !jsMath.Browser.VersionAtLeast(3.0))) { + wh = jsMath.BBoxFor(''+jsMath.TeX.cmex10[1].c+''); + jsMath.nofonts = ((wh.w*3 > wh.h || wh.h == 0) && !this.Test1('cmr10')); + if (!jsMath.nofonts) {jsMath.Setup.Script("jsMath-BaKoMa-fonts.js")} + } + }, + + /* + * Check for the availability of TeX fonts. We do this by looking at + * the width and height of a character in the cmex10 font. The cmex10 + * font has depth considerably greater than most characters' widths (the + * whole font has the depth of the character with greatest depth). This + * is not the case for most fonts, so if we can access cmex10, the + * height of a character should be much bigger than the width. + * Otherwise, if we don't have cmex10, we'll get a character in another + * font with normal height and width. In this case, we insert a message + * pointing the user to the jsMath site, and load one of the fallback + * definitions. + * + */ + Check: function () { + var cookie = jsMath.Controls.cookie; + this.CheckTeX(); + if (jsMath.nofonts) { + if (cookie.autofont || cookie.font == 'tex') { + cookie.font = this.fallback; + if (cookie.warn) { + jsMath.nofontMessage = 1; + cookie.warn = 0; jsMath.Controls.SetCookie(0); + if (jsMath.window.NoFontMessage) {jsMath.window.NoFontMessage()} + else {this.Message(this.message)} + } + } + } else { + if (cookie.autofont) {cookie.font = 'tex'} + if (cookie.font == 'tex') return; + } + if (jsMath.noImgFonts) {cookie.font = 'unicode'} + if (cookie.font == 'unicode') { + jsMath.Setup.Script('jsMath-fallback-'+jsMath.platform+'.js'); + jsMath.Box.TeXnonfallback = jsMath.Box.TeX; + jsMath.Box.TeX = jsMath.Box.TeXfallback; + return; + } + if (!cookie.print && cookie.printwarn) { + this.PrintMessage( + (jsMath.Browser.alphaPrintBug && jsMath.Controls.cookie.alpha) ? + this.print_message + this.alpha_message : this.print_message); + } + if (jsMath.Browser.waitForImages) { + jsMath.Script.Push(jsMath.Script,"WaitForImage",jsMath.blank); + } + if (cookie.font == 'symbol') { + jsMath.Setup.Script('jsMath-fallback-symbols.js'); + jsMath.Box.TeXnonfallback = jsMath.Box.TeX; + jsMath.Box.TeX = jsMath.Box.TeXfallback; + return; + } + jsMath.Img.SetFont({ + cmr10: ['all'], cmmi10: ['all'], cmsy10: ['all'], + cmex10: ['all'], cmbx10: ['all'], cmti10: ['all'] + }); + jsMath.Img.LoadFont('cm-fonts'); + }, + + /* + * The message for when no TeX fonts. You can eliminate this message + * by including + * + * + * + * in your HTML file, before loading jsMath.js, if you want. But this + * means the user may not know that he or she can get a better version + * of your page. + */ + Message: function (message) { + if (jsMath.Element("Warning")) return; + var div = jsMath.Setup.DIV("Warning",{}); + div.innerHTML = + '
' + + '
' + message + + '
' + + 'jsMath Control Panel' + + '' + + 'Hide this Message' + + '

' + + '
' + + '

'; + }, + + HideMessage: function () { + var message = jsMath.Element("Warning"); + if (message) {message.style.display = "none"} + }, + + PrintMessage: function (message) { + if (jsMath.Element("PrintWarning")) return; + var div = jsMath.Setup.DIV("PrintWarning",{}); + div.innerHTML = + '
' + + '
' + message + '
' + + '
' + + '

'; + }, + + /* + * Register an extra font so jsMath knows about it + */ + Register: function (data,force) { + if (typeof(data) == 'string') {data = {name: data}} + if (!jsMath.Setup.inited && !force) { + this.register[this.register.length] = data; + return; + } + var fontname = data.name; var name = fontname.replace(/10$/,''); + var fontfam = jsMath.TeX.fam.length; + if (data.prefix == null) {data.prefix = ""} + if (!data.style) {data.style = "font-family: "+data.prefix+fontname+", serif"} + if (!data.styles) {data.styles = {}} + if (!data.macros) {data.macros = {}} + /* + * Register font family + */ + jsMath.TeX.fam[fontfam] = fontname; + jsMath.TeX.famName[fontname] = fontfam; + data.macros[name] = ['HandleFont',fontfam]; + jsMath.Add(jsMath.Parser.prototype.macros,data.macros); + /* + * Set up styles + */ + data.styles['.typeset .'+fontname] = data.style; + jsMath.Setup.Styles(data.styles); + if (jsMath.initialized) {jsMath.Script.Push(jsMath.Setup,'TeXfont',fontname)} + /* + * Check for font and give message if missing + */ + var cookie = jsMath.Controls.cookie; + var hasTeXfont = !jsMath.nofonts && + data.test(fontname,data.testChar,data.testFactor,data.prefix); + if (hasTeXfont && cookie.font == 'tex') { + if (data.tex) {data.tex(fontname,fontfam,data)} + return; + } + if (!hasTeXfont && cookie.warn && cookie.font == 'tex' && !jsMath.nofonts) { + if (!cookie.fonts.match("/"+fontname+"/")) { + cookie.fonts += fontname + "/"; jsMath.Controls.SetCookie(0); + if (!jsMath.Element("Warning")) this.Message(this.extra_message); + var extra = jsMath.Element("ExtraFonts"); + if (extra) { + if (extra.innerHTML != "") {extra.innerHTML += ','} + extra.innerHTML += " " + data.prefix+fontname; + } + } + } + if (cookie.font == 'unicode' || jsMath.noImgFonts) { + if (data.fallback) {data.fallback(fontname,fontfam,data)} + return; + } + // Image fonts + var font = {}; + if (cookie.font == 'symbol' && data.symbol != null) { + font[fontname] = data.symbol(fontname,fontfam,data); + } else { + font[fontname] = ['all']; + } + jsMath.Img.SetFont(font); + jsMath.Img.LoadFont(fontname); + if (jsMath.initialized) { + jsMath.Script.Push(jsMath.Img,'Scale'); + jsMath.Script.Push(jsMath.Img,'UpdateFonts'); + } + }, + /* + * If fonts are registered before jsMath.Init() is called, jsMath.em + * will not be available, so they need to be delayed. + */ + LoadRegistered: function () { + var i = 0; + while (i < this.register.length) {this.Register(this.register[i++],1)} + this.register = []; + }, + + /* + * Load a font + */ + Load: function (name) {jsMath.Setup.Script(this.URL(name))}, + URL: function (name) {return jsMath.Img.root+name+'/def.js'} + +}; + +/***************************************************************************/ + +/* + * Implements the jsMath control panel. + * Much of the code is in jsMath-controls.html, which is + * loaded into a hidden IFRAME on demand + */ +jsMath.Controls = { + + // Data stored in the jsMath cookie + cookie: { + scale: 100, + font: 'tex', autofont: 1, scaleImg: 0, alpha: 1, + warn: 1, fonts: '/', printwarn: 1, stayhires: 0, + button: 1, progress: 1, asynch: 0, blank: 0, + print: 0, keep: '0D', global: 'auto', hiddenGlobal: 1 + }, + + cookiePath: '/', // can also set cookieDomain + noCookiePattern: /^(file|mk):$/, // pattern for handling cookies locally + + + /* + * Create the HTML needed for control panel + */ + Init: function () { + this.panel = jsMath.Setup.DIV("panel",{display:'none'},jsMath.fixedDiv); + if (!jsMath.Browser.msieButtonBug) {this.Button()} + else {setTimeout("jsMath.Controls.Button()",500)} + }, + + /* + * Load the control panel + */ + Panel: function () { + jsMath.Translate.Cancel(); + if (this.loaded) {this.Main()} + else {jsMath.Script.delayedLoad(jsMath.root+"jsMath-controls.html")} + }, + + /* + * Create the control panel button + */ + Button: function () { + var button = jsMath.Setup.DIV("button",{},jsMath.fixedDiv); + button.title = ' Open jsMath Control Panel '; + button.innerHTML = + 'jsMath'; + if (!jsMath.Global.isLocal && !jsMath.noShowGlobal) { + button.innerHTML += + 'Global '; + } + if (button.offsetWidth < 30) {button.style.width = "auto"} + if (!this.cookie.button) {button.style.display = "none"} + }, + + /* + * Since MSIE doesn't handle position:float, we need to have the + * window repositioned every time the window scrolls. We do that + * putting the floating elements into a window-sized DIV, but + * absolutely positioned, and then move the DIV. + */ + MoveButton: function () { + jsMath.fixedDiv.style.left = document.body.scrollLeft + 'px'; +// jsMath.fixedDiv.style.top = document.body.scrollTop + 'px'; + jsMath.fixedDiv.style.top = document.body.scrollTop + document.body.clientHeight + 'px'; + jsMath.fixedDiv.style.width = document.body.clientWidth + 'px'; +// jsMath.fixedDiv.style.height = document.body.clientHeight + 'px'; + }, + + /* + * Get the cookie data from the browser + * (for file: references, use url '?' syntax) + */ + GetCookie: function () { + // save the current cookie settings as the defaults + if (this.defaults == null) {this.defaults = {}} + jsMath.Add(this.defaults,this.cookie); this.userSet = {}; + // get the browser's cookie data + var cookies = jsMath.document.cookie; + if (jsMath.window.location.protocol.match(this.noCookiePattern)) { + cookies = this.localGetCookie(); + this.isLocalCookie = 1; + } + if (cookies.match(/jsMath=([^;]+)/)) { + var data = unescape(RegExp.$1).split(/,/); + for (var i = 0; i < data.length; i++) { + var x = data[i].match(/(.*):(.*)/); + if (x[2].match(/^\d+$/)) {x[2] = 1*x[2]} // convert from string + this.cookie[x[1]] = x[2]; + this.userSet[x[1]] = 1; + } + } + }, + localGetCookie: function () { + return jsMath.window.location.search.substr(1); + }, + + /* + * Save the cookie data in the browser + * (for file: urls, append data like CGI reference) + */ + SetCookie: function (warn) { + var cookie = []; + for (var id in this.cookie) { + if (this.defaults[id] == null || this.cookie[id] != this.defaults[id]) + {cookie[cookie.length] = id + ':' + this.cookie[id]} + } + cookie = cookie.join(','); + if (this.isLocalCookie) { + if (warn == 2) {return 'jsMath='+escape(cookie)} + this.localSetCookie(cookie,warn); + } else { + cookie = escape(cookie); + if (cookie == '') {warn = 0} + if (this.cookiePath) {cookie += '; path='+this.cookiePath} + if (this.cookieDomain) {cookie += '; domain='+this.cookieDomain} + if (this.cookie.keep != '0D') { + var ms = { + D: 1000*60*60*24, + W: 1000*60*60*24*7, + M: 1000*60*60*24*30, + Y: 1000*60*60*24*365 + }; + var exp = new Date; + exp.setTime(exp.getTime() + + this.cookie.keep.substr(0,1) * ms[this.cookie.keep.substr(1,1)]); + cookie += '; expires=' + exp.toGMTString(); + } + if (cookie != '') { + jsMath.document.cookie = 'jsMath='+cookie; + var cookies = jsMath.document.cookie; + if (warn && !cookies.match(/jsMath=/)) + {alert("Cookies must be enabled in order to save jsMath options")} + } + } + return null; + }, + localSetCookie: function (cookie,warn) { + if (!warn) return; + var href = String(jsMath.window.location).replace(/\?.*/,""); + if (cookie != '') {href += '?jsMath=' + escape(cookie)} + if (href != jsMath.window.location.href) {this.Reload(href)} + }, + + /* + * Reload the page (with the given URL) + */ + Reload: function (url) { + if (!this.loaded) return; + this.loaded = 0; jsMath.Setup.inited = -100; + jsMath.Global.ClearCache(); + if (url) {jsMath.window.location.replace(url)} + else {jsMath.window.location.reload()} + } + +}; + +/***************************************************************************/ + +/* + * Implements the actions for clicking and double-clicking + * on math formulas + */ +jsMath.Click = { + + /* + * Handle clicking on math to get control panel + */ + CheckClick: function (event) { + if (!event) {event = jsMath.window.event} + if (event.altKey) jsMath.Controls.Panel(); + }, + + /* + * Handle double-click for seeing TeX code + */ + + CheckDblClick: function (event) { + if (!event) {event = jsMath.window.event} + if (!jsMath.Click.DblClick) { + jsMath.Extension.Require('double-click',1); + // Firefox clears the event, so copy it + var tmpEvent = event; event = {}; + for (var id in tmpEvent) {event[id] = tmpEvent[id]} + } + jsMath.Script.Push(jsMath.Click,'DblClick',[event,this.alt]); + } + +}; + +/***************************************************************************/ + +/* + * The TeX font information + */ +jsMath.TeX = { + + // + // The TeX font parameters + // + thinmuskip: 3/18, + medmuskip: 4/18, + thickmuskip: 5/18, + + x_height: .430554, + quad: 1, + num1: .676508, + num2: .393732, + num3: .44373, + denom1: .685951, + denom2: .344841, + sup1: .412892, + sup2: .362892, + sup3: .288888, + sub1: .15, + sub2: .247217, + sup_drop: .386108, + sub_drop: .05, + delim1: 2.39, + delim2: 1.0, + axis_height: .25, + default_rule_thickness: .06, + big_op_spacing1: .111111, + big_op_spacing2: .166666, + big_op_spacing3: .2, + big_op_spacing4: .6, + big_op_spacing5: .1, + + integer: 6553.6, // conversion of em's to TeX internal integer + scriptspace: .05, + nulldelimiterspace: .12, + delimiterfactor: 901, + delimitershortfall: .5, + scale: 1, // scaling factor for font dimensions + + // The TeX math atom types (see Appendix G of the TeXbook) + atom: ['ord', 'op', 'bin', 'rel', 'open', 'close', 'punct', 'ord'], + + // The TeX font families + fam: ['cmr10','cmmi10','cmsy10','cmex10','cmti10','','cmbx10',''], + famName: {cmr10:0, cmmi10:1, cmsy10:2, cmex10:3, cmti10:4, cmbx10:6}, + + // Encoding used by jsMath fonts + encoding: [ + 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', + 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', + + '°', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '·', + 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'µ', '¶', 'ß', + + 'ï', '!', '"', '#', '$', '%', '&', ''', + '(', ')', '*', '+', ',', '-', '.', '/', + + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '[', '\', ']', '^', '_', + + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '{', '|', '}', '~', 'ÿ' + ], + + /* + * The following are the TeX font mappings and metrics. The metric + * information comes directly from the TeX .tfm files. Browser-specific + * adjustments are made to these tables in the Browser.Init() routine + */ + cmr10: [ + [0.625,0.683], [0.833,0.683], [0.778,0.683], [0.694,0.683], + [0.667,0.683], [0.75,0.683], [0.722,0.683], [0.778,0.683], + [0.722,0.683], [0.778,0.683], [0.722,0.683], + [0.583,0.694,0,{ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 14, '108': 15}}], + [0.556,0.694], [0.556,0.694], [0.833,0.694], [0.833,0.694], + + [0.278,0.431], [0.306,0.431,0.194], [0.5,0.694], [0.5,0.694], + [0.5,0.628], [0.5,0.694], [0.5,0.568], [0.75,0.694], + [0.444,0,0.17], [0.5,0.694], [0.722,0.431], [0.778,0.431], + [0.5,0.528,0.0972], [0.903,0.683], [1.01,0.683], [0.778,0.732,0.0486], + + [0.278,0.431,0,{krn: {'108': -0.278, '76': -0.319}}], + [0.278,0.694,0,{lig: {'96': 60}}], + [0.5,0.694], [0.833,0.694,0.194], [0.5,0.75,0.0556], + [0.833,0.75,0.0556], [0.778,0.694], + [0.278,0.694,0,{krn: {'63': 0.111, '33': 0.111}, lig: {'39': 34}}], + [0.389,0.75,0.25], [0.389,0.75,0.25], [0.5,0.75], + [0.778,0.583,0.0833], [0.278,0.106,0.194], + [0.333,0.431,0,{lig: {'45': 123}}], + [0.278,0.106], [0.5,0.75,0.25], + + [0.5,0.644], [0.5,0.644], [0.5,0.644], [0.5,0.644], + [0.5,0.644], [0.5,0.644], [0.5,0.644], [0.5,0.644], + [0.5,0.644], [0.5,0.644], [0.278,0.431], [0.278,0.431,0.194], + [0.278,0.5,0.194], [0.778,0.367,-0.133], [0.472,0.5,0.194], + [0.472,0.694,0,{lig: {'96': 62}}], + + [0.778,0.694], + [0.75,0.683,0,{krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}}], + [0.708,0.683], [0.722,0.683], + [0.764,0.683,0,{krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}}], + [0.681,0.683], + [0.653,0.683,0,{krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}], + [0.785,0.683], [0.75,0.683], [0.361,0.683,0,{krn: {'73': 0.0278}}], + [0.514,0.683], + [0.778,0.683,0,{krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}], + [0.625,0.683,0,{krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}}], + [0.917,0.683], [0.75,0.683], + [0.778,0.683,0,{krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}}], + + [0.681,0.683,0,{krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}}], + [0.778,0.683,0.194], + [0.736,0.683,0,{krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}}], + [0.556,0.683], + [0.722,0.683,0,{krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}}], + [0.75,0.683], + [0.75,0.683,0,{ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}], + [1.03,0.683,0,{ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}], + [0.75,0.683,0,{krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}], + [0.75,0.683,0,{ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}}], + [0.611,0.683], [0.278,0.75,0.25], [0.5,0.694], + [0.278,0.75,0.25], [0.5,0.694], [0.278,0.668], + + [0.278,0.694,0,{lig: {'96': 92}}], + [0.5,0.431,0,{krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}], + [0.556,0.694,0,{krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}], + [0.444,0.431,0,{krn: {'104': -0.0278, '107': -0.0278}}], + [0.556,0.694], [0.444,0.431], + [0.306,0.694,0,{ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}}], + [0.5,0.431,0.194,{ic: 0.0139, krn: {'106': 0.0278}}], + [0.556,0.694,0,{krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}}], + [0.278,0.668], [0.306,0.668,0.194], + [0.528,0.694,0,{krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}}], + [0.278,0.694], + [0.833,0.431,0,{krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}}], + [0.556,0.431,0,{krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}}], + [0.5,0.431,0,{krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}], + + [0.556,0.431,0.194,{krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}], + [0.528,0.431,0.194], [0.392,0.431], [0.394,0.431], + [0.389,0.615,0,{krn: {'121': -0.0278, '119': -0.0278}}], + [0.556,0.431,0,{krn: {'119': -0.0278}}], + [0.528,0.431,0,{ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}}], + [0.722,0.431,0,{ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}}], + [0.528,0.431], + [0.528,0.431,0.194,{ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}}], + [0.444,0.431], [0.5,0.431,0,{ic: 0.0278, lig: {'45': 124}}], + [1,0.431,0,{ic: 0.0278}], [0.5,0.694], [0.5,0.668], [0.5,0.668] + ], + + cmmi10: [ + [0.615,0.683,0,{ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}}], + [0.833,0.683,0,{krn: {'127': 0.167}}], + [0.763,0.683,0,{ic: 0.0278, krn: {'127': 0.0833}}], + [0.694,0.683,0,{krn: {'127': 0.167}}], + [0.742,0.683,0,{ic: 0.0757, krn: {'127': 0.0833}}], + [0.831,0.683,0,{ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}}], + [0.78,0.683,0,{ic: 0.0576, krn: {'127': 0.0833}}], + [0.583,0.683,0,{ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0556}}], + [0.667,0.683,0,{krn: {'127': 0.0833}}], + [0.612,0.683,0,{ic: 0.11, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}}], + [0.772,0.683,0,{ic: 0.0502, krn: {'127': 0.0833}}], + [0.64,0.431,0,{ic: 0.0037, krn: {'127': 0.0278}}], + [0.566,0.694,0.194,{ic: 0.0528, krn: {'127': 0.0833}}], + [0.518,0.431,0.194,{ic: 0.0556}], + [0.444,0.694,0,{ic: 0.0378, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}}], + [0.406,0.431,0,{krn: {'127': 0.0556}}], + + [0.438,0.694,0.194,{ic: 0.0738, krn: {'127': 0.0833}}], + [0.497,0.431,0.194,{ic: 0.0359, krn: {'127': 0.0556}}], + [0.469,0.694,0,{ic: 0.0278, krn: {'127': 0.0833}}], + [0.354,0.431,0,{krn: {'127': 0.0556}}], + [0.576,0.431], [0.583,0.694], + [0.603,0.431,0.194,{krn: {'127': 0.0278}}], + [0.494,0.431,0,{ic: 0.0637, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}}], + [0.438,0.694,0.194,{ic: 0.046, krn: {'127': 0.111}}], + [0.57,0.431,0,{ic: 0.0359}], + [0.517,0.431,0.194,{krn: {'127': 0.0833}}], + [0.571,0.431,0,{ic: 0.0359, krn: {'59': -0.0556, '58': -0.0556}}], + [0.437,0.431,0,{ic: 0.113, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}}], + [0.54,0.431,0,{ic: 0.0359, krn: {'127': 0.0278}}], + [0.596,0.694,0.194,{krn: {'127': 0.0833}}], + [0.626,0.431,0.194,{krn: {'127': 0.0556}}], + + [0.651,0.694,0.194,{ic: 0.0359, krn: {'127': 0.111}}], + [0.622,0.431,0,{ic: 0.0359}], + [0.466,0.431,0,{krn: {'127': 0.0833}}], + [0.591,0.694,0,{krn: {'127': 0.0833}}], + [0.828,0.431,0,{ic: 0.0278}], + [0.517,0.431,0.194,{krn: {'127': 0.0833}}], + [0.363,0.431,0.0972,{ic: 0.0799, krn: {'127': 0.0833}}], + [0.654,0.431,0.194,{krn: {'127': 0.0833}}], + [1,0.367,-0.133], [1,0.367,-0.133], [1,0.367,-0.133], [1,0.367,-0.133], + [0.278,0.464,-0.0363], [0.278,0.464,-0.0363], [0.5,0.465,-0.0347], [0.5,0.465,-0.0347], + + [0.5,0.431], [0.5,0.431], [0.5,0.431], [0.5,0.431,0.194], + [0.5,0.431,0.194], [0.5,0.431,0.194], [0.5,0.644], [0.5,0.431,0.194], + [0.5,0.644], [0.5,0.431,0.194], [0.278,0.106], [0.278,0.106,0.194], + [0.778,0.539,0.0391], + [0.5,0.75,0.25,{krn: {'1': -0.0556, '65': -0.0556, '77': -0.0556, '78': -0.0556, '89': 0.0556, '90': -0.0556}}], + [0.778,0.539,0.0391], [0.5,0.465,-0.0347], + + [0.531,0.694,0,{ic: 0.0556, krn: {'127': 0.0833}}], + [0.75,0.683,0,{krn: {'127': 0.139}}], + [0.759,0.683,0,{ic: 0.0502, krn: {'127': 0.0833}}], + [0.715,0.683,0,{ic: 0.0715, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}], + [0.828,0.683,0,{ic: 0.0278, krn: {'127': 0.0556}}], + [0.738,0.683,0,{ic: 0.0576, krn: {'127': 0.0833}}], + [0.643,0.683,0,{ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}}], + [0.786,0.683,0,{krn: {'127': 0.0833}}], + [0.831,0.683,0,{ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}}], + [0.44,0.683,0,{ic: 0.0785, krn: {'127': 0.111}}], + [0.555,0.683,0,{ic: 0.0962, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.167}}], + [0.849,0.683,0,{ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}}], + [0.681,0.683,0,{krn: {'127': 0.0278}}], + [0.97,0.683,0,{ic: 0.109, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}}], + [0.803,0.683,0,{ic: 0.109, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}], + [0.763,0.683,0,{ic: 0.0278, krn: {'127': 0.0833}}], + + [0.642,0.683,0,{ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}}], + [0.791,0.683,0.194,{krn: {'127': 0.0833}}], + [0.759,0.683,0,{ic: 0.00773, krn: {'127': 0.0833}}], + [0.613,0.683,0,{ic: 0.0576, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}}], + [0.584,0.683,0,{ic: 0.139, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}], + [0.683,0.683,0,{ic: 0.109, krn: {'59': -0.111, '58': -0.111, '61': -0.0556, '127': 0.0278}}], + [0.583,0.683,0,{ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}}], + [0.944,0.683,0,{ic: 0.139, krn: {'59': -0.167, '58': -0.167, '61': -0.111}}], + [0.828,0.683,0,{ic: 0.0785, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}], + [0.581,0.683,0,{ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}}], + [0.683,0.683,0,{ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}}], + [0.389,0.75], [0.389,0.694,0.194], [0.389,0.694,0.194], + [1,0.358,-0.142], [1,0.358,-0.142], + + [0.417,0.694,0,{krn: {'127': 0.111}}], + [0.529,0.431], [0.429,0.694], [0.433,0.431,0,{krn: {'127': 0.0556}}], + [0.52,0.694,0,{krn: {'89': 0.0556, '90': -0.0556, '106': -0.111, '102': -0.167, '127': 0.167}}], + [0.466,0.431,0,{krn: {'127': 0.0556}}], + [0.49,0.694,0.194,{ic: 0.108, krn: {'59': -0.0556, '58': -0.0556, '127': 0.167}}], + [0.477,0.431,0.194,{ic: 0.0359, krn: {'127': 0.0278}}], + [0.576,0.694,0,{krn: {'127': -0.0278}}], [0.345,0.66], + [0.412,0.66,0.194,{ic: 0.0572, krn: {'59': -0.0556, '58': -0.0556}}], + [0.521,0.694,0,{ic: 0.0315}], [0.298,0.694,0,{ic: 0.0197, krn: {'127': 0.0833}}], + [0.878,0.431], [0.6,0.431], [0.485,0.431,0,{krn: {'127': 0.0556}}], + + [0.503,0.431,0.194,{krn: {'127': 0.0833}}], + [0.446,0.431,0.194,{ic: 0.0359, krn: {'127': 0.0833}}], + [0.451,0.431,0,{ic: 0.0278, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}}], + [0.469,0.431,0,{krn: {'127': 0.0556}}], [0.361,0.615,0,{krn: {'127': 0.0833}}], + [0.572,0.431,0,{krn: {'127': 0.0278}}], + [0.485,0.431,0,{ic: 0.0359, krn: {'127': 0.0278}}], + [0.716,0.431,0,{ic: 0.0269, krn: {'127': 0.0833}}], + [0.572,0.431,0,{krn: {'127': 0.0278}}], + [0.49,0.431,0.194,{ic: 0.0359, krn: {'127': 0.0556}}], + [0.465,0.431,0,{ic: 0.044, krn: {'127': 0.0556}}], + [0.322,0.431,0,{krn: {'127': 0.0278}}], + [0.384,0.431,0.194,{krn: {'127': 0.0833}}], + [0.636,0.431,0.194,{krn: {'127': 0.111}}], + [0.5,0.714,0,{ic: 0.154}], [0.278,0.694,0,{ic: 0.399}] + ], + + cmsy10: [ + [0.778,0.583,0.0833], [0.278,0.444,-0.0556], [0.778,0.583,0.0833], + [0.5,0.465,-0.0347], [0.778,0.583,0.0833], [0.5,0.444,-0.0556], + [0.778,0.583,0.0833], [0.778,0.583,0.0833], [0.778,0.583,0.0833], + [0.778,0.583,0.0833], [0.778,0.583,0.0833], [0.778,0.583,0.0833], + [0.778,0.583,0.0833], [1,0.694,0.194], [0.5,0.444,-0.0556], [0.5,0.444,-0.0556], + + [0.778,0.464,-0.0363], [0.778,0.464,-0.0363], [0.778,0.636,0.136], + [0.778,0.636,0.136], [0.778,0.636,0.136], [0.778,0.636,0.136], + [0.778,0.636,0.136], [0.778,0.636,0.136], [0.778,0.367,-0.133], + [0.778,0.483,-0.0169], [0.778,0.539,0.0391], [0.778,0.539,0.0391], + [1,0.539,0.0391], [1,0.539,0.0391], [0.778,0.539,0.0391], [0.778,0.539,0.0391], + + [1,0.367,-0.133], [1,0.367,-0.133], [0.5,0.694,0.194], [0.5,0.694,0.194], + [1,0.367,-0.133], [1,0.694,0.194], [1,0.694,0.194], [0.778,0.464,-0.0363], + [1,0.367,-0.133], [1,0.367,-0.133], [0.611,0.694,0.194], [0.611,0.694,0.194], + [1,0.367,-0.133], [1,0.694,0.194], [1,0.694,0.194], [0.778,0.431], + + [0.275,0.556], [1,0.431], [0.667,0.539,0.0391], [0.667,0.539,0.0391], + [0.889,0.694,0.194], [0.889,0.694,0.194], [0,0.694,0.194], [0,0.367,-0.133], + [0.556,0.694], [0.556,0.694], [0.667,0.431], [0.5,0.75,0.0556], + [0.722,0.694], [0.722,0.694], [0.778,0.694], [0.778,0.694], + + [0.611,0.694], [0.798,0.683,0,{krn: {'48': 0.194}}], + [0.657,0.683,0,{ic: 0.0304, krn: {'48': 0.139}}], + [0.527,0.683,0,{ic: 0.0583, krn: {'48': 0.139}}], + [0.771,0.683,0,{ic: 0.0278, krn: {'48': 0.0833}}], + [0.528,0.683,0,{ic: 0.0894, krn: {'48': 0.111}}], + [0.719,0.683,0,{ic: 0.0993, krn: {'48': 0.111}}], + [0.595,0.683,0.0972,{ic: 0.0593, krn: {'48': 0.111}}], + [0.845,0.683,0,{ic: 0.00965, krn: {'48': 0.111}}], + [0.545,0.683,0,{ic: 0.0738, krn: {'48': 0.0278}}], + [0.678,0.683,0.0972,{ic: 0.185, krn: {'48': 0.167}}], + [0.762,0.683,0,{ic: 0.0144, krn: {'48': 0.0556}}], + [0.69,0.683,0,{krn: {'48': 0.139}}], [1.2,0.683,0,{krn: {'48': 0.139}}], + [0.82,0.683,0,{ic: 0.147, krn: {'48': 0.0833}}], + [0.796,0.683,0,{ic: 0.0278, krn: {'48': 0.111}}], + + [0.696,0.683,0,{ic: 0.0822, krn: {'48': 0.0833}}], + [0.817,0.683,0.0972,{krn: {'48': 0.111}}], + [0.848,0.683,0,{krn: {'48': 0.0833}}], + [0.606,0.683,0,{ic: 0.075, krn: {'48': 0.139}}], + [0.545,0.683,0,{ic: 0.254, krn: {'48': 0.0278}}], + [0.626,0.683,0,{ic: 0.0993, krn: {'48': 0.0833}}], + [0.613,0.683,0,{ic: 0.0822, krn: {'48': 0.0278}}], + [0.988,0.683,0,{ic: 0.0822, krn: {'48': 0.0833}}], + [0.713,0.683,0,{ic: 0.146, krn: {'48': 0.139}}], + [0.668,0.683,0.0972,{ic: 0.0822, krn: {'48': 0.0833}}], + [0.725,0.683,0,{ic: 0.0794, krn: {'48': 0.139}}], + [0.667,0.556], [0.667,0.556], [0.667,0.556], [0.667,0.556], [0.667,0.556], + + [0.611,0.694], [0.611,0.694], [0.444,0.75,0.25], [0.444,0.75,0.25], + [0.444,0.75,0.25], [0.444,0.75,0.25], [0.5,0.75,0.25], [0.5,0.75,0.25], + [0.389,0.75,0.25], [0.389,0.75,0.25], [0.278,0.75,0.25], [0.5,0.75,0.25], + [0.5,0.75,0.25], [0.611,0.75,0.25], [0.5,0.75,0.25], [0.278,0.694,0.194], + + [0.833,0.04,0.96], [0.75,0.683], [0.833,0.683], [0.417,0.694,0.194,{ic: 0.111}], + [0.667,0.556], [0.667,0.556], [0.778,0.636,0.136], [0.778,0.636,0.136], + [0.444,0.694,0.194], [0.444,0.694,0.194], [0.444,0.694,0.194], + [0.611,0.694,0.194], [0.778,0.694,0.13], [0.778,0.694,0.13], + [0.778,0.694,0.13], [0.778,0.694,0.13] + ], + + cmex10: [ + [0.458,0.04,1.16,{n: 16}], [0.458,0.04,1.16,{n: 17}], + [0.417,0.04,1.16,{n: 104}], [0.417,0.04,1.16,{n: 105}], + [0.472,0.04,1.16,{n: 106}], [0.472,0.04,1.16,{n: 107}], + [0.472,0.04,1.16,{n: 108}], [0.472,0.04,1.16,{n: 109}], + [0.583,0.04,1.16,{n: 110}], [0.583,0.04,1.16,{n: 111}], + [0.472,0.04,1.16,{n: 68}], [0.472,0.04,1.16,{n: 69}], + [0.333,0,0.6,{delim: {rep: 12}}], [0.556,0,0.6,{delim: {rep: 13}}], + [0.578,0.04,1.16,{n: 46}], [0.578,0.04,1.16,{n: 47}], + + [0.597,0.04,1.76,{n: 18}], [0.597,0.04,1.76,{n: 19}], + [0.736,0.04,2.36,{n: 32}], [0.736,0.04,2.36,{n: 33}], + [0.528,0.04,2.36,{n: 34}], [0.528,0.04,2.36,{n: 35}], + [0.583,0.04,2.36,{n: 36}], [0.583,0.04,2.36,{n: 37}], + [0.583,0.04,2.36,{n: 38}], [0.583,0.04,2.36,{n: 39}], + [0.75,0.04,2.36,{n: 40}], [0.75,0.04,2.36,{n: 41}], + [0.75,0.04,2.36,{n: 42}], [0.75,0.04,2.36,{n: 43}], + [1.04,0.04,2.36,{n: 44}], [1.04,0.04,2.36,{n: 45}], + + [0.792,0.04,2.96,{n: 48}], [0.792,0.04,2.96,{n: 49}], + [0.583,0.04,2.96,{n: 50}], [0.583,0.04,2.96,{n: 51}], + [0.639,0.04,2.96,{n: 52}], [0.639,0.04,2.96,{n: 53}], + [0.639,0.04,2.96,{n: 54}], [0.639,0.04,2.96,{n: 55}], + [0.806,0.04,2.96,{n: 56}], [0.806,0.04,2.96,{n: 57}], + [0.806,0.04,2.96], [0.806,0.04,2.96], + [1.28,0.04,2.96], [1.28,0.04,2.96], + [0.811,0.04,1.76,{n: 30}], [0.811,0.04,1.76,{n: 31}], + + [0.875,0.04,1.76,{delim: {top: 48, bot: 64, rep: 66}}], + [0.875,0.04,1.76,{delim: {top: 49, bot: 65, rep: 67}}], + [0.667,0.04,1.76,{delim: {top: 50, bot: 52, rep: 54}}], + [0.667,0.04,1.76,{delim: {top: 51, bot: 53, rep: 55}}], + [0.667,0.04,1.76,{delim: {bot: 52, rep: 54}}], + [0.667,0.04,1.76,{delim: {bot: 53, rep: 55}}], + [0.667,0,0.6,{delim: {top: 50, rep: 54}}], + [0.667,0,0.6,{delim: {top: 51, rep: 55}}], + [0.889,0,0.9,{delim: {top: 56, mid: 60, bot: 58, rep: 62}}], + [0.889,0,0.9,{delim: {top: 57, mid: 61, bot: 59, rep: 62}}], + [0.889,0,0.9,{delim: {top: 56, bot: 58, rep: 62}}], + [0.889,0,0.9,{delim: {top: 57, bot: 59, rep: 62}}], + [0.889,0,1.8,{delim: {rep: 63}}], + [0.889,0,1.8,{delim: {rep: 119}}], + [0.889,0,0.3,{delim: {rep: 62}}], + [0.667,0,0.6,{delim: {top: 120, bot: 121, rep: 63}}], + + [0.875,0.04,1.76,{delim: {top: 56, bot: 59, rep: 62}}], + [0.875,0.04,1.76,{delim: {top: 57, bot: 58, rep: 62}}], + [0.875,0,0.6,{delim: {rep: 66}}], [0.875,0,0.6,{delim: {rep: 67}}], + [0.611,0.04,1.76,{n: 28}], [0.611,0.04,1.76,{n: 29}], + [0.833,0,1,{n: 71}], [1.11,0.1,1.5], [0.472,0,1.11,{ic: 0.194, n: 73}], + [0.556,0,2.22,{ic: 0.444}], [1.11,0,1,{n: 75}], [1.51,0.1,1.5], + [1.11,0,1,{n: 77}], [1.51,0.1,1.5], [1.11,0,1,{n: 79}], [1.51,0.1,1.5], + + [1.06,0,1,{n: 88}], [0.944,0,1,{n: 89}], [0.472,0,1.11,{ic: 0.194, n: 90}], + [0.833,0,1,{n: 91}], [0.833,0,1,{n: 92}], [0.833,0,1,{n: 93}], + [0.833,0,1,{n: 94}], [0.833,0,1,{n: 95}], [1.44,0.1,1.5], + [1.28,0.1,1.5], [0.556,0,2.22,{ic: 0.444}], [1.11,0.1,1.5], + [1.11,0.1,1.5], [1.11,0.1,1.5], [1.11,0.1,1.5], [1.11,0.1,1.5], + + [0.944,0,1,{n: 97}], [1.28,0.1,1.5], [0.556,0.722,0,{n: 99}], + [1,0.75,0,{n: 100}], [1.44,0.75], [0.556,0.722,0,{n: 102}], + [1,0.75,0,{n: 103}], [1.44,0.75], [0.472,0.04,1.76,{n: 20}], + [0.472,0.04,1.76,{n: 21}], [0.528,0.04,1.76,{n: 22}], + [0.528,0.04,1.76,{n: 23}], [0.528,0.04,1.76,{n: 24}], + [0.528,0.04,1.76,{n: 25}], [0.667,0.04,1.76,{n: 26}], + [0.667,0.04,1.76,{n: 27}], + + [1,0.04,1.16,{n: 113}], [1,0.04,1.76,{n: 114}], [1,0.04,2.36,{n: 115}], + [1,0.04,2.96,{n: 116}], [1.06,0,1.8,{delim: {top: 118, bot: 116, rep: 117}}], + [1.06,0,0.6], [1.06,0.04,0.56], + [0.778,0,0.6,{delim: {top: 126, bot: 127, rep: 119}}], + [0.667,0,0.6,{delim: {top: 120, rep: 63}}], + [0.667,0,0.6,{delim: {bot: 121, rep: 63}}], + [0.45,0.12], [0.45,0.12], [0.45,0.12], [0.45,0.12], + [0.778,0,0.6,{delim: {top: 126, rep: 119}}], + [0.778,0,0.6,{delim: {bot: 127, rep: 119}}] + ], + + cmti10: [ + [0.627,0.683,0,{ic: 0.133}], [0.818,0.683], [0.767,0.683,0,{ic: 0.094}], + [0.692,0.683], [0.664,0.683,0,{ic: 0.153}], [0.743,0.683,0,{ic: 0.164}], + [0.716,0.683,0,{ic: 0.12}], [0.767,0.683,0,{ic: 0.111}], + [0.716,0.683,0,{ic: 0.0599}], [0.767,0.683,0,{ic: 0.111}], + [0.716,0.683,0,{ic: 0.103}], + [0.613,0.694,0.194,{ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 14, '108': 15}}], + [0.562,0.694,0.194,{ic: 0.103}], [0.588,0.694,0.194,{ic: 0.103}], + [0.882,0.694,0.194,{ic: 0.103}], [0.894,0.694,0.194,{ic: 0.103}], + + [0.307,0.431,0,{ic: 0.0767}], [0.332,0.431,0.194,{ic: 0.0374}], + [0.511,0.694], [0.511,0.694,0,{ic: 0.0969}], [0.511,0.628,0,{ic: 0.083}], + [0.511,0.694,0,{ic: 0.108}], [0.511,0.562,0,{ic: 0.103}], [0.831,0.694], + [0.46,0,0.17], [0.537,0.694,0.194,{ic: 0.105}], [0.716,0.431,0,{ic: 0.0751}], + [0.716,0.431,0,{ic: 0.0751}], [0.511,0.528,0.0972,{ic: 0.0919}], + [0.883,0.683,0,{ic: 0.12}], [0.985,0.683,0,{ic: 0.12}], + [0.767,0.732,0.0486,{ic: 0.094}], + + [0.256,0.431,0,{krn: {'108': -0.256, '76': -0.321}}], + [0.307,0.694,0,{ic: 0.124, lig: {'96': 60}}], + [0.514,0.694,0,{ic: 0.0696}], [0.818,0.694,0.194,{ic: 0.0662}], + [0.769,0.694], [0.818,0.75,0.0556,{ic: 0.136}], + [0.767,0.694,0,{ic: 0.0969}], + [0.307,0.694,0,{ic: 0.124, krn: {'63': 0.102, '33': 0.102}, lig: {'39': 34}}], + [0.409,0.75,0.25,{ic: 0.162}], [0.409,0.75,0.25,{ic: 0.0369}], + [0.511,0.75,0,{ic: 0.149}], [0.767,0.562,0.0567,{ic: 0.0369}], + [0.307,0.106,0.194], [0.358,0.431,0,{ic: 0.0283, lig: {'45': 123}}], + [0.307,0.106], [0.511,0.75,0.25,{ic: 0.162}], + + [0.511,0.644,0,{ic: 0.136}], [0.511,0.644,0,{ic: 0.136}], + [0.511,0.644,0,{ic: 0.136}], [0.511,0.644,0,{ic: 0.136}], + [0.511,0.644,0.194,{ic: 0.136}], [0.511,0.644,0,{ic: 0.136}], + [0.511,0.644,0,{ic: 0.136}], [0.511,0.644,0.194,{ic: 0.136}], + [0.511,0.644,0,{ic: 0.136}], [0.511,0.644,0,{ic: 0.136}], + [0.307,0.431,0,{ic: 0.0582}], [0.307,0.431,0.194,{ic: 0.0582}], + [0.307,0.5,0.194,{ic: 0.0756}], [0.767,0.367,-0.133,{ic: 0.0662}], + [0.511,0.5,0.194], [0.511,0.694,0,{ic: 0.122, lig: {'96': 62}}], + + [0.767,0.694,0,{ic: 0.096}], + [0.743,0.683,0,{krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], + [0.704,0.683,0,{ic: 0.103}], [0.716,0.683,0,{ic: 0.145}], + [0.755,0.683,0,{ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}}], + [0.678,0.683,0,{ic: 0.12}], + [0.653,0.683,0,{ic: 0.133, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}], + [0.774,0.683,0,{ic: 0.0872}], [0.743,0.683,0,{ic: 0.164}], + [0.386,0.683,0,{ic: 0.158}], [0.525,0.683,0,{ic: 0.14}], + [0.769,0.683,0,{ic: 0.145, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}], + [0.627,0.683,0,{krn: {'84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], + [0.897,0.683,0,{ic: 0.164}], [0.743,0.683,0,{ic: 0.164}], + [0.767,0.683,0,{ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}}], + + [0.678,0.683,0,{ic: 0.103, krn: {'65': -0.0767}}], + [0.767,0.683,0.194,{ic: 0.094}], + [0.729,0.683,0,{ic: 0.0387, krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], + [0.562,0.683,0,{ic: 0.12}], + [0.716,0.683,0,{ic: 0.133, krn: {'121': -0.0767, '101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}}], + [0.743,0.683,0,{ic: 0.164}], + [0.743,0.683,0,{ic: 0.184, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}], + [0.999,0.683,0,{ic: 0.184, krn: {'65': -0.0767}}], + [0.743,0.683,0,{ic: 0.158, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}], + [0.743,0.683,0,{ic: 0.194, krn: {'101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}}], + [0.613,0.683,0,{ic: 0.145}], [0.307,0.75,0.25,{ic: 0.188}], + [0.514,0.694,0,{ic: 0.169}], [0.307,0.75,0.25,{ic: 0.105}], + [0.511,0.694,0,{ic: 0.0665}], [0.307,0.668,0,{ic: 0.118}], + + [0.307,0.694,0,{ic: 0.124, lig: {'96': 92}}], [0.511,0.431,0,{ic: 0.0767}], + [0.46,0.694,0,{ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], + [0.46,0.431,0,{ic: 0.0565, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], + [0.511,0.694,0,{ic: 0.103, krn: {'108': 0.0511}}], + [0.46,0.431,0,{ic: 0.0751, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], + [0.307,0.694,0.194,{ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 12, '102': 11, '108': 13}}], + [0.46,0.431,0.194,{ic: 0.0885}], [0.511,0.694,0,{ic: 0.0767}], + [0.307,0.655,0,{ic: 0.102}], [0.307,0.655,0.194,{ic: 0.145}], + [0.46,0.694,0,{ic: 0.108}], [0.256,0.694,0,{ic: 0.103, krn: {'108': 0.0511}}], + [0.818,0.431,0,{ic: 0.0767}], [0.562,0.431,0,{ic: 0.0767, krn: {'39': -0.102}}], + [0.511,0.431,0,{ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], + + [0.511,0.431,0.194,{ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], + [0.46,0.431,0.194,{ic: 0.0885}], + [0.422,0.431,0,{ic: 0.108, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}], + [0.409,0.431,0,{ic: 0.0821}], [0.332,0.615,0,{ic: 0.0949}], + [0.537,0.431,0,{ic: 0.0767}], [0.46,0.431,0,{ic: 0.108}], + [0.664,0.431,0,{ic: 0.108, krn: {'108': 0.0511}}], + [0.464,0.431,0,{ic: 0.12}], [0.486,0.431,0.194,{ic: 0.0885}], + [0.409,0.431,0,{ic: 0.123}], [0.511,0.431,0,{ic: 0.0921, lig: {'45': 124}}], + [1.02,0.431,0,{ic: 0.0921}], [0.511,0.694,0,{ic: 0.122}], + [0.511,0.668,0,{ic: 0.116}], [0.511,0.668,0,{ic: 0.105}] + ], + + cmbx10: [ + [0.692,0.686], [0.958,0.686], [0.894,0.686], [0.806,0.686], + [0.767,0.686], [0.9,0.686], [0.831,0.686], [0.894,0.686], + [0.831,0.686], [0.894,0.686], [0.831,0.686], + [0.671,0.694,0,{ic: 0.109, krn: {'39': 0.109, '63': 0.109, '33': 0.109, '41': 0.109, '93': 0.109}, lig: {'105': 14, '108': 15}}], + [0.639,0.694], [0.639,0.694], [0.958,0.694], [0.958,0.694], + + [0.319,0.444], [0.351,0.444,0.194], [0.575,0.694], [0.575,0.694], + [0.575,0.632], [0.575,0.694], [0.575,0.596], [0.869,0.694], + [0.511,0,0.17], [0.597,0.694], [0.831,0.444], [0.894,0.444], + [0.575,0.542,0.0972], [1.04,0.686], [1.17,0.686], [0.894,0.735,0.0486], + + [0.319,0.444,0,{krn: {'108': -0.319, '76': -0.378}}], + [0.35,0.694,0,{lig: {'96': 60}}], [0.603,0.694], [0.958,0.694,0.194], + [0.575,0.75,0.0556], [0.958,0.75,0.0556], [0.894,0.694], + [0.319,0.694,0,{krn: {'63': 0.128, '33': 0.128}, lig: {'39': 34}}], + [0.447,0.75,0.25], [0.447,0.75,0.25], [0.575,0.75], [0.894,0.633,0.133], + [0.319,0.156,0.194], [0.383,0.444,0,{lig: {'45': 123}}], + [0.319,0.156], [0.575,0.75,0.25], + + [0.575,0.644], [0.575,0.644], [0.575,0.644], [0.575,0.644], + [0.575,0.644], [0.575,0.644], [0.575,0.644], [0.575,0.644], + [0.575,0.644], [0.575,0.644], [0.319,0.444], [0.319,0.444,0.194], + [0.35,0.5,0.194], [0.894,0.391,-0.109], [0.543,0.5,0.194], + [0.543,0.694,0,{lig: {'96': 62}}], + + [0.894,0.694], + [0.869,0.686,0,{krn: {'116': -0.0319, '67': -0.0319, '79': -0.0319, '71': -0.0319, '85': -0.0319, '81': -0.0319, '84': -0.0958, '89': -0.0958, '86': -0.128, '87': -0.128}}], + [0.818,0.686], [0.831,0.686], + [0.882,0.686,0,{krn: {'88': -0.0319, '87': -0.0319, '65': -0.0319, '86': -0.0319, '89': -0.0319}}], + [0.756,0.686], + [0.724,0.686,0,{krn: {'111': -0.0958, '101': -0.0958, '117': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.128, '79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}}], + [0.904,0.686], [0.9,0.686], [0.436,0.686,0,{krn: {'73': 0.0319}}], + [0.594,0.686], + [0.901,0.686,0,{krn: {'79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}}], + [0.692,0.686,0,{krn: {'84': -0.0958, '89': -0.0958, '86': -0.128, '87': -0.128}}], + [1.09,0.686], [0.9,0.686], + [0.864,0.686,0,{krn: {'88': -0.0319, '87': -0.0319, '65': -0.0319, '86': -0.0319, '89': -0.0319}}], + + [0.786,0.686,0,{krn: {'65': -0.0958, '111': -0.0319, '101': -0.0319, '97': -0.0319, '46': -0.0958, '44': -0.0958}}], + [0.864,0.686,0.194], + [0.862,0.686,0,{krn: {'116': -0.0319, '67': -0.0319, '79': -0.0319, '71': -0.0319, '85': -0.0319, '81': -0.0319, '84': -0.0958, '89': -0.0958, '86': -0.128, '87': -0.128}}], + [0.639,0.686], + [0.8,0.686,0,{krn: {'121': -0.0319, '101': -0.0958, '111': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.0958, '117': -0.0958}}], + [0.885,0.686], + [0.869,0.686,0,{ic: 0.016, krn: {'111': -0.0958, '101': -0.0958, '117': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.128, '79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}}], + [1.19,0.686,0,{ic: 0.016, krn: {'111': -0.0958, '101': -0.0958, '117': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.128, '79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}}], + [0.869,0.686,0,{krn: {'79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}}], + [0.869,0.686,0,{ic: 0.0287, krn: {'101': -0.0958, '111': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.0958, '117': -0.0958}}], + [0.703,0.686], [0.319,0.75,0.25], [0.603,0.694], [0.319,0.75,0.25], + [0.575,0.694], [0.319,0.694], + + [0.319,0.694,0,{lig: {'96': 92}}], + [0.559,0.444,0,{krn: {'118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}}], + [0.639,0.694,0,{krn: {'101': 0.0319, '111': 0.0319, '120': -0.0319, '100': 0.0319, '99': 0.0319, '113': 0.0319, '118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}}], + [0.511,0.444,0,{krn: {'104': -0.0319, '107': -0.0319}}], + [0.639,0.694], [0.527,0.444], + [0.351,0.694,0,{ic: 0.109, krn: {'39': 0.109, '63': 0.109, '33': 0.109, '41': 0.109, '93': 0.109}, lig: {'105': 12, '102': 11, '108': 13}}], + [0.575,0.444,0.194,{ic: 0.016, krn: {'106': 0.0319}}], + [0.639,0.694,0,{krn: {'116': -0.0319, '117': -0.0319, '98': -0.0319, '121': -0.0319, '118': -0.0319, '119': -0.0319}}], + [0.319,0.694], [0.351,0.694,0.194], + [0.607,0.694,0,{krn: {'97': -0.0639, '101': -0.0319, '97': -0.0319, '111': -0.0319, '99': -0.0319}}], + [0.319,0.694], + [0.958,0.444,0,{krn: {'116': -0.0319, '117': -0.0319, '98': -0.0319, '121': -0.0319, '118': -0.0319, '119': -0.0319}}], + [0.639,0.444,0,{krn: {'116': -0.0319, '117': -0.0319, '98': -0.0319, '121': -0.0319, '118': -0.0319, '119': -0.0319}}], + [0.575,0.444,0,{krn: {'101': 0.0319, '111': 0.0319, '120': -0.0319, '100': 0.0319, '99': 0.0319, '113': 0.0319, '118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}}], + + [0.639,0.444,0.194,{krn: {'101': 0.0319, '111': 0.0319, '120': -0.0319, '100': 0.0319, '99': 0.0319, '113': 0.0319, '118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}}], + [0.607,0.444,0.194], [0.474,0.444], [0.454,0.444], + [0.447,0.635,0,{krn: {'121': -0.0319, '119': -0.0319}}], + [0.639,0.444,0,{krn: {'119': -0.0319}}], + [0.607,0.444,0,{ic: 0.016, krn: {'97': -0.0639, '101': -0.0319, '97': -0.0319, '111': -0.0319, '99': -0.0319}}], + [0.831,0.444,0,{ic: 0.016, krn: {'101': -0.0319, '97': -0.0319, '111': -0.0319, '99': -0.0319}}], + [0.607,0.444], + [0.607,0.444,0.194,{ic: 0.016, krn: {'111': -0.0319, '101': -0.0319, '97': -0.0319, '46': -0.0958, '44': -0.0958}}], + [0.511,0.444], [0.575,0.444,0,{ic: 0.0319, lig: {'45': 124}}], + [1.15,0.444,0,{ic: 0.0319}], [0.575,0.694], [0.575,0.694], [0.575,0.694] + ] +}; + +/***************************************************************************/ + +/* + * Implement image-based fonts for fallback method + */ +jsMath.Img = { + + // font sizes available + fonts: [50, 60, 70, 85, 100, 120, 144, 173, 207, 249, 298, 358, 430], + + // em widths for the various font size directories + w: {'50': 6.9, '60': 8.3, '70': 9.7, '85': 11.8, '100': 13.9, + '120': 16.7, '144': 20.0, '173': 24.0, '207': 28.8, '249': 34.6, + '298': 41.4, '358': 49.8, '430': 59.8}, + + best: 4, // index of best font size in the fonts list + update: {}, // fonts to update (see UpdateFonts below) + factor: 1, // factor by which to shrink images (for better printing) + loaded: 0, // image fonts are loaded + + // add characters to be drawn using images + SetFont: function (change) { + for (var font in change) { + if (!this.update[font]) {this.update[font] = []} + this.update[font] = this.update[font].concat(change[font]); + } + }, + + /* + * Called by the exta-font definition files to add an image font + * into the mix + */ + AddFont: function (size,def) { + if (!jsMath.Img[size]) {jsMath.Img[size] = {}}; + jsMath.Add(jsMath.Img[size],def); + }, + + /* + * Update font(s) to use image data rather than native fonts + * It looks in the jsMath.Img.update array to find the names + * of the fonts to udpate, and the arrays of character codes + * to set (or 'all' to change every character); + */ + UpdateFonts: function () { + var change = this.update; if (!this.loaded) return; + for (var font in change) { + for (var i = 0; i < change[font].length; i++) { + var c = change[font][i]; + if (c == 'all') {for (c in jsMath.TeX[font]) {jsMath.TeX[font][c].img = {}}} + else {jsMath.TeX[font][c].img = {}} + } + } + this.update = {}; + }, + + /* + * Find the font size that best fits our current font + * (this is the directory name for the img files used + * in some fallback modes). + */ + BestSize: function () { + var w = jsMath.em * this.factor; + var m = this.w[this.fonts[0]]; + for (var i = 1; i < this.fonts.length; i++) { + if (w < (this.w[this.fonts[i]] + 2*m) / 3) {return i-1} + m = this.w[this.fonts[i]]; + } + return i-1; + }, + + /* + * Get the scaling factor for the image fonts + */ + Scale: function () { + if (!this.loaded) return; + this.best = this.BestSize(); + this.em = jsMath.Img.w[this.fonts[this.best]]; + this.scale = (jsMath.em/this.em); + if (Math.abs(this.scale - 1) < .12) {this.scale = 1} + }, + + /* + * Get URL to directory for given font and size, based on the + * user's alpha/plain setting + */ + URL: function (name,size,C) { + var type = (jsMath.Controls.cookie.alpha) ? '/alpha/': '/plain/'; + if (C == null) {C = "def.js"} else {C = 'char'+C+'.png'} + if (size != "") {size += '/'} + return this.root+name+type+size+C; + }, + + /* + * Laod the data for an image font + */ + LoadFont: function (name) { + if (!this.loaded) this.Init(); + jsMath.Setup.Script(this.URL(name,"")); + }, + + /* + * Setup for print mode, and create the hex code table + */ + Init: function () { + if (jsMath.Controls.cookie.print || jsMath.Controls.cookie.stayhires) { + jsMath.Controls.cookie.print = jsMath.Controls.cookie.stayhires; + this.factor *= 3; + if (!jsMath.Controls.isLocalCookie || !jsMath.Global.isLocal) {jsMath.Controls.SetCookie(0)} + if (jsMath.Browser.alphaPrintBug) {jsMath.Controls.cookie.alpha = 0} + } + var codes = '0123456789ABCDEF'; + this.HexCode = []; + for (var i = 0; i < 128; i++) { + var h = Math.floor(i/16); var l = i - 16*h; + this.HexCode[i] = codes.charAt(h)+codes.charAt(l); + } + this.loaded = 1; + } + +}; + +/***************************************************************************/ + +/* + * jsMath.HTML handles creation of most of the HTML needed for + * presenting mathematics in HTML pages. + */ + +jsMath.HTML = { + + /* + * Produce a string version of a measurement in ems, + * showing only a limited number of digits, and + * using 0 when the value is near zero. + */ + Em: function (m) { + if (Math.abs(m) < .000001) {m = 0} + var s = String(m); s = s.replace(/(\.\d\d\d).+/,'$1'); + return s+'em' + }, + + /* + * Create a horizontal space of width w + */ + Spacer: function (w) { + if (w == 0) {return ''}; + return jsMath.Browser.msieSpaceFix+''; + }, + + /* + * Create a blank rectangle of the given size + * If the height is small, it is converted to pixels so that it + * will not disappear at small font sizes. + */ + + Blank: function (w,h,d,isRule) { + var backspace = ''; var style = '' + if (isRule) { + style += 'border-left:'+this.Em(w)+' solid;'; + if (jsMath.Browser.widthAddsBorder) {w = 0}; + } + if (w == 0) { + if (jsMath.Browser.blankWidthBug) { + if (jsMath.Browser.quirks) { + style += 'width:1px;'; + backspace = '' + } else if (!isRule) { + style += 'width:1px;margin-right:-1px;'; + } + } + } else {style += 'width:'+this.Em(w)+';'} + if (d == null) {d = 0} + if (h) { + var H = this.Em(h+d); + if (isRule && h*jsMath.em <= 1.5) {H = "1.5px"; h = 1.5/jsMath.em} + style += 'height:'+H+';'; + } + if (jsMath.Browser.mozInlineBlockBug) {d = -h} + if (jsMath.Browser.msieBorderBug && !isRule) {d -= jsMath.d} + if (d) {style += 'vertical-align:'+this.Em(-d)} + return backspace+''; + }, + + /* + * Create a rule line for fractions, etc. + */ + Rule: function (w,h) { + if (h == null) {h = jsMath.TeX.default_rule_thickness} + return this.Blank(w,h,0,1); + }, + + /* + * Add a tag to activate a specific CSS class + */ + Class: function (tclass,html) { + return ''+html+''; + }, + + /* + * Use a to place some HTML at a specific position. + * (This can be replaced by the ones below to overcome + * some browser-specific bugs.) + */ + Place: function (html,x,y) { + if (Math.abs(x) < .0001) {x = 0} + if (Math.abs(y) < .0001) {y = 0} + if (x || y) { + var span = '' + html + ''; + } + return html; + }, + + /* + * For MSIE on Windows, backspacing must be done in a separate + * , otherwise the contents will be clipped. Netscape + * also doesn't combine vertical and horizontal spacing well. + * Here the x and y positioning are done in separate tags + */ + PlaceSeparateSkips: function (html,x,y,mw,Mw,w) { + if (Math.abs(x) < .0001) {x = 0} + if (Math.abs(y) < .0001) {y = 0} + if (y) { + var lw = 0; var rw = 0; var width = ""; + if (mw != null) { + rw = Mw - w; lw = mw; + width = ' width:'+this.Em(Mw-mw)+';'; + } + html = + this.Spacer(lw-rw) + + '' + + this.Spacer(-lw) + + html + + this.Spacer(rw) + + '' + } + if (x) {html = this.Spacer(x) + html} + return html; + }, + + /* + * Place a SPAN with absolute coordinates + */ + PlaceAbsolute: function (html,x,y,mw,Mw,w) { + if (Math.abs(x) < .0001) {x = 0} + if (Math.abs(y) < .0001) {y = 0} + var leftSpace = ""; var rightSpace = ""; var width = ""; + if (jsMath.Browser.msieRelativeClipBug && mw != null) { + leftSpace = this.Spacer(-mw); x += mw; + rightSpace = this.Spacer(Mw-w); + } + if (jsMath.Browser.operaAbsoluteWidthBug) {width = " width: "+this.Em(w+2)} + html = + '' + + leftSpace + html + rightSpace + + ' ' + // space normalizes line height in script styles + ''; + return html; + }, + + Absolute: function(html,w,h,d,y) { + if (y != "none") { + if (Math.abs(y) < .0001) {y = 0} + html = '' + + html + ' ' // space normalizes line height in script styles + + ''; + } + if (d == "none") {d = 0} + html += this.Blank(w,h-d,d); + if (jsMath.Browser.msieAbsoluteBug) { // for MSIE (Mac) + html = '' + html + ''; + } + html = '' + html + ''; + return html; + } + +}; + + +/***************************************************************************/ + +/* + * jsMath.Box handles TeX's math boxes and jsMath's equivalent of hboxes. + */ + +jsMath.Box = function (format,text,w,h,d) { + if (d == null) {d = jsMath.d} + this.type = 'typeset'; + this.w = w; this.h = h; this.d = d; this.bh = h; this.bd = d; + this.x = 0; this.y = 0; this.mw = 0; this.Mw = w; + this.html = text; this.format = format; +}; + + +jsMath.Add(jsMath.Box,{ + + defaultH: 0, // default height for characters with none specified + + /* + * An empty box + */ + Null: function () {return new jsMath.Box('null','',0,0,0)}, + + /* + * A box containing only text whose class and style haven't been added + * yet (so that we can combine ones with the same styles). It gets + * the text dimensions, if needed. (In general, this has been + * replaced by TeX() below, but is still used in fallback mode.) + */ + Text: function (text,tclass,style,size,a,d) { + var html = jsMath.Typeset.AddClass(tclass,text); + html = jsMath.Typeset.AddStyle(style,size,html); + var BB = jsMath.EmBoxFor(html); var TeX = jsMath.Typeset.TeX(style,size); + var bd = ((tclass == 'cmsy10' || tclass == 'cmex10')? BB.h-TeX.h: TeX.d*BB.h/TeX.hd); + var box = new jsMath.Box('text',text,BB.w,BB.h-bd,bd); + box.style = style; box.size = size; box.tclass = tclass; + if (d != null) {box.d = d*TeX.scale} else {box.d = 0} + if (a == null || a == 1) {box.h = .9*TeX.M_height} + else {box.h = 1.1*TeX.x_height + TeX.scale*a} + return box; + }, + + /* + * Produce a box containing a given TeX character from a given font. + * The box is a text box (like the ones above), so that characters from + * the same font can be combined. + */ + TeX: function (C,font,style,size) { + var c = jsMath.TeX[font][C]; + if (c.d == null) {c.d = 0}; if (c.h == null) {c.h = 0} + if (c.img != null && c.c != '') this.TeXIMG(font,C,jsMath.Typeset.StyleSize(style,size)); + var scale = jsMath.Typeset.TeX(style,size).scale; + var box = new jsMath.Box('text',c.c,c.w*scale,c.h*scale,c.d*scale); + box.style = style; box.size = size; + if (c.tclass) { + box.tclass = c.tclass; + if (c.img) {box.bh = c.img.bh; box.bd = c.img.bd} + else {box.bh = scale*jsMath.h; box.bd = scale*jsMath.d} + } else { + box.tclass = font; + box.bh = scale*jsMath.TeX[font].h; + box.bd = scale*jsMath.TeX[font].d; + if (jsMath.Browser.msieFontBug && box.html.match(/&#/)) { + // hack to avoid font changing back to the default + // font when a unicode reference is not followed + // by a letter or number + box.html += 'x'; + } + } + return box; + }, + + /* + * In fallback modes, handle the fact that we don't have the + * sizes of the characters precomputed + */ + TeXfallback: function (C,font,style,size) { + var c = jsMath.TeX[font][C]; if (!c.tclass) {c.tclass = font} + if (c.img != null) {return this.TeXnonfallback(C,font,style,size)} + if (c.h != null && c.a == null) {c.a = c.h-1.1*jsMath.TeX.x_height} + var a = c.a; var d = c.d; // avoid Firefox warnings + var box = this.Text(c.c,c.tclass,style,size,a,d); + var scale = jsMath.Typeset.TeX(style,size).scale; + if (c.bh != null) { + box.bh = c.bh*scale; + box.bd = c.bd*scale; + } else { + var h = box.bd+box.bh; + var html = jsMath.Typeset.AddClass(box.tclass,box.html); + html = jsMath.Typeset.AddStyle(style,size,html); + box.bd = jsMath.EmBoxFor(html+jsMath.HTML.Blank(1,h)).h - h; + box.bh = h - box.bd; + if (scale == 1) {c.bh = box.bh; c.bd = box.bd} + } + if (jsMath.msieFontBug && box.html.match(/&#/)) + {box.html += 'x'} + return box; + }, + + /* + * Set the character's string to the appropriate image file + */ + TeXIMG: function (font,C,size) { + var c = jsMath.TeX[font][C]; + if (c.img.size != null && c.img.size == size && + c.img.best != null && c.img.best == jsMath.Img.best) return; + var mustScale = (jsMath.Img.scale != 1); + var id = jsMath.Img.best + size - 4; + if (id < 0) {id = 0; mustScale = 1} else + if (id >= jsMath.Img.fonts.length) {id = jsMath.Img.fonts.length-1; mustScale = 1} + var imgFont = jsMath.Img[jsMath.Img.fonts[id]]; + var img = imgFont[font][C]; + var scale = 1/jsMath.Img.w[jsMath.Img.fonts[id]]; + if (id != jsMath.Img.best + size - 4) { + if (c.w != null) {scale = c.w/img[0]} else { + scale *= jsMath.Img.fonts[size]/jsMath.Img.fonts[4] + * jsMath.Img.fonts[jsMath.Img.best]/jsMath.Img.fonts[id]; + } + } + var w = img[0]*scale; var h = img[1]*scale; var d = -img[2]*scale; var v; + var wadjust = (c.w == null || Math.abs(c.w-w) < .01)? "" : " margin-right:"+jsMath.HTML.Em(c.w-w)+';'; + var resize = ""; C = jsMath.Img.HexCode[C]; + if (!mustScale && !jsMath.Controls.cookie.scaleImg) { + if (jsMath.Browser.mozImageSizeBug || 2*w < h || + (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha)) + {resize = "height:"+(img[1]*jsMath.Browser.imgScale)+'px;'} + resize += " width:"+(img[0]*jsMath.Browser.imgScale)+'px;' + v = -img[2]+'px'; + } else { + if (jsMath.Browser.mozImageSizeBug || 2*w < h || + (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha)) + {resize = "height:"+jsMath.HTML.Em(h*jsMath.Browser.imgScale)+';'} + resize += " width:"+jsMath.HTML.Em(w*jsMath.Browser.imgScale)+';' + v = jsMath.HTML.Em(d); + } + var vadjust = (Math.abs(d) < .01 && !jsMath.Browser.valignBug)? + "": " vertical-align:"+v+';'; + var URL = jsMath.Img.URL(font,jsMath.Img.fonts[id],C); + if (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha) { + c.c = ''; + } else { + c.c = ''; + } + c.tclass = "normal"; + c.img.bh = h+d; c.img.bd = -d; + c.img.size = size; c.img.best = jsMath.Img.best; + }, + + /* + * A box containing a spacer of a specific width + */ + Space: function (w) { + return new jsMath.Box('html',jsMath.HTML.Spacer(w),w,0,0); + }, + + /* + * A box containing a horizontal rule + */ + Rule: function (w,h) { + if (h == null) {h = jsMath.TeX.default_rule_thickness} + var html = jsMath.HTML.Rule(w,h); + return new jsMath.Box('html',html,w,h,0); + }, + + /* + * Get a character from a TeX font, and make sure that it has + * its metrics specified. + */ + GetChar: function (code,font) { + var c = jsMath.TeX[font][code]; + if (c.img != null) {this.TeXIMG(font,code,4)} + if (c.tclass == null) {c.tclass = font} + if (!c.computedW) { + c.w = jsMath.EmBoxFor(jsMath.Typeset.AddClass(c.tclass,c.c)).w; + if (c.h == null) {c.h = jsMath.Box.defaultH}; if (c.d == null) {c.d = 0} + c.computedW = 1; + } + return c; + }, + + /* + * Locate the TeX delimiter character that matches a given height. + * Return the character, font, style and actual height used. + */ + DelimBestFit: function (H,c,font,style) { + if (c == 0 && font == 0) return null; + var C; var h; font = jsMath.TeX.fam[font]; + var isSS = (style.charAt(1) == 'S'); + var isS = (style.charAt(0) == 'S'); + while (c != null) { + C = jsMath.TeX[font][c]; + if (C.h == null) {C.h = jsMath.Box.defaultH}; if (C.d == null) {C.d = 0} + h = C.h+C.d; + if (C.delim) {return [c,font,'',H]} + if (isSS && .5*h >= H) {return [c,font,'SS',.5*h]} + if (isS && .7*h >= H) {return [c,font,'S',.7*h]} + if (h >= H || C.n == null) {return [c,font,'T',h]} + c = C.n; + } + return null; + }, + + /* + * Create the HTML needed for a stretchable delimiter of a given height, + * either centered or not. This version uses relative placement (i.e., + * backspaces, not line-breaks). This works with more browsers, but + * if the font size changes, the backspacing may not be right, so the + * delimiters may become jagged. + */ + DelimExtendRelative: function (H,c,font,a,nocenter) { + var C = jsMath.TeX[font][c]; + var top = this.GetChar(C.delim.top? C.delim.top: C.delim.rep,font); + var rep = this.GetChar(C.delim.rep,font); + var bot = this.GetChar(C.delim.bot? C.delim.bot: C.delim.rep,font); + var ext = jsMath.Typeset.AddClass(rep.tclass,rep.c); + var w = rep.w; var h = rep.h+rep.d + var y; var Y; var html; var dx; var i; var n; + if (C.delim.mid) {// braces + var mid = this.GetChar(C.delim.mid,font); + n = Math.ceil((H-(top.h+top.d)-(mid.h+mid.d)-(bot.h+bot.d))/(2*(rep.h+rep.d))); + H = 2*n*(rep.h+rep.d) + (top.h+top.d) + (mid.h+mid.d) + (bot.h+bot.d); + if (nocenter) {y = 0} else {y = H/2+a}; Y = y; + html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h) + + jsMath.HTML.Place(jsMath.Typeset.AddClass(bot.tclass,bot.c),-(top.w+bot.w)/2,y-(H-bot.d)) + + jsMath.HTML.Place(jsMath.Typeset.AddClass(mid.tclass,mid.c),-(bot.w+mid.w)/2,y-(H+mid.h-mid.d)/2); + dx = (w-mid.w)/2; if (Math.abs(dx) < .0001) {dx = 0} + if (dx) {html += jsMath.HTML.Spacer(dx)} + y -= top.h+top.d + rep.h; + for (i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)} + y -= H/2 - rep.h/2; + for (i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)} + } else {// everything else + n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d))/(rep.h+rep.d)); + // make sure two-headed arrows have an extender + if (top.h+top.d < .9*(rep.h+rep.d)) {n = Math.max(1,n)} + H = n*(rep.h+rep.d) + (top.h+top.d) + (bot.h+bot.d); + if (nocenter) {y = 0} else {y = H/2+a}; Y = y; + html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h) + dx = (w-top.w)/2; if (Math.abs(dx) < .0001) {dx = 0} + if (dx) {html += jsMath.HTML.Spacer(dx)} + y -= top.h+top.d + rep.h; + for (i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)} + html += jsMath.HTML.Place(jsMath.Typeset.AddClass(bot.tclass,bot.c),-(w+bot.w)/2,Y-(H-bot.d)); + } + if (nocenter) {h = top.h} else {h = H/2+a} + var box = new jsMath.Box('html',html,rep.w,h,H-h); + box.bh = jsMath.TeX[font].h; box.bd = jsMath.TeX[font].d; + return box; + }, + + /* + * Create the HTML needed for a stretchable delimiter of a given height, + * either centered or not. This version uses absolute placement (i.e., + * line-breaks, not backspacing). This gives more reliable results, + * but doesn't work with all browsers. + */ + DelimExtendAbsolute: function (H,c,font,a,nocenter) { + var Font = jsMath.TeX[font]; + var C = Font[c]; var html; + var top = this.GetChar(C.delim.top? C.delim.top: C.delim.rep,font); + var rep = this.GetChar(C.delim.rep,font); + var bot = this.GetChar(C.delim.bot? C.delim.bot: C.delim.rep,font); + var n; var h; var y; var ext; var i; + + if (C.delim.mid) {// braces + var mid = this.GetChar(C.delim.mid,font); + n = Math.ceil((H-(top.h+top.d)-(mid.h+mid.d-.05)-(bot.h+bot.d-.05))/(2*(rep.h+rep.d-.05))); + H = 2*n*(rep.h+rep.d-.05) + (top.h+top.d) + (mid.h+mid.d-.05) + (bot.h+bot.d-.05); + + html = jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(top.tclass,top.c),0,0); + h = rep.h+rep.d - .05; y = top.d-.05 + rep.h; + ext = jsMath.Typeset.AddClass(font,rep.c) + for (i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)} + html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(mid.tclass,mid.c),0,y+n*h-rep.h+mid.h); + y += n*h + mid.h+mid.d - .05; + for (i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)} + html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(bot.tclass,bot.c),0,y+n*h-rep.h+bot.h); + } else {// all others + n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d-.05))/(rep.h+rep.d-.05)); + H = n*(rep.h+rep.d-.05) + (top.h+top.d) + (bot.h+bot.d-.05); + + html = jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(top.tclass,top.c),0,0); + h = rep.h+rep.d-.05; y = top.d-.05 + rep.h; + ext = jsMath.Typeset.AddClass(rep.tclass,rep.c); + for (i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)} + html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(bot.tclass,bot.c),0,y+n*h-rep.h+bot.h); + } + + var w = top.w; + if (nocenter) {h = top.h; y = 0} else {h = H/2 + a; y = h - top.h} + html = jsMath.HTML.Absolute(html,w,Font.h,"none",-y); + var box = new jsMath.Box('html',html,rep.w,h,H-h); + box.bh = jsMath.TeX[font].h; box.bd = jsMath.TeX[font].d; + return box; + }, + + /* + * Get the HTML for a given delimiter of a given height. + * It will return either a single character, if one exists, or the + * more complex HTML needed for a stretchable delimiter. + */ + Delimiter: function (H,delim,style,nocenter) { + var size = 4; //### pass this? + var TeX = jsMath.Typeset.TeX(style,size); + if (!delim) {return this.Space(TeX.nulldelimiterspace)} + var CFSH = this.DelimBestFit(H,delim[2],delim[1],style); + if (CFSH == null || CFSH[3] < H) + {CFSH = this.DelimBestFit(H,delim[4],delim[3],style)} + if (CFSH == null) {return this.Space(TeX.nulldelimiterspace)} + if (CFSH[2] == '') + {return this.DelimExtend(H,CFSH[0],CFSH[1],TeX.axis_height,nocenter)} + var box = jsMath.Box.TeX(CFSH[0],CFSH[1],CFSH[2],size).Styled(); + if (!nocenter) {box.y = -((box.h+box.d)/2 - box.d - TeX.axis_height)} + if (Math.abs(box.y) < .0001) {box.y = 0} + if (box.y) {box = jsMath.Box.SetList([box],CFSH[2],size)} + return box; + }, + + /* + * Get a character by its TeX charcode, and make sure its width + * is specified. + */ + GetCharCode: function (code) { + var font = jsMath.TeX.fam[code[0]]; + var Font = jsMath.TeX[font]; + var c = Font[code[1]]; + if (c.img != null) {this.TeXIMG(font,code[1],4)} + if (c.w == null) {c.w = jsMath.EmBoxFor(jsMath.Typeset.AddClass(c.tclass,c.c)).w} + if (c.font == null) {c.font = font} + return c; + }, + + /* + * Add the class to the html, and use the font if there isn't one + * specified already + */ + + AddClass: function (tclass,html,font) { + if (tclass == null) {tclass = font} + return jsMath.Typeset.AddClass(tclass,html); + }, + + /* + * Create the HTML for an alignment (e.g., array or matrix) + * Since the widths are not really accurate (they are based on pixel + * widths not the sub-pixel widths of the actual characters), there + * is some drift involved. We lay out the table column by column + * to help reduce the problem. + * + * ### still need to allow users to specify row and column attributes, + * and do things like \span and \multispan ### + */ + LayoutRelative: function (size,table,align,cspacing,rspacing,vspace,useStrut,addWidth) { + if (align == null) {align = []} + if (cspacing == null) {cspacing = []} + if (rspacing == null) {rspacing = []} + if (useStrut == null) {useStrut = 1} + if (addWidth == null) {addWidth = 1} + + // get row and column maximum dimensions + var scale = jsMath.sizes[size]/100; + var W = []; var H = []; var D = []; + var unset = -1000; var bh = unset; var bd = unset; + var i; var j; var row; + for (i = 0; i < table.length; i++) { + if (rspacing[i] == null) {rspacing[i] = 0} + row = table[i]; + H[i] = useStrut*jsMath.h*scale; D[i] = useStrut*jsMath.d*scale; + for (j = 0; j < row.length; j++) { + row[j] = row[j].Remeasured(); + if (row[j].h > H[i]) {H[i] = row[j].h} + if (row[j].d > D[i]) {D[i] = row[j].d} + if (j >= W.length) {W[j] = row[j].w} + else if (row[j].w > W[j]) {W[j] = row[j].w} + if (row[j].bh > bh) {bh = row[j].bh} + if (row[j].bd > bd) {bd = row[j].bd} + } + } + if (rspacing[table.length] == null) {rspacing[table.length] = 0} + if (bh == unset) {bh = 0}; if (bd == unset) {bd = 0} + + // lay out the columns + var HD = useStrut*(jsMath.hd-.01)*scale; + var dy = (vspace || 1) * scale/6; + var html = ''; var pW = 0; var cW = 0; + var w; var h; var y; + var box; var mlist; var entry; + for (j = 0; j < W.length; j++) { + mlist = []; y = -H[0]-rspacing[0]; pW = 0; + for (i = 0; i < table.length; i++) { + entry = table[i][j]; + if (entry && entry.format != 'null') { + if (align[j] == 'l') {w = 0} else + if (align[j] == 'r') {w = W[j] - entry.w} else + {w = (W[j] - entry.w)/2} + entry.x = w - pW; pW = entry.w + w; entry.y = y; + mlist[mlist.length] = entry; + } + if (i+1 < table.length) {y -= Math.max(HD,D[i]+H[i+1]) + dy + rspacing[i+1]} + } + if (cspacing[j] == null) cspacing[j] = scale; + if (mlist.length > 0) { + box = jsMath.Box.SetList(mlist,'T',size); + html += jsMath.HTML.Place(box.html,cW,0); + cW = W[j] - box.w + cspacing[j]; + } else {cW += cspacing[j]} + } + + // get the full width and height + w = -cspacing[W.length-1]; y = (H.length-1)*dy + rspacing[0]; + for (i = 0; i < W.length; i++) {w += W[i] + cspacing[i]} + for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i]) + rspacing[i+1]} + h = y/2 + jsMath.TeX.axis_height; var d = y-h; + + // adjust the final row width, and vcenter the table + // (add 1/6em at each side for the \,) + html += jsMath.HTML.Spacer(cW-cspacing[W.length-1] + addWidth*scale/6); + html = jsMath.HTML.Place(html,addWidth*scale/6,h); + box = new jsMath.Box('html',html,w+addWidth*scale/3,h,d); + box.bh = bh; box.bd = bd; + return box; + }, + + /* + * Create the HTML for an alignment (e.g., array or matrix) + * Use absolute position for elements in the array. + * + * ### still need to allow users to specify row and column attributes, + * and do things like \span and \multispan ### + */ + LayoutAbsolute: function (size,table,align,cspacing,rspacing,vspace,useStrut,addWidth) { + if (align == null) {align = []} + if (cspacing == null) {cspacing = []} + if (rspacing == null) {rspacing = []} + if (useStrut == null) {useStrut = 1} + if (addWidth == null) {addWidth = 1} + // get row and column maximum dimensions + var scale = jsMath.sizes[size]/100; + var HD = useStrut*(jsMath.hd-.01)*scale; + var dy = (vspace || 1) * scale/6; + var W = []; var H = []; var D = []; + var w = 0; var h; var x; var y; + var i; var j; var row; + for (i = 0; i < table.length; i++) { + if (rspacing[i] == null) {rspacing[i] = 0} + row = table[i]; + H[i] = useStrut*jsMath.h*scale; D[i] = useStrut*jsMath.d*scale; + for (j = 0; j < row.length; j++) { + row[j] = row[j].Remeasured(); + if (row[j].h > H[i]) {H[i] = row[j].h} + if (row[j].d > D[i]) {D[i] = row[j].d} + if (j >= W.length) {W[j] = row[j].w} + else if (row[j].w > W[j]) {W[j] = row[j].w} + } + } + if (rspacing[table.length] == null) {rspacing[table.length] = 0} + + // get the height and depth of the centered table + y = (H.length-1)*dy + rspacing[0]; + for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i]) + rspacing[i+1]} + h = y/2 + jsMath.TeX.axis_height; var d = y - h; + + // lay out the columns + var html = ''; var entry; w = addWidth*scale/6; + for (j = 0; j < W.length; j++) { + y = H[0]-h + rspacing[0]; + for (i = 0; i < table.length; i++) { + entry = table[i][j]; + if (entry && entry.format != 'null') { + if (align[j] && align[j] == 'l') {x = 0} else + if (align[j] && align[j] == 'r') {x = W[j] - entry.w} else + {x = (W[j] - entry.w)/2} + html += jsMath.HTML.PlaceAbsolute(entry.html,w+x, + y-Math.max(0,entry.bh-jsMath.h*scale), + entry.mw,entry.Mw,entry.w); + } + if (i+1 < table.length) {y += Math.max(HD,D[i]+H[i+1]) + dy + rspacing[i+1]} + } + if (cspacing[j] == null) cspacing[j] = scale; + w += W[j] + cspacing[j]; + } + + // get the full width + w = -cspacing[W.length-1]+addWidth*scale/3; + for (i = 0; i < W.length; i++) {w += W[i] + cspacing[i]} + + html = jsMath.HTML.Spacer(addWidth*scale/6)+html+jsMath.HTML.Spacer(addWidth*scale/6); + if (jsMath.Browser.spanHeightVaries) {y = h-jsMath.h} else {y = 0} + html = jsMath.HTML.Absolute(html,w,h+d,d,y); + var box = new jsMath.Box('html',html,w+addWidth*scale/3,h,d); + return box; + }, + + /* + * Look for math within \hbox and other non-math text + */ + InternalMath: function (text,size) { + if (!jsMath.safeHBoxes) {text = text.replace(/@\(([^)]*)\)/g,'<$1>')} + if (!text.match(/\$|\\\(/)) + {return this.Text(this.safeHTML(text),'normal','T',size).Styled()} + + var i = 0; var k = 0; var c; var match = ''; + var mlist = []; var parse, s; + while (i < text.length) { + c = text.charAt(i++); + if (c == '$') { + if (match == '$') { + parse = jsMath.Parse(text.slice(k,i-1),null,size); + if (parse.error) { + mlist[mlist.length] = this.Text(parse.error,'error','T',size,1,.2); + } else { + parse.Atomize(); + mlist[mlist.length] = parse.mlist.Typeset('T',size).Styled(); + } + match = ''; k = i; + } else { + s = this.safeHTML(text.slice(k,i-1)); + mlist[mlist.length] = this.Text(s,'normal','T',size,1,.2); + match = '$'; k = i; + } + } else if (c == '\\') { + c = text.charAt(i++); + if (c == '(' && match == '') { + s = this.safeHTML(text.slice(k,i-2)); + mlist[mlist.length] = this.Text(s,'normal','T',size,1,.2); + match = ')'; k = i; + } else if (c == ')' && match == ')') { + parse = jsMath.Parse(text.slice(k,i-2),null,size); + if (parse.error) { + mlist[mlist.length] = this.Text(parse.error,'error','T',size,1,.2); + } else { + parse.Atomize(); + mlist[mlist.length] = parse.mlist.Typeset('T',size).Styled(); + } + match = ''; k = i; + } + } + } + s = this.safeHTML(text.slice(k)); + mlist[mlist.length] = this.Text(s,'normal','T',size,1,.2); + return this.SetList(mlist,'T',size); + }, + + /* + * Quote HTML characters if we are in safe mode + */ + safeHTML: function (s) { + if (jsMath.safeHBoxes) { + s = s.replace(/&/g,'&') + .replace(//g,'>'); + } + return s; + }, + + /* + * Convert an abitrary box to a typeset box. I.e., make an + * HTML version of the contents of the box, at its desired (x,y) + * position. + */ + Set: function (box,style,size,addstyle) { + if (box && box.type) { + if (box.type == 'typeset') {return box} + if (box.type == 'mlist') { + box.mlist.Atomize(style,size); + return box.mlist.Typeset(style,size); + } + if (box.type == 'text') { + box = this.Text(box.text,box.tclass,style,size,box.ascend||null,box.descend||null); + if (addstyle != 0) {box.Styled()} + return box; + } + box = this.TeX(box.c,box.font,style,size); + if (addstyle != 0) {box.Styled()} + return box; + } + return jsMath.Box.Null(); + }, + + /* + * Convert a list of boxes to a single typeset box. I.e., finalize + * the HTML for the list of boxes, properly spaced and positioned. + */ + SetList: function (boxes,style,size) { + var mlist = []; var box; + for (var i = 0; i < boxes.length; i++) { + box = boxes[i]; + if (box.type == 'typeset') {box = jsMath.mItem.Typeset(box)} + mlist[mlist.length] = box; + } + var typeset = new jsMath.Typeset(mlist); + return typeset.Typeset(style,size); + } + +}); + + +jsMath.Package(jsMath.Box,{ + + /* + * Add the class and style to a text box (i.e., finalize the + * unpositioned HTML for the box). + */ + Styled: function () { + if (this.format == 'text') { + this.html = jsMath.Typeset.AddClass(this.tclass,this.html); + this.html = jsMath.Typeset.AddStyle(this.style,this.size,this.html); + delete this.tclass; delete this.style; + this.format = 'html'; + } + return this; + }, + + /* + * Recompute the box width to make it more accurate. + */ + Remeasured: function () { + if (this.w > 0) { + var w = this.w; this.w = jsMath.EmBoxFor(this.html).w; + if (this.w > this.Mw) {this.Mw = this.w} + w = this.w/w; if (Math.abs(w-1) > .05) {this.h *= w; this.d *= w} + } + return this; + } + +}); + + +/***************************************************************************/ + +/* + * mItems are the building blocks of mLists (math lists) used to + * store the information about a mathematical expression. These are + * basically the items listed in the TeXbook in Appendix G (plus some + * minor extensions). + */ +jsMath.mItem = function (type,def) { + this.type = type; + jsMath.Add(this,def); +} + +jsMath.Add(jsMath.mItem,{ + + /* + * A general atom (given a nucleus for the atom) + */ + Atom: function (type,nucleus) { + return new jsMath.mItem(type,{atom: 1, nuc: nucleus}); + }, + + /* + * An atom whose nucleus is a piece of text, in a given + * class, with a given additional height and depth + */ + TextAtom: function (type,text,tclass,a,d) { + var atom = new jsMath.mItem(type,{ + atom: 1, + nuc: { + type: 'text', + text: text, + tclass: tclass + } + }); + if (a != null) {atom.nuc.ascend = a} + if (d != null) {atom.nuc.descend = d} + return atom; + }, + + /* + * An atom whose nucleus is a TeX character in a specific font + */ + TeXAtom: function (type,c,font) { + return new jsMath.mItem(type,{ + atom: 1, + nuc: { + type: 'TeX', + c: c, + font: font + } + }); + }, + + /* + * A generalized fraction atom, with given delimiters, rule + * thickness, and a numerator and denominator. + */ + Fraction: function (name,num,den,thickness,left,right) { + return new jsMath.mItem('fraction',{ + from: name, num: num, den: den, + thickness: thickness, left: left, right: right + }); + }, + + /* + * An atom that inserts some glue + */ + Space: function (w) {return new jsMath.mItem('space',{w: w})}, + + /* + * An atom that contains a typeset box (like an hbox or vbox) + */ + Typeset: function (box) {return new jsMath.mItem('ord',{atom:1, nuc: box})}, + + /* + * An atom that contains some finished HTML (acts like a typeset box) + */ + HTML: function (html) {return new jsMath.mItem('html',{html: html})} + +}); + +/***************************************************************************/ + +/* + * mLists are lists of mItems, and encode the contents of + * mathematical expressions and sub-expressions. They act as + * the expression "stack" as the mathematics is parsed, and + * contain some state information, like the position of the + * most recent open paren and \over command, and the current font. + */ +jsMath.mList = function (list,font,size,style) { + if (list) {this.mlist = list} else {this.mlist = []} + if (style == null) {style = 'T'}; if (size == null) {size = 4} + this.data = {openI: null, overI: null, overF: null, + font: font, size: size, style: style}; + this.init = {size: size, style: style}; +} + +jsMath.Package(jsMath.mList,{ + + /* + * Add an mItem to the list + */ + Add: function (box) {return (this.mlist[this.mlist.length] = box)}, + + /* + * Get the i-th mItem from the list + */ + Get: function (i) {return this.mlist[i]}, + + /* + * Get the length of the list + */ + Length: function() {return this.mlist.length}, + + /* + * Get the tail mItem of the list + */ + Last: function () { + if (this.mlist.length == 0) {return null} + return this.mlist[this.mlist.length-1] + }, + + /* + * Get a sublist of an mList + */ + Range: function (i,j) { + if (j == null) {j = this.mlist.length} + return new jsMath.mList(this.mlist.slice(i,j+1)); + }, + + /* + * Remove a range of mItems from the list. + */ + Delete: function (i,j) { + if (j == null) {j = i} + if (this.mlist.splice) {this.mlist.splice(i,j-i+1)} else { + var mlist = []; + for (var k = 0; k < this.mlist.length; k++) + {if (k < i || k > j) {mlist[mlist.length] = this.mlist[k]}} + this.mlist = mlist; + } + }, + + /* + * Add an open brace and maintain the stack information + * about the previous open brace so we can recover it + * when this one os closed. + */ + Open: function (left) { + var box = this.Add(new jsMath.mItem('boundary',{data: this.data})); + var olddata = this.data; + this.data = {}; for (var i in olddata) {this.data[i] = olddata[i]} + delete this.data.overI; delete this.data.overF; + this.data.openI = this.mlist.length-1; + if (left != null) {box.left = left} + return box; + }, + + /* + * Attempt to close a brace. Recover the stack information + * about previous open braces and \over commands. If there was an + * \over (or \above, etc) in this set of braces, create a fraction + * atom from the two halves, otherwise create an inner or ord + * from the contents of the braces. + * Remove the braced material from the list and add the newly + * created atom (the fraction, inner or ord). + */ + Close: function (right) { + if (right != null) {right = new jsMath.mItem('boundary',{right: right})} + var atom; var open = this.data.openI; + var over = this.data.overI; var from = this.data.overF; + this.data = this.mlist[open].data; + if (over) { + atom = jsMath.mItem.Fraction(from.name, + {type: 'mlist', mlist: this.Range(open+1,over-1)}, + {type: 'mlist', mlist: this.Range(over)}, + from.thickness,from.left,from.right); + if (right) { + var mlist = new jsMath.mList([this.mlist[open],atom,right]); + atom = jsMath.mItem.Atom('inner',{type: 'mlist', mlist: mlist}); + } + } else { + var openI = open+1; if (right) {this.Add(right); openI--} + atom = jsMath.mItem.Atom((right)?'inner':'ord', + {type: 'mlist', mlist: this.Range(openI)}); + } + this.Delete(open,this.Length()); + return this.Add(atom); + }, + + /* + * Create a generalized fraction from an mlist that + * contains an \over (or \above, etc). + */ + Over: function () { + var over = this.data.overI; var from = this.data.overF; + var atom = jsMath.mItem.Fraction(from.name, + {type: 'mlist', mlist: this.Range(open+1,over-1)}, + {type: 'mlist', mlist: this.Range(over)}, + from.thickness,from.left,from.right); + this.mlist = [atom]; + }, + + /* + * Take a raw mList (that has been produced by parsing some TeX + * expression), and perform the modifications outlined in + * Appendix G of the TeXbook. + */ + Atomize: function (style,size) { + var mitem; var prev = ''; + this.style = style; this.size = size; + for (var i = 0; i < this.mlist.length; i++) { + mitem = this.mlist[i]; mitem.delta = 0; + if (mitem.type == 'choice') + {this.mlist = this.Atomize.choice(this.style,mitem,i,this.mlist); i--} + else if (this.Atomize[mitem.type]) { + var f = this.Atomize[mitem.type]; // Opera needs separate name + f(this.style,this.size,mitem,prev,this,i); + } + prev = mitem; + } + if (mitem && mitem.type == 'bin') {mitem.type = 'ord'} + if (this.mlist.length >= 2 && mitem.type == 'boundary' && + this.mlist[0].type == 'boundary') {this.AddDelimiters(style,size)} + }, + + /* + * For a list that has boundary delimiters as its first and last + * entries, we replace the boundary atoms by open and close + * atoms whose nuclii are the specified delimiters properly sized + * for the contents of the list. (Rule 19) + */ + AddDelimiters: function(style,size) { + var unset = -10000; var h = unset; var d = unset; + for (var i = 0; i < this.mlist.length; i++) { + var mitem = this.mlist[i]; + if (mitem.atom || mitem.type == 'box') { + h = Math.max(h,mitem.nuc.h+mitem.nuc.y); + d = Math.max(d,mitem.nuc.d-mitem.nuc.y); + } + } + var TeX = jsMath.TeX; var a = jsMath.Typeset.TeX(style,size).axis_height; + var delta = Math.max(h-a,d+a); + var H = Math.max(Math.floor(TeX.integer*delta/500)*TeX.delimiterfactor, + TeX.integer*(2*delta-TeX.delimitershortfall))/TeX.integer; + var left = this.mlist[0]; var right = this.mlist[this.mlist.length-1]; + left.nuc = jsMath.Box.Delimiter(H,left.left,style); + right.nuc = jsMath.Box.Delimiter(H,right.right,style); + left.type = 'open'; left.atom = 1; delete left.left; + right.type = 'close'; right.atom = 1; delete right.right; + }, + + /* + * Typeset a math list to produce final HTML for the list. + */ + Typeset: function (style,size) { + var typeset = new jsMath.Typeset(this.mlist); + return typeset.Typeset(style,size); + } + +}); + + +/* + * These routines implement the main rules given in Appendix G of the + * TeXbook + */ + +jsMath.Add(jsMath.mList.prototype.Atomize,{ + + /* + * Handle \displaystyle, \textstyle, etc. + */ + style: function (style,size,mitem,prev,mlist) { + mlist.style = mitem.style; + }, + + /* + * Handle \tiny, \small, etc. + */ + size: function (style,size,mitem,prev,mlist) { + mlist.size = mitem.size; + }, + + /* + * Create empty boxes of the proper sizes for the various + * phantom-type commands + */ + phantom: function (style,size,mitem) { + var box = mitem.nuc = jsMath.Box.Set(mitem.phantom,style,size); + if (mitem.h) {box.Remeasured(); box.html = jsMath.HTML.Spacer(box.w)} + else {box.html = '', box.w = box.Mw = box.mw = 0;} + if (!mitem.v) {box.h = box.d = 0} + box.bd = box.bh = 0; + delete mitem.phantom; + mitem.type = 'box'; + }, + + /* + * Create a box of zero height and depth containing the + * contents of the atom + */ + smash: function (style,size,mitem) { + var box = mitem.nuc = jsMath.Box.Set(mitem.smash,style,size).Remeasured(); + box.h = box.d = 0; + delete mitem.smash; + mitem.type = 'box'; + }, + + /* + * Move a box up or down vertically + */ + raise: function (style,size,mitem) { + mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size); + var y = mitem.raise; + mitem.nuc.html = + jsMath.HTML.Place(mitem.nuc.html,0,y,mitem.nuc.mw,mitem.nuc.Mw,mitem.nuc.w); + mitem.nuc.h += y; mitem.nuc.d -= y; + mitem.type = 'ord'; mitem.atom = 1; + }, + + /* + * Hide the size of a box so that it laps to the left or right, or + * up or down. + */ + lap: function (style,size,mitem) { + var box = jsMath.Box.Set(mitem.nuc,style,size).Remeasured(); + var mlist = [box]; + if (mitem.lap == 'llap') {box.x = -box.w} else + if (mitem.lap == 'rlap') {mlist[1] = jsMath.mItem.Space(-box.w)} else + if (mitem.lap == 'ulap') {box.y = box.d; box.h = box.d = 0} else + if (mitem.lap == 'dlap') {box.y = -box.h; box.h = box.d = 0} + mitem.nuc = jsMath.Box.SetList(mlist,style,size); + if (mitem.lap == 'ulap' || mitem.lap == 'dlap') {mitem.nuc.h = mitem.nuc.d = 0} + mitem.type = 'box'; delete mitem.atom; + }, + + /* + * Handle a Bin atom. (Rule 5) + */ + bin: function (style,size,mitem,prev) { + if (prev && prev.type) { + var type = prev.type; + if (type == 'bin' || type == 'op' || type == 'rel' || + type == 'open' || type == 'punct' || type == '' || + (type == 'boundary' && prev.left != '')) {mitem.type = 'ord'} + } else {mitem.type = 'ord'} + jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); + }, + + /* + * Handle a Rel atom. (Rule 6) + */ + rel: function (style,size,mitem,prev) { + if (prev.type && prev.type == 'bin') {prev.type = 'ord'} + jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); + }, + + /* + * Handle a Close atom. (Rule 6) + */ + close: function (style,size,mitem,prev) { + if (prev.type && prev.type == 'bin') {prev.type = 'ord'} + jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); + }, + + /* + * Handle a Punct atom. (Rule 6) + */ + punct: function (style,size,mitem,prev) { + if (prev.type && prev.type == 'bin') {prev.type = 'ord'} + jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); + }, + + /* + * Handle an Open atom. (Rule 7) + */ + open: function (style,size,mitem) { + jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); + }, + + /* + * Handle an Inner atom. (Rule 7) + */ + inner: function (style,size,mitem) { + jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); + }, + + /* + * Handle a Vcent atom. (Rule 8) + */ + vcenter: function (style,size,mitem) { + var box = jsMath.Box.Set(mitem.nuc,style,size); + var TeX = jsMath.Typeset.TeX(style,size); + box.y = TeX.axis_height - (box.h-box.d)/2; + mitem.nuc = box; mitem.type = 'ord'; + jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); + }, + + /* + * Handle an Over atom. (Rule 9) + */ + overline: function (style,size,mitem) { + var TeX = jsMath.Typeset.TeX(style,size); + var box = jsMath.Box.Set(mitem.nuc,jsMath.Typeset.PrimeStyle(style),size).Remeasured(); + var t = TeX.default_rule_thickness; + var rule = jsMath.Box.Rule(box.w,t); + rule.x = -rule.w; rule.y = box.h + 3*t; + mitem.nuc = jsMath.Box.SetList([box,rule],style,size); + mitem.nuc.h += t; + mitem.type = 'ord'; + jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); + }, + + /* + * Handle an Under atom. (Rule 10) + */ + underline: function (style,size,mitem) { + var TeX = jsMath.Typeset.TeX(style,size); + var box = jsMath.Box.Set(mitem.nuc,jsMath.Typeset.PrimeStyle(style),size).Remeasured(); + var t = TeX.default_rule_thickness; + var rule = jsMath.Box.Rule(box.w,t); + rule.x = -rule.w; rule.y = -box.d - 3*t - t; + mitem.nuc = jsMath.Box.SetList([box,rule],style,size); + mitem.nuc.d += t; + mitem.type = 'ord'; + jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); + }, + + /* + * Handle a Rad atom. (Rule 11 plus stuff for \root..\of) + */ + radical: function (style,size,mitem) { + var TeX = jsMath.Typeset.TeX(style,size); + var Cp = jsMath.Typeset.PrimeStyle(style); + var box = jsMath.Box.Set(mitem.nuc,Cp,size).Remeasured(); + var t = TeX.default_rule_thickness; + var p = t; if (style == 'D' || style == "D'") {p = TeX.x_height} + var r = t + p/4; + var surd = jsMath.Box.Delimiter(box.h+box.d+r+t,[0,2,0x70,3,0x70],style,1); +// if (surd.h > 0) {t = surd.h} // thickness of rule is height of surd character + if (surd.d > box.h+box.d+r) {r = (r+surd.d-box.h-box.d)/2} + surd.y = box.h+r; + var rule = jsMath.Box.Rule(box.w,t); + rule.y = surd.y-t/2; rule.h += 3*t/2; box.x = -box.w; + var Cr = jsMath.Typeset.UpStyle(jsMath.Typeset.UpStyle(style)); + var root = jsMath.Box.Set(mitem.root || null,Cr,size).Remeasured(); + if (mitem.root) { + root.y = .55*(box.h+box.d+3*t+r)-box.d; + surd.x = Math.max(root.w-(11/18)*surd.w,0); + rule.x = (7/18)*surd.w; + root.x = -(root.w+rule.x); + } + mitem.nuc = jsMath.Box.SetList([surd,root,rule,box],style,size); + mitem.type = 'ord'; + jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); + }, + + /* + * Handle an Acc atom. (Rule 12) + */ + accent: function (style,size,mitem) { + var TeX = jsMath.Typeset.TeX(style,size); + var Cp = jsMath.Typeset.PrimeStyle(style); + var box = jsMath.Box.Set(mitem.nuc,Cp,size); + var u = box.w; var s; var Font; var ic = 0; + if (mitem.nuc.type == 'TeX') { + Font = jsMath.TeX[mitem.nuc.font]; + if (Font[mitem.nuc.c].krn && Font.skewchar) + {s = Font[mitem.nuc.c].krn[Font.skewchar]} + ic = Font[mitem.nuc.c].ic; if (ic == null) {ic = 0} + } + if (s == null) {s = 0} + + var c = mitem.accent[2]; + var font = jsMath.TeX.fam[mitem.accent[1]]; Font = jsMath.TeX[font]; + while (Font[c].n && Font[Font[c].n].w <= u) {c = Font[c].n} + + var delta = Math.min(box.h,TeX.x_height); + if (mitem.nuc.type == 'TeX') { + var nitem = jsMath.mItem.Atom('ord',mitem.nuc); + nitem.sup = mitem.sup; nitem.sub = mitem.sub; nitem.delta = 0; + jsMath.mList.prototype.Atomize.SupSub(style,size,nitem); + delta += (nitem.nuc.h - box.h); + box = mitem.nuc = nitem.nuc; + delete mitem.sup; delete mitem.sub; + } + var acc = jsMath.Box.TeX(c,font,style,size); + acc.y = box.h - delta; acc.x = -box.w + s + (u-acc.w)/2; + if (jsMath.Browser.msieAccentBug) + {acc.html += jsMath.HTML.Spacer(.1); acc.w += .1; acc.Mw += .1} + if (Font[c].ic || ic) {acc.x += (ic - (Font[c].ic||0)) * TeX.scale} + + mitem.nuc = jsMath.Box.SetList([box,acc],style,size); + if (mitem.nuc.w != box.w) { + var space = jsMath.mItem.Space(box.w-mitem.nuc.w); + mitem.nuc = jsMath.Box.SetList([mitem.nuc,space],style,size); + } + mitem.type = 'ord'; + jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); + }, + + /* + * Handle an Op atom. (Rules 13 and 13a) + */ + op: function (style,size,mitem) { + var TeX = jsMath.Typeset.TeX(style,size); var box; + mitem.delta = 0; var isD = (style.charAt(0) == 'D'); + if (mitem.limits == null && isD) {mitem.limits = 1} + + if (mitem.nuc.type == 'TeX') { + var C = jsMath.TeX[mitem.nuc.font][mitem.nuc.c]; + if (isD && C.n) {mitem.nuc.c = C.n; C = jsMath.TeX[mitem.nuc.font][C.n]} + box = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size); + if (C.ic) { + mitem.delta = C.ic * TeX.scale; + if (mitem.limits || !mitem.sub || jsMath.Browser.msieIntegralBug) { + box = mitem.nuc = jsMath.Box.SetList([box,jsMath.mItem.Space(mitem.delta)],style,size); + } + } + box.y = -((box.h+box.d)/2 - box.d - TeX.axis_height); + if (Math.abs(box.y) < .0001) {box.y = 0} + } + + if (!box) {box = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size).Remeasured()} + if (mitem.limits) { + var W = box.w; var x = box.w; + var mlist = [box]; var dh = 0; var dd = 0; + if (mitem.sup) { + var sup = jsMath.Box.Set(mitem.sup,jsMath.Typeset.UpStyle(style),size).Remeasured(); + sup.x = ((box.w-sup.w)/2 + mitem.delta/2) - x; dh = TeX.big_op_spacing5; + W = Math.max(W,sup.w); x += sup.x + sup.w; + sup.y = box.h+sup.d + box.y + + Math.max(TeX.big_op_spacing1,TeX.big_op_spacing3-sup.d); + mlist[mlist.length] = sup; delete mitem.sup; + } + if (mitem.sub) { + var sub = jsMath.Box.Set(mitem.sub,jsMath.Typeset.DownStyle(style),size).Remeasured(); + sub.x = ((box.w-sub.w)/2 - mitem.delta/2) - x; dd = TeX.big_op_spacing5; + W = Math.max(W,sub.w); x += sub.x + sub.w; + sub.y = -box.d-sub.h + box.y - + Math.max(TeX.big_op_spacing2,TeX.big_op_spacing4-sub.h); + mlist[mlist.length] = sub; delete mitem.sub; + } + if (W > box.w) {box.x = (W-box.w)/2; x += box.x} + if (x < W) {mlist[mlist.length] = jsMath.mItem.Space(W-x)} + mitem.nuc = jsMath.Box.SetList(mlist,style,size); + mitem.nuc.h += dh; mitem.nuc.d += dd; + } else { + if (jsMath.Browser.msieIntegralBug && mitem.sub && C && C.ic) + {mitem.nuc = jsMath.Box.SetList([box,jsMath.Box.Space(-C.ic*TeX.scale)],style,size)} + else if (box.y) {mitem.nuc = jsMath.Box.SetList([box],style,size)} + jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); + } + }, + + /* + * Handle an Ord atom. (Rule 14) + */ + ord: function (style,size,mitem,prev,mList,i) { + if (mitem.nuc.type == 'TeX' && !mitem.sup && !mitem.sub) { + var nitem = mList.mlist[i+1]; + if (nitem && nitem.atom && nitem.type && + (nitem.type == 'ord' || nitem.type == 'op' || nitem.type == 'bin' || + nitem.type == 'rel' || nitem.type == 'open' || + nitem.type == 'close' || nitem.type == 'punct')) { + if (nitem.nuc.type == 'TeX' && nitem.nuc.font == mitem.nuc.font) { + mitem.textsymbol = 1; + var krn = jsMath.TeX[mitem.nuc.font][mitem.nuc.c].krn; + krn *= jsMath.Typeset.TeX(style,size).scale; + if (krn && krn[nitem.nuc.c]) { + for (var k = mList.mlist.length-1; k > i; k--) + {mList.mlist[k+1] = mList.mlist[k]} + mList.mlist[i+1] = jsMath.mItem.Space(krn[nitem.nuc.c]); + } + } + } + } + jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); + }, + + /* + * Handle a generalized fraction. (Rules 15 to 15e) + */ + fraction: function (style,size,mitem) { + var TeX = jsMath.Typeset.TeX(style,size); var t = 0; + if (mitem.thickness != null) {t = mitem.thickness} + else if (mitem.from.match(/over/)) {t = TeX.default_rule_thickness} + var isD = (style.charAt(0) == 'D'); + var Cn = (style == 'D')? 'T': (style == "D'")? "T'": jsMath.Typeset.UpStyle(style); + var Cd = (isD)? "T'": jsMath.Typeset.DownStyle(style); + var num = jsMath.Box.Set(mitem.num,Cn,size).Remeasured(); + var den = jsMath.Box.Set(mitem.den,Cd,size).Remeasured(); + + var u; var v; var w; var p; var r; + var H = (isD)? TeX.delim1 : TeX.delim2; + var mlist = [jsMath.Box.Delimiter(H,mitem.left,style)] + var right = jsMath.Box.Delimiter(H,mitem.right,style); + + if (num.w < den.w) { + num.x = (den.w-num.w)/2; + den.x = -(num.w + num.x); + w = den.w; mlist[1] = num; mlist[2] = den; + } else { + den.x = (num.w-den.w)/2; + num.x = -(den.w + den.x); + w = num.w; mlist[1] = den; mlist[2] = num; + } + if (isD) {u = TeX.num1; v = TeX.denom1} else { + u = (t != 0)? TeX.num2: TeX.num3; + v = TeX.denom2; + } + if (t == 0) {// atop + p = (isD)? 7*TeX.default_rule_thickness: 3*TeX.default_rule_thickness; + r = (u - num.d) - (den.h - v); + if (r < p) {u += (p-r)/2; v += (p-r)/2} + } else {// over + p = (isD)? 3*t: t; var a = TeX.axis_height; + r = (u-num.d)-(a+t/2); if (r < p) {u += p-r} + r = (a-t/2)-(den.h-v); if (r < p) {v += p-r} + var rule = jsMath.Box.Rule(w,t); rule.x = -w; rule.y = a - t/2; + mlist[mlist.length] = rule; + } + num.y = u; den.y = -v; + + mlist[mlist.length] = right; + mitem.nuc = jsMath.Box.SetList(mlist,style,size); + mitem.type = 'ord'; mitem.atom = 1; + delete mitem.num; delete mitem.den; + jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); + }, + + /* + * Add subscripts and superscripts. (Rules 17-18f) + */ + SupSub: function (style,size,mitem) { + var TeX = jsMath.Typeset.TeX(style,size); + var nuc = mitem.nuc; + var box = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size,0); + if (box.format == 'null') + {box = mitem.nuc = jsMath.Box.Text('','normal',style,size)} + + if (nuc.type == 'TeX') { + if (!mitem.textsymbol) { + var C = jsMath.TeX[nuc.font][nuc.c]; + if (C.ic) { + mitem.delta = C.ic * TeX.scale; + if (!mitem.sub) { + box = mitem.nuc = jsMath.Box.SetList([box,jsMath.Box.Space(mitem.delta)],style,size); + mitem.delta = 0; + } + } + } else {mitem.delta = 0} + } + + if (!mitem.sup && !mitem.sub) return; + mitem.nuc.Styled(); + + var Cd = jsMath.Typeset.DownStyle(style); + var Cu = jsMath.Typeset.UpStyle(style); + var q = jsMath.Typeset.TeX(Cu,size).sup_drop; + var r = jsMath.Typeset.TeX(Cd,size).sub_drop; + var u = 0; var v = 0; var p; + if (nuc.type && nuc.type != 'text' && nuc.type != 'TeX' && nuc.type != 'null') + {u = box.h - q; v = box.d + r} + + if (mitem.sub) { + var sub = jsMath.Box.Set(mitem.sub,Cd,size); + sub = jsMath.Box.SetList([sub,jsMath.mItem.Space(TeX.scriptspace)],style,size); + } + + if (!mitem.sup) { + sub.y = -Math.max(v,TeX.sub1,sub.h-(4/5)*jsMath.Typeset.TeX(Cd,size).x_height); + mitem.nuc = jsMath.Box.SetList([box,sub],style,size).Styled(); delete mitem.sub; + return; + } + + var sup = jsMath.Box.Set(mitem.sup,Cu,size); + sup = jsMath.Box.SetList([sup,jsMath.mItem.Space(TeX.scriptspace)],style,size); + if (style == 'D') {p = TeX.sup1} + else if (style.charAt(style.length-1) == "'") {p = TeX.sup3} + else {p = TeX.sup2} + u = Math.max(u,p,sup.d+jsMath.Typeset.TeX(Cu,size).x_height/4); + + if (!mitem.sub) { + sup.y = u; + mitem.nuc = jsMath.Box.SetList([box,sup],style,size); delete mitem.sup; + return; + } + + v = Math.max(v,jsMath.Typeset.TeX(Cd,size).sub2); + var t = TeX.default_rule_thickness; + if ((u-sup.d) - (sub.h -v) < 4*t) { + v = 4*t + sub.h - (u-sup.d); + p = (4/5)*TeX.x_height - (u-sup.d); + if (p > 0) {u += p; v -= p} + } + sup.Remeasured(); sub.Remeasured(); + sup.y = u; sub.y = -v; sup.x = mitem.delta; + if (sup.w+sup.x > sub.w) + {sup.x -= sub.w; mitem.nuc = jsMath.Box.SetList([box,sub,sup],style,size)} else + {sub.x -= (sup.w+sup.x); mitem.nuc = jsMath.Box.SetList([box,sup,sub],style,size)} + + delete mitem.sup; delete mitem.sub; + } + +}); + + +/***************************************************************************/ + +/* + * The Typeset object handles most of the TeX-specific processing + */ + +jsMath.Typeset = function (mlist) { + this.type = 'typeset'; + this.mlist = mlist; +} + +jsMath.Add(jsMath.Typeset,{ + + /* + * The "C-uparrow" style table (TeXbook, p. 441) + */ + upStyle: { + D: "S", T: "S", "D'": "S'", "T'": "S'", + S: "SS", SS: "SS", "S'": "SS'", "SS'": "SS'" + }, + + /* + * The "C-downarrow" style table (TeXbook, p. 441) + */ + downStyle: { + D: "S'", T: "S'", "D'": "S'", "T'": "S'", + S: "SS'", SS: "SS'", "S'": "SS'", "SS'": "SS'" + }, + + /* + * Get the various styles given the current style + * (see TeXbook, p. 441) + */ + UpStyle: function (style) {return this.upStyle[style]}, + DownStyle: function (style) {return this.downStyle[style]}, + PrimeStyle: function (style) { + if (style.charAt(style.length-1) == "'") {return style} + return style + "'" + }, + + /* + * A value scaled to the appropriate size for scripts + */ + StyleValue: function (style,v) { + if (style == "S" || style == "S'") {return .7*v} + if (style == "SS" || style == "SS'") {return .5*v} + return v; + }, + + /* + * Return the size associated with a given style and size + */ + StyleSize: function (style,size) { + if (style == "S" || style == "S'") {size = Math.max(0,size-2)} + else if (style == "SS" || style == "SS'") {size = Math.max(0,size-4)} + return size; + }, + + /* + * Return the font parameter table for the given style + */ + TeX: function (style,size) { + if (style == "S" || style == "S'") {size = Math.max(0,size-2)} + else if (style == "SS" || style == "SS'") {size = Math.max(0,size-4)} + return jsMath.TeXparams[size]; + }, + + + /* + * Add the CSS class for the given TeX style + */ + AddStyle: function (style,size,html) { + if (style == "S" || style == "S'") {size = Math.max(0,size-2)} + else if (style == "SS" || style == "SS'") {size = Math.max(0,size-4)} + if (size != 4) {html = '' + html + ''} + return html; + }, + + /* + * Add the font class, if needed + */ + AddClass: function (tclass,html) { + if (tclass != '' && tclass != 'normal') {html = jsMath.HTML.Class(tclass,html)} + return html; + } + +}); + + +jsMath.Package(jsMath.Typeset,{ + + /* + * The spacing tables for inter-atom spacing + * (See rule 20, and Chapter 18, p 170) + */ + DTsep: { + ord: {op: 1, bin: 2, rel: 3, inner: 1}, + op: {ord: 1, op: 1, rel: 3, inner: 1}, + bin: {ord: 2, op: 2, open: 2, inner: 2}, + rel: {ord: 3, op: 3, open: 3, inner: 3}, + open: {}, + close: {op: 1, bin:2, rel: 3, inner: 1}, + punct: {ord: 1, op: 1, rel: 1, open: 1, close: 1, punct: 1, inner: 1}, + inner: {ord: 1, op: 1, bin: 2, rel: 3, open: 1, punct: 1, inner: 1} + }, + + SSsep: { + ord: {op: 1}, + op: {ord: 1, op: 1}, + bin: {}, + rel: {}, + open: {}, + close: {op: 1}, + punct: {}, + inner: {op: 1} + }, + + /* + * The sizes used in the tables above + */ + sepW: ['','thinmuskip','medmuskip','thickmuskip'], + + + /* + * Find the amount of separation to use between two adjacent + * atoms in the given style + */ + GetSeparation: function (l,r,style) { + if (l && l.atom && r.atom) { + var table = this.DTsep; if (style.charAt(0) == "S") {table = this.SSsep} + var row = table[l.type]; + if (row && row[r.type] != null) {return jsMath.TeX[this.sepW[row[r.type]]]} + } + return 0; + }, + + /* + * Typeset an mlist (i.e., turn it into HTML). + * Here, text items of the same class and style are combined + * to reduce the number of tags used (though it is still + * huge). Spaces are combined, when possible. + * ### More needs to be done with that. ### + * The width of the final box is recomputed at the end, since + * the final width is not necessarily the sum of the widths of + * the individual parts (widths are in pixels, but the browsers + * puts pieces together using sub-pixel accuracy). + */ + Typeset: function (style,size) { + this.style = style; this.size = size; var unset = -10000 + this.w = 0; this.mw = 0; this.Mw = 0; + this.h = unset; this.d = unset; + this.bh = this.h; this.bd = this.d; + this.tbuf = ''; this.tx = 0; this.tclass = ''; + this.cbuf = ''; this.hbuf = ''; this.hx = 0; + var mitem = null; var prev; this.x = 0; this.dx = 0; + + for (var i = 0; i < this.mlist.length; i++) { + prev = mitem; mitem = this.mlist[i]; + switch (mitem.type) { + + case 'size': + this.FlushClassed(); + this.size = mitem.size; + mitem = prev; // hide this from TeX + break; + + case 'style': + this.FlushClassed(); + if (this.style.charAt(this.style.length-1) == "'") + {this.style = mitem.style + "'"} else {this.style = mitem.style} + mitem = prev; // hide this from TeX + break; + + case 'space': + if (typeof(mitem.w) == 'object') { + if (this.style.charAt(1) == 'S') {mitem.w = .5*mitem.w[0]/18} + else if (this.style.charAt(0) == 'S') {mitem.w = .7*mitem.w[0]/18} + else {mitem.w = mitem.w[0]/18} + } + this.dx += mitem.w-0; // mitem.w is sometimes a string? + mitem = prev; // hide this from TeX + break; + + case 'html': + this.FlushClassed(); + if (this.hbuf == '') {this.hx = this.x} + this.hbuf += mitem.html; + mitem = prev; // hide this from TeX + break; + + default: // atom + if (!mitem.atom && mitem.type != 'box') break; + mitem.nuc.x += this.dx + this.GetSeparation(prev,mitem,this.style); + if (mitem.nuc.x || mitem.nuc.y) mitem.nuc.Styled(); + this.dx = 0; this.x = this.x + this.w; + if (this.x + mitem.nuc.x + mitem.nuc.mw < this.mw) + {this.mw = this.x + mitem.nuc.x + mitem.nuc.mw} + if (this.w + mitem.nuc.x + mitem.nuc.Mw > this.Mw) + {this.Mw = this.w + mitem.nuc.x + mitem.nuc.Mw} + this.w += mitem.nuc.w + mitem.nuc.x; + if (mitem.nuc.format == 'text') { + if (this.tclass != mitem.nuc.tclass && this.tclass != '') this.FlushText(); + if (this.tbuf == '' && this.cbuf == '') {this.tx = this.x} + this.tbuf += mitem.nuc.html; this.tclass = mitem.nuc.tclass; + } else { + this.FlushClassed(); + if (mitem.nuc.x || mitem.nuc.y) this.Place(mitem.nuc); + if (this.hbuf == '') {this.hx = this.x} + this.hbuf += mitem.nuc.html; + } + this.h = Math.max(this.h,mitem.nuc.h+mitem.nuc.y); this.bh = Math.max(this.bh,mitem.nuc.bh); + this.d = Math.max(this.d,mitem.nuc.d-mitem.nuc.y); this.bd = Math.max(this.bd,mitem.nuc.bd); + break; + } + } + + this.FlushClassed(); // make sure scaling is included + if (this.dx) { + this.hbuf += jsMath.HTML.Spacer(this.dx); this.w += this.dx; + if (this.w > this.Mw) {this.Mw = this.w} + if (this.w < this.mw) {this.mw = this.w} + } + if (this.hbuf == '') {return jsMath.Box.Null()} + if (this.h == unset) {this.h = 0} + if (this.d == unset) {this.d = 0} + var box = new jsMath.Box('html',this.hbuf,this.w,this.h,this.d); + box.bh = this.bh; box.bd = this.bd; + box.mw = this.mw; box.Mw = this.Mw; + return box; + }, + + /* + * Add the font to the buffered text and move it to the + * classed-text buffer. + */ + FlushText: function () { + if (this.tbuf == '') return; + this.cbuf += jsMath.Typeset.AddClass(this.tclass,this.tbuf); + this.tbuf = ''; this.tclass = ''; + }, + + /* + * Add the script or scriptscript style to the text and + * move it to the HTML buffer + */ + FlushClassed: function () { + this.FlushText(); + if (this.cbuf == '') return; + if (this.hbuf == '') {this.hx = this.tx} + this.hbuf += jsMath.Typeset.AddStyle(this.style,this.size,this.cbuf); + this.cbuf = ''; + }, + + /* + * Add a to position an item's HTML, and + * adjust the item's height and depth. + * (This may be replaced buy one of the following browser-specific + * versions by Browser.Init().) + */ + Place: function (item) { + var html = '' + item.html + ''; + item.h += item.y; item.d -= item.y; + item.x = 0; item.y = 0; + }, + + /* + * For MSIE on Windows, backspacing must be done in a separate + * , otherwise the contents will be clipped. Netscape + * also doesn't combine vertical and horizontal spacing well. + * Here, the horizontal and vertical spacing are done separately. + */ + + PlaceSeparateSkips: function (item) { + if (item.y) { + var rw = item.Mw - item.w; var lw = item.mw; + var W = item.Mw - item.mw; + item.html = + jsMath.HTML.Spacer(lw-rw) + + '' + + jsMath.HTML.Spacer(-lw) + + item.html + + jsMath.HTML.Spacer(rw) + + '' + } + if (item.x) {item.html = jsMath.HTML.Spacer(item.x) + item.html} + item.h += item.y; item.d -= item.y; + item.x = 0; item.y = 0; + } + +}); + + + +/***************************************************************************/ + +/* + * The Parse object handles the parsing of the TeX input string, and creates + * the mList to be typeset by the Typeset object above. + */ + +jsMath.Parse = function (s,font,size,style) { + var parse = new jsMath.Parser(s,font,size,style); + parse.Parse(); + return parse; +} + +jsMath.Parser = function (s,font,size,style) { + this.string = s; this.i = 0; + this.mlist = new jsMath.mList(null,font,size,style); +} + +jsMath.Package(jsMath.Parser,{ + + // special characters + cmd: '\\', + open: '{', + close: '}', + + // patterns for letters and numbers + letter: /[a-z]/i, + number: /[0-9]/, + // pattern for macros to ^ and _ that should be read with arguments + scriptargs: /^((math|text)..|mathcal|[hm]box)$/, + + // the \mathchar definitions (see Appendix B of the TeXbook). + mathchar: { + '!': [5,0,0x21], + '(': [4,0,0x28], + ')': [5,0,0x29], + '*': [2,2,0x03], // \ast + '+': [2,0,0x2B], + ',': [6,1,0x3B], + '-': [2,2,0x00], + '.': [0,1,0x3A], + '/': [0,1,0x3D], + ':': [3,0,0x3A], + ';': [6,0,0x3B], + '<': [3,1,0x3C], + '=': [3,0,0x3D], + '>': [3,1,0x3E], + '?': [5,0,0x3F], + '[': [4,0,0x5B], + ']': [5,0,0x5D], +// '{': [4,2,0x66], +// '}': [5,2,0x67], + '|': [0,2,0x6A] + }, + + // handle special \catcode characters + special: { + '~': 'Tilde', + '^': 'HandleSuperscript', + '_': 'HandleSubscript', + ' ': 'Space', + '\01': 'Space', + "\t": 'Space', + "\r": 'Space', + "\n": 'Space', + "'": 'Prime', + '%': 'HandleComment', + '&': 'HandleEntry', + '#': 'Hash' + }, + + // the \mathchardef table (see Appendix B of the TeXbook). + mathchardef: { + // brace parts + braceld: [0,3,0x7A], + bracerd: [0,3,0x7B], + bracelu: [0,3,0x7C], + braceru: [0,3,0x7D], + + // Greek letters + alpha: [0,1,0x0B], + beta: [0,1,0x0C], + gamma: [0,1,0x0D], + delta: [0,1,0x0E], + epsilon: [0,1,0x0F], + zeta: [0,1,0x10], + eta: [0,1,0x11], + theta: [0,1,0x12], + iota: [0,1,0x13], + kappa: [0,1,0x14], + lambda: [0,1,0x15], + mu: [0,1,0x16], + nu: [0,1,0x17], + xi: [0,1,0x18], + pi: [0,1,0x19], + rho: [0,1,0x1A], + sigma: [0,1,0x1B], + tau: [0,1,0x1C], + upsilon: [0,1,0x1D], + phi: [0,1,0x1E], + chi: [0,1,0x1F], + psi: [0,1,0x20], + omega: [0,1,0x21], + varepsilon: [0,1,0x22], + vartheta: [0,1,0x23], + varpi: [0,1,0x24], + varrho: [0,1,0x25], + varsigma: [0,1,0x26], + varphi: [0,1,0x27], + + Gamma: [7,0,0x00], + Delta: [7,0,0x01], + Theta: [7,0,0x02], + Lambda: [7,0,0x03], + Xi: [7,0,0x04], + Pi: [7,0,0x05], + Sigma: [7,0,0x06], + Upsilon: [7,0,0x07], + Phi: [7,0,0x08], + Psi: [7,0,0x09], + Omega: [7,0,0x0A], + + // Ord symbols + aleph: [0,2,0x40], + imath: [0,1,0x7B], + jmath: [0,1,0x7C], + ell: [0,1,0x60], + wp: [0,1,0x7D], + Re: [0,2,0x3C], + Im: [0,2,0x3D], + partial: [0,1,0x40], + infty: [0,2,0x31], + prime: [0,2,0x30], + emptyset: [0,2,0x3B], + nabla: [0,2,0x72], + surd: [1,2,0x70], + top: [0,2,0x3E], + bot: [0,2,0x3F], + triangle: [0,2,0x34], + forall: [0,2,0x38], + exists: [0,2,0x39], + neg: [0,2,0x3A], + lnot: [0,2,0x3A], + flat: [0,1,0x5B], + natural: [0,1,0x5C], + sharp: [0,1,0x5D], + clubsuit: [0,2,0x7C], + diamondsuit: [0,2,0x7D], + heartsuit: [0,2,0x7E], + spadesuit: [0,2,0x7F], + + // big ops + coprod: [1,3,0x60], + bigvee: [1,3,0x57], + bigwedge: [1,3,0x56], + biguplus: [1,3,0x55], + bigcap: [1,3,0x54], + bigcup: [1,3,0x53], + intop: [1,3,0x52], + prod: [1,3,0x51], + sum: [1,3,0x50], + bigotimes: [1,3,0x4E], + bigoplus: [1,3,0x4C], + bigodot: [1,3,0x4A], + ointop: [1,3,0x48], + bigsqcup: [1,3,0x46], + smallint: [1,2,0x73], + + // binary operations + triangleleft: [2,1,0x2F], + triangleright: [2,1,0x2E], + bigtriangleup: [2,2,0x34], + bigtriangledown: [2,2,0x35], + wedge: [2,2,0x5E], + land: [2,2,0x5E], + vee: [2,2,0x5F], + lor: [2,2,0x5F], + cap: [2,2,0x5C], + cup: [2,2,0x5B], + ddagger: [2,2,0x7A], + dagger: [2,2,0x79], + sqcap: [2,2,0x75], + sqcup: [2,2,0x74], + uplus: [2,2,0x5D], + amalg: [2,2,0x71], + diamond: [2,2,0x05], + bullet: [2,2,0x0F], + wr: [2,2,0x6F], + div: [2,2,0x04], + odot: [2,2,0x0C], + oslash: [2,2,0x0B], + otimes: [2,2,0x0A], + ominus: [2,2,0x09], + oplus: [2,2,0x08], + mp: [2,2,0x07], + pm: [2,2,0x06], + circ: [2,2,0x0E], + bigcirc: [2,2,0x0D], + setminus: [2,2,0x6E], // for set difference A\setminus B + cdot: [2,2,0x01], + ast: [2,2,0x03], + times: [2,2,0x02], + star: [2,1,0x3F], + + // Relations + propto: [3,2,0x2F], + sqsubseteq: [3,2,0x76], + sqsupseteq: [3,2,0x77], + parallel: [3,2,0x6B], + mid: [3,2,0x6A], + dashv: [3,2,0x61], + vdash: [3,2,0x60], + leq: [3,2,0x14], + le: [3,2,0x14], + geq: [3,2,0x15], + ge: [3,2,0x15], + lt: [3,1,0x3C], // extra since < and > are hard + gt: [3,1,0x3E], // to get in HTML + succ: [3,2,0x1F], + prec: [3,2,0x1E], + approx: [3,2,0x19], + succeq: [3,2,0x17], + preceq: [3,2,0x16], + supset: [3,2,0x1B], + subset: [3,2,0x1A], + supseteq: [3,2,0x13], + subseteq: [3,2,0x12], + 'in': [3,2,0x32], + ni: [3,2,0x33], + owns: [3,2,0x33], + gg: [3,2,0x1D], + ll: [3,2,0x1C], + not: [3,2,0x36], + sim: [3,2,0x18], + simeq: [3,2,0x27], + perp: [3,2,0x3F], + equiv: [3,2,0x11], + asymp: [3,2,0x10], + smile: [3,1,0x5E], + frown: [3,1,0x5F], + + // Arrows + Leftrightarrow: [3,2,0x2C], + Leftarrow: [3,2,0x28], + Rightarrow: [3,2,0x29], + leftrightarrow: [3,2,0x24], + leftarrow: [3,2,0x20], + gets: [3,2,0x20], + rightarrow: [3,2,0x21], + to: [3,2,0x21], + mapstochar: [3,2,0x37], + leftharpoonup: [3,1,0x28], + leftharpoondown: [3,1,0x29], + rightharpoonup: [3,1,0x2A], + rightharpoondown: [3,1,0x2B], + nearrow: [3,2,0x25], + searrow: [3,2,0x26], + nwarrow: [3,2,0x2D], + swarrow: [3,2,0x2E], + + minuschar: [3,2,0x00], // for longmapsto + hbarchar: [0,0,0x16], // for \hbar + lhook: [3,1,0x2C], + rhook: [3,1,0x2D], + + ldotp: [6,1,0x3A], // ldot as a punctuation mark + cdotp: [6,2,0x01], // cdot as a punctuation mark + colon: [6,0,0x3A], // colon as a punctuation mark + + '#': [7,0,0x23], + '$': [7,0,0x24], + '%': [7,0,0x25], + '&': [7,0,0x26] + }, + + // The delimiter table (see Appendix B of the TeXbook) + delimiter: { + '(': [0,0,0x28,3,0x00], + ')': [0,0,0x29,3,0x01], + '[': [0,0,0x5B,3,0x02], + ']': [0,0,0x5D,3,0x03], + '<': [0,2,0x68,3,0x0A], + '>': [0,2,0x69,3,0x0B], + '\\lt': [0,2,0x68,3,0x0A], // extra since < and > are + '\\gt': [0,2,0x69,3,0x0B], // hard to get in HTML + '/': [0,0,0x2F,3,0x0E], + '|': [0,2,0x6A,3,0x0C], + '.': [0,0,0x00,0,0x00], + '\\': [0,2,0x6E,3,0x0F], + '\\lmoustache': [4,3,0x7A,3,0x40], // top from (, bottom from ) + '\\rmoustache': [5,3,0x7B,3,0x41], // top from ), bottom from ( + '\\lgroup': [4,6,0x28,3,0x3A], // extensible ( with sharper tips + '\\rgroup': [5,6,0x29,3,0x3B], // extensible ) with sharper tips + '\\arrowvert': [0,2,0x6A,3,0x3C], // arrow without arrowheads + '\\Arrowvert': [0,2,0x6B,3,0x3D], // double arrow without arrowheads +// '\\bracevert': [0,7,0x7C,3,0x3E], // the vertical bar that extends braces + '\\bracevert': [0,2,0x6A,3,0x3E], // we don't load tt, so use | instead + '\\Vert': [0,2,0x6B,3,0x0D], + '\\|': [0,2,0x6B,3,0x0D], + '\\vert': [0,2,0x6A,3,0x0C], + '\\uparrow': [3,2,0x22,3,0x78], + '\\downarrow': [3,2,0x23,3,0x79], + '\\updownarrow': [3,2,0x6C,3,0x3F], + '\\Uparrow': [3,2,0x2A,3,0x7E], + '\\Downarrow': [3,2,0x2B,3,0x7F], + '\\Updownarrow': [3,2,0x6D,3,0x77], + '\\backslash': [0,2,0x6E,3,0x0F], // for double coset G\backslash H + '\\rangle': [5,2,0x69,3,0x0B], + '\\langle': [4,2,0x68,3,0x0A], + '\\rbrace': [5,2,0x67,3,0x09], + '\\lbrace': [4,2,0x66,3,0x08], + '\\}': [5,2,0x67,3,0x09], + '\\{': [4,2,0x66,3,0x08], + '\\rceil': [5,2,0x65,3,0x07], + '\\lceil': [4,2,0x64,3,0x06], + '\\rfloor': [5,2,0x63,3,0x05], + '\\lfloor': [4,2,0x62,3,0x04], + '\\lbrack': [0,0,0x5B,3,0x02], + '\\rbrack': [0,0,0x5D,3,0x03] + }, + + /* + * The basic macros for plain TeX. + * + * When the control sequence on the left is called, the JavaScript + * funtion on the right is called, with the name of the control sequence + * as its first parameter (this way, the same function can be called by + * several different control sequences to do similar actions, and the + * function can still tell which TeX command was issued). If the right + * is an array, the first entry is the routine to call, and the + * remaining entries in the array are parameters to pass to the function + * as the second parameter (they are in an array reference). + * + * Note: TeX macros as defined by the user are discussed below. + */ + macros: { + displaystyle: ['HandleStyle','D'], + textstyle: ['HandleStyle','T'], + scriptstyle: ['HandleStyle','S'], + scriptscriptstyle: ['HandleStyle','SS'], + + rm: ['HandleFont',0], + mit: ['HandleFont',1], + oldstyle: ['HandleFont',1], + cal: ['HandleFont',2], + it: ['HandleFont',4], + bf: ['HandleFont',6], + + font: ['Extension','font'], + + left: 'HandleLeft', + right: 'HandleRight', + + arcsin: ['NamedOp',0], + arccos: ['NamedOp',0], + arctan: ['NamedOp',0], + arg: ['NamedOp',0], + cos: ['NamedOp',0], + cosh: ['NamedOp',0], + cot: ['NamedOp',0], + coth: ['NamedOp',0], + csc: ['NamedOp',0], + deg: ['NamedOp',0], + det: 'NamedOp', + dim: ['NamedOp',0], + exp: ['NamedOp',0], + gcd: 'NamedOp', + hom: ['NamedOp',0], + inf: 'NamedOp', + ker: ['NamedOp',0], + lg: ['NamedOp',0], + lim: 'NamedOp', + liminf: ['NamedOp',null,'liminf'], + limsup: ['NamedOp',null,'limsup'], + ln: ['NamedOp',0], + log: ['NamedOp',0], + max: 'NamedOp', + min: 'NamedOp', + Pr: 'NamedOp', + sec: ['NamedOp',0], + sin: ['NamedOp',0], + sinh: ['NamedOp',0], + sup: 'NamedOp', + tan: ['NamedOp',0], + tanh: ['NamedOp',0], + + vcenter: ['HandleAtom','vcenter'], + overline: ['HandleAtom','overline'], + underline: ['HandleAtom','underline'], + over: 'HandleOver', + overwithdelims: 'HandleOver', + atop: 'HandleOver', + atopwithdelims: 'HandleOver', + above: 'HandleOver', + abovewithdelims: 'HandleOver', + brace: ['HandleOver','\\{','\\}'], + brack: ['HandleOver','[',']'], + choose: ['HandleOver','(',')'], + + overbrace: ['Extension','leaders'], + underbrace: ['Extension','leaders'], + overrightarrow: ['Extension','leaders'], + underrightarrow: ['Extension','leaders'], + overleftarrow: ['Extension','leaders'], + underleftarrow: ['Extension','leaders'], + overleftrightarrow: ['Extension','leaders'], + underleftrightarrow: ['Extension','leaders'], + overset: ['Extension','underset-overset'], + underset: ['Extension','underset-overset'], + + llap: 'HandleLap', + rlap: 'HandleLap', + ulap: 'HandleLap', + dlap: 'HandleLap', + raise: 'RaiseLower', + lower: 'RaiseLower', + moveleft: 'MoveLeftRight', + moveright: 'MoveLeftRight', + + frac: 'Frac', + root: 'Root', + sqrt: 'Sqrt', + + // TeX substitution macros + hbar: ['Macro','\\hbarchar\\kern-.5em h'], + ne: ['Macro','\\not='], + neq: ['Macro','\\not='], + notin: ['Macro','\\mathrel{\\rlap{\\kern2mu/}}\\in'], + cong: ['Macro','\\mathrel{\\lower2mu{\\mathrel{{\\rlap{=}\\raise6mu\\sim}}}}'], + bmod: ['Macro','\\mathbin{\\rm mod}'], + pmod: ['Macro','\\kern 18mu ({\\rm mod}\\,\\,#1)',1], + 'int': ['Macro','\\intop\\nolimits'], + oint: ['Macro','\\ointop\\nolimits'], + doteq: ['Macro','\\buildrel\\textstyle.\\over='], + ldots: ['Macro','\\mathinner{\\ldotp\\ldotp\\ldotp}'], + cdots: ['Macro','\\mathinner{\\cdotp\\cdotp\\cdotp}'], + vdots: ['Macro','\\mathinner{\\rlap{\\raise8pt{.\\rule 0pt 6pt 0pt}}\\rlap{\\raise4pt{.}}.}'], + ddots: ['Macro','\\mathinner{\\kern1mu\\raise7pt{\\rule 0pt 7pt 0pt .}\\kern2mu\\raise4pt{.}\\kern2mu\\raise1pt{.}\\kern1mu}'], + joinrel: ['Macro','\\mathrel{\\kern-4mu}'], + relbar: ['Macro','\\mathrel{\\smash-}'], // \smash, because - has the same height as + + Relbar: ['Macro','\\mathrel='], + bowtie: ['Macro','\\mathrel\\triangleright\\joinrel\\mathrel\\triangleleft'], + models: ['Macro','\\mathrel|\\joinrel='], + mapsto: ['Macro','\\mathrel{\\mapstochar\\rightarrow}'], + rightleftharpoons: ['Macro','\\vcenter{\\mathrel{\\rlap{\\raise3mu{\\rightharpoonup}}}\\leftharpoondown}'], + hookrightarrow: ['Macro','\\lhook\\joinrel\\rightarrow'], + hookleftarrow: ['Macro','\\leftarrow\\joinrel\\rhook'], + Longrightarrow: ['Macro','\\Relbar\\joinrel\\Rightarrow'], + longrightarrow: ['Macro','\\relbar\\joinrel\\rightarrow'], + longleftarrow: ['Macro','\\leftarrow\\joinrel\\relbar'], + Longleftarrow: ['Macro','\\Leftarrow\\joinrel\\Relbar'], + longmapsto: ['Macro','\\mathrel{\\mapstochar\\minuschar\\joinrel\\rightarrow}'], + longleftrightarrow: ['Macro','\\leftarrow\\joinrel\\rightarrow'], + Longleftrightarrow: ['Macro','\\Leftarrow\\joinrel\\Rightarrow'], + iff: ['Macro','\\;\\Longleftrightarrow\\;'], + mathcal: ['Macro','{\\cal #1}',1], + mathrm: ['Macro','{\\rm #1}',1], + mathbf: ['Macro','{\\bf #1}',1], + mathbb: ['Macro','{\\bf #1}',1], + mathit: ['Macro','{\\it #1}',1], + textrm: ['Macro','\\mathord{\\hbox{#1}}',1], + textit: ['Macro','\\mathord{\\class{textit}{\\hbox{#1}}}',1], + textbf: ['Macro','\\mathord{\\class{textbf}{\\hbox{#1}}}',1], + pmb: ['Macro','\\rlap{#1}\\kern1px{#1}',1], + + TeX: ['Macro','T\\kern-.1667em\\lower.5ex{E}\\kern-.125em X'], + + limits: ['Limits',1], + nolimits: ['Limits',0], + + ',': ['Spacer',1/6], + ':': ['Spacer',1/6], // for LaTeX + '>': ['Spacer',2/9], + ';': ['Spacer',5/18], + '!': ['Spacer',-1/6], + enspace: ['Spacer',1/2], + quad: ['Spacer',1], + qquad: ['Spacer',2], + thinspace: ['Spacer',1/6], + negthinspace: ['Spacer',-1/6], + + hskip: 'Hskip', + kern: 'Hskip', + rule: ['Rule','colored'], + space: ['Rule','blank'], + + big: ['MakeBig','ord',0.85], + Big: ['MakeBig','ord',1.15], + bigg: ['MakeBig','ord',1.45], + Bigg: ['MakeBig','ord',1.75], + bigl: ['MakeBig','open',0.85], + Bigl: ['MakeBig','open',1.15], + biggl: ['MakeBig','open',1.45], + Biggl: ['MakeBig','open',1.75], + bigr: ['MakeBig','close',0.85], + Bigr: ['MakeBig','close',1.15], + biggr: ['MakeBig','close',1.45], + Biggr: ['MakeBig','close',1.75], + bigm: ['MakeBig','rel',0.85], + Bigm: ['MakeBig','rel',1.15], + biggm: ['MakeBig','rel',1.45], + Biggm: ['MakeBig','rel',1.75], + + mathord: ['HandleAtom','ord'], + mathop: ['HandleAtom','op'], + mathopen: ['HandleAtom','open'], + mathclose: ['HandleAtom','close'], + mathbin: ['HandleAtom','bin'], + mathrel: ['HandleAtom','rel'], + mathpunct: ['HandleAtom','punct'], + mathinner: ['HandleAtom','inner'], + + mathchoice: ['Extension','mathchoice'], + buildrel: 'BuildRel', + + hbox: 'HBox', + text: 'HBox', + mbox: 'HBox', + fbox: ['Extension','fbox'], + + strut: 'Strut', + mathstrut: ['Macro','\\vphantom{(}'], + phantom: ['Phantom',1,1], + vphantom: ['Phantom',1,0], + hphantom: ['Phantom',0,1], + smash: 'Smash', + + acute: ['MathAccent', [7,0,0x13]], + grave: ['MathAccent', [7,0,0x12]], + ddot: ['MathAccent', [7,0,0x7F]], + tilde: ['MathAccent', [7,0,0x7E]], + bar: ['MathAccent', [7,0,0x16]], + breve: ['MathAccent', [7,0,0x15]], + check: ['MathAccent', [7,0,0x14]], + hat: ['MathAccent', [7,0,0x5E]], + vec: ['MathAccent', [0,1,0x7E]], + dot: ['MathAccent', [7,0,0x5F]], + widetilde: ['MathAccent', [0,3,0x65]], + widehat: ['MathAccent', [0,3,0x62]], + + '_': ['Replace','ord','_','normal',-.4,.1], + ' ': ['Replace','ord',' ','normal'], +// angle: ['Replace','ord','∠','normal'], + angle: ['Macro','\\kern2.5mu\\raise1.54pt{\\rlap{\\scriptstyle \\char{cmsy10}{54}}\\kern1pt\\rule{.45em}{-1.2pt}{1.54pt}\\kern2.5mu}'], + + matrix: 'Matrix', + array: 'Matrix', // ### still need to do alignment options ### + pmatrix: ['Matrix','(',')','c'], + cases: ['Matrix','\\{','.',['l','l'],null,2], + eqalign: ['Matrix',null,null,['r','l'],[5/18],3,'D'], + displaylines: ['Matrix',null,null,['c'],null,3,'D'], + cr: 'HandleRow', + '\\': 'HandleRow', + newline: 'HandleRow', + noalign: 'HandleNoAlign', + eqalignno: ['Matrix',null,null,['r','l','r'],[5/8,3],3,'D'], + leqalignno: ['Matrix',null,null,['r','l','r'],[5/8,3],3,'D'], + + // LaTeX + begin: 'Begin', + end: 'End', + tiny: ['HandleSize',0], + Tiny: ['HandleSize',1], // non-standard + scriptsize: ['HandleSize',2], + small: ['HandleSize',3], + normalsize: ['HandleSize',4], + large: ['HandleSize',5], + Large: ['HandleSize',6], + LARGE: ['HandleSize',7], + huge: ['HandleSize',8], + Huge: ['HandleSize',9], + dots: ['Macro','\\ldots'], + + newcommand: ['Extension','newcommand'], + newenvironment: ['Extension','newcommand'], + def: ['Extension','newcommand'], + + // Extensions to TeX + color: ['Extension','HTML'], + href: ['Extension','HTML'], + 'class': ['Extension','HTML'], + style: ['Extension','HTML'], + cssId: ['Extension','HTML'], + unicode: ['Extension','HTML'], + bbox: ['Extension','bbox'], + + require: 'Require', + + // debugging and test routines + 'char': 'Char' + }, + + /* + * LaTeX environments + */ + environments: { + array: 'Array', + matrix: ['Array',null,null,'c'], + pmatrix: ['Array','(',')','c'], + bmatrix: ['Array','[',']','c'], + Bmatrix: ['Array','\\{','\\}','c'], + vmatrix: ['Array','\\vert','\\vert','c'], + Vmatrix: ['Array','\\Vert','\\Vert','c'], + cases: ['Array','\\{','.','ll',null,2], + eqnarray: ['Array',null,null,'rcl',[5/18,5/18],3,'D'], + 'eqnarray*': ['Array',null,null,'rcl',[5/18,5/18],3,'D'], + equation: 'Equation', + 'equation*': 'Equation', + + align: ['Extension','AMSmath'], + 'align*': ['Extension','AMSmath'], + aligned: ['Extension','AMSmath'], + multline: ['Extension','AMSmath'], + 'multline*': ['Extension','AMSmath'], + split: ['Extension','AMSmath'], + gather: ['Extension','AMSmath'], + 'gather*': ['Extension','AMSmath'], + gathered: ['Extension','AMSmath'] + }, + + + /***************************************************************************/ + + /* + * Add special characters to list above. (This makes it possible + * to define them in a variable that the user can change.) + */ + AddSpecial: function (obj) { + for (var id in obj) { + jsMath.Parser.prototype.special[jsMath.Parser.prototype[id]] = obj[id]; + } + }, + + /* + * Throw an error + */ + Error: function (s) { + this.i = this.string.length; + if (s.error) {this.error = s.error} else { + if (!this.error) {this.error = s} + } + }, + + /***************************************************************************/ + + /* + * Check if the next character is a space + */ + nextIsSpace: function () { + return this.string.charAt(this.i).match(/[ \n\r\t]/); + }, + + /* + * Trim spaces from a string + */ + trimSpaces: function (text) { + if (typeof(text) != 'string') {return text} + return text.replace(/^\s+|\s+$/g,''); + }, + + /* + * Parse a substring to get its mList, and return it. + * Check that no errors occured + */ + Process: function (arg) { + var data = this.mlist.data; + arg = jsMath.Parse(arg,data.font,data.size,data.style); + if (arg.error) {this.Error(arg); return null} + if (arg.mlist.Length() == 0) {return null} + if (arg.mlist.Length() == 1) { + var atom = arg.mlist.Last(); + if (atom.atom && atom.type == 'ord' && atom.nuc && + !atom.sub && !atom.sup && (atom.nuc.type == 'text' || atom.nuc.type == 'TeX')) + {return atom.nuc} + } + return {type: 'mlist', mlist: arg.mlist}; + }, + + /* + * Get and return a control-sequence name from the TeX string + */ + GetCommand: function () { + var letter = /^([a-z]+|.) ?/i; + var cmd = letter.exec(this.string.slice(this.i)); + if (cmd) {this.i += cmd[1].length; return cmd[1]} + this.i++; return " "; + }, + + /* + * Get and return a TeX argument (either a single character or control sequence, + * or the contents of the next set of braces). + */ + GetArgument: function (name,noneOK) { + while (this.nextIsSpace()) {this.i++} + if (this.i >= this.string.length) {if (!noneOK) this.Error("Missing argument for "+name); return null} + if (this.string.charAt(this.i) == this.close) {if (!noneOK) this.Error("Extra close brace"); return null} + if (this.string.charAt(this.i) == this.cmd) {this.i++; return this.cmd+this.GetCommand()} + if (this.string.charAt(this.i) != this.open) {return this.string.charAt(this.i++)} + var j = ++this.i; var pcount = 1; var c = ''; + while (this.i < this.string.length) { + c = this.string.charAt(this.i++); + if (c == this.cmd) {this.i++} + else if (c == this.open) {pcount++} + else if (c == this.close) { + if (pcount == 0) {this.Error("Extra close brace"); return null} + if (--pcount == 0) {return this.string.slice(j,this.i-1)} + } + } + this.Error("Missing close brace"); + return null; + }, + + /* + * Get an argument and process it into an mList + */ + ProcessArg: function (name) { + var arg = this.GetArgument(name); if (this.error) {return null} + return this.Process(arg); + }, + + /* + * Get and process an argument for a super- or subscript. + * (read extra args for \frac, \sqrt, \mathrm, etc.) + * This handles these macros as special cases, so is really + * rather a hack. A more general method for indicating + * how to handle macros in scripts needs to be developed. + */ + ProcessScriptArg: function (name) { + var arg = this.GetArgument(name); if (this.error) {return null} + if (arg.charAt(0) == this.cmd) { + var csname = arg.substr(1); + if (csname == "frac") { + arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null} + arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null} + } else if (csname == "sqrt") { + arg += '['+this.GetBrackets(csname)+']'; if (this.error) {return null} + arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null} + } else if (csname.match(this.scriptargs)) { + arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null} + } + } + return this.Process(arg); + }, + + /* + * Get the name of a delimiter (check it in the delimiter list). + */ + GetDelimiter: function (name) { + while (this.nextIsSpace()) {this.i++} + var c = this.string.charAt(this.i); + if (this.i < this.string.length) { + this.i++; + if (c == this.cmd) {c = '\\'+this.GetCommand(name); if (this.error) return null} + if (this.delimiter[c] != null) {return this.delimiter[c]} + } + this.Error("Missing or unrecognized delimiter for "+name); + return null; + }, + + /* + * Get a dimension (including its units). + * Convert the dimen to em's, except for mu's, which must be + * converted when typeset. + */ + GetDimen: function (name,nomu) { + var rest; var advance = 0; + if (this.nextIsSpace()) {this.i++} + if (this.string.charAt(this.i) == '{') { + rest = this.GetArgument(name); + } else { + rest = this.string.slice(this.i); + advance = 1; + } + return this.ParseDimen(rest,name,advance,nomu); + }, + + ParseDimen: function (dimen,name,advance,nomu) { + var match = dimen.match(/^\s*([-+]?(\.\d+|\d+(\.\d*)?))(pt|em|ex|mu|px)/); + if (!match) {this.Error("Missing dimension or its units for "+name); return null} + if (advance) { + this.i += match[0].length; + if (this.nextIsSpace()) {this.i++} + } + var d = match[1]-0; + if (match[4] == 'px') {d /= jsMath.em} + else if (match[4] == 'pt') {d /= 10} + else if (match[4] == 'ex') {d *= jsMath.TeX.x_height} + else if (match[4] == 'mu') {if (nomu) {d = d/18} else {d = [d,'mu']}} + return d; + }, + + /* + * Get the next non-space character + */ + GetNext: function () { + while (this.nextIsSpace()) {this.i++} + return this.string.charAt(this.i); + }, + + /* + * Get an optional LaTeX argument in brackets + */ + GetBrackets: function (name) { + var c = this.GetNext(); if (c != '[') return ''; + var start = ++this.i; var pcount = 0; + while (this.i < this.string.length) { + c = this.string.charAt(this.i++); + if (c == '{') {pcount++} + else if (c == '}') { + if (pcount == 0) + {this.Error("Extra close brace while looking for ']'"); return null} + pcount --; + } else if (c == this.cmd) { + this.i++; + } else if (c == ']') { + if (pcount == 0) {return this.string.slice(start,this.i-1)} + } + } + this.Error("Couldn't find closing ']' for argument to "+this.cmd+name); + return null; + }, + + /* + * Get everything up to the given control sequence name (token) + */ + GetUpto: function (name,token) { + while (this.nextIsSpace()) {this.i++} + var start = this.i; var pcount = 0; + while (this.i < this.string.length) { + var c = this.string.charAt(this.i++); + if (c == '{') {pcount++} + else if (c == '}') { + if (pcount == 0) + {this.Error("Extra close brace while looking for "+this.cmd+token); return null} + pcount --; + } else if (c == this.cmd) { + // really need separate counter for begin/end + // and it should really be a stack (new pcount for each begin) + if (this.string.slice(this.i,this.i+5) == "begin") {pcount++; this.i+=4} + else if (this.string.slice(this.i,this.i+3) == "end") { + if (pcount > 0) {pcount--; this.i += 2} + } + if (pcount == 0) { + if (this.string.slice(this.i,this.i+token.length) == token) { + c = this.string.charAt(this.i+token.length); + if (c.match(/[^a-z]/i) || !token.match(/[a-z]/i)) { + var arg = this.string.slice(start,this.i-1); + this.i += token.length; + return arg; + } + } + } + this.i++; + } + } + this.Error("Couldn't find "+this.cmd+token+" for "+name); + return null; + }, + + /* + * Get a parameter delimited by a control sequence, and + * process it to get its mlist + */ + ProcessUpto: function (name,token) { + var arg = this.GetUpto(name,token); if (this.error) return null; + return this.Process(arg); + }, + + /* + * Get everything up to \end{env} + */ + GetEnd: function (env) { + var body = ''; var name = ''; + while (name != env) { + body += this.GetUpto('begin{'+env+'}','end'); if (this.error) return null; + name = this.GetArgument(this.cmd+'end'); if (this.error) return null; + } + return body; + }, + + + /***************************************************************************/ + + + /* + * Ignore spaces + */ + Space: function () {}, + + /* + * Collect together any primes and convert them to a superscript + */ + Prime: function (c) { + var base = this.mlist.Last(); + if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac')) + {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))} + if (base.sup) {this.Error("Prime causes double exponent: use braces to clarify"); return} + var sup = ''; + while (c == "'") {sup += this.cmd+'prime'; c = this.GetNext(); if (c == "'") {this.i++}} + base.sup = this.Process(sup); + base.sup.isPrime = 1; + }, + + /* + * Raise or lower its parameter by a given amount + * @@@ Note that this is different from TeX, which requires an \hbox @@@ + * ### make this work with mu's ### + */ + RaiseLower: function (name) { + var h = this.GetDimen(this.cmd+name,1); if (this.error) return; + var box = this.ProcessScriptArg(this.cmd+name); if (this.error) return; + if (name == 'lower') {h = -h} + this.mlist.Add(new jsMath.mItem('raise',{nuc: box, raise: h})); + }, + + /* + * Shift an expression to the right or left + * @@@ Note that this is different from TeX, which requires a \vbox @@@ + * ### make this work with mu's ### + */ + MoveLeftRight: function (name) { + var x = this.GetDimen(this.cmd+name,1); if (this.error) return; + var box = this.ProcessScriptArg(this.cmd+name); if (this.error) return; + if (name == 'moveleft') {x = -x} + this.mlist.Add(jsMath.mItem.Space(x)); + this.mlist.Add(jsMath.mItem.Atom('ord',box)); + this.mlist.Add(jsMath.mItem.Space(-x)); + }, + + /* + * Load an extension if it has not already been loaded + */ + Require: function (name) { + var file = this.GetArgument(this.cmd+name); if (this.error) return; + file = jsMath.Extension.URL(file); + if (jsMath.Setup.loaded[file]) return; + this.Extension(null,[file]); + }, + + /* + * Load an extension file and restart processing the math + */ + Extension: function (name,data) { + jsMath.Translate.restart = 1; + if (name != null) {delete jsMath.Parser.prototype[data[1]||'macros'][name]} + jsMath.Extension.Require(data[0],jsMath.Translate.asynchronous); + throw "restart"; + }, + + /* + * Implements \frac{num}{den} + */ + Frac: function (name) { + var num = this.ProcessArg(this.cmd+name); if (this.error) return; + var den = this.ProcessArg(this.cmd+name); if (this.error) return; + this.mlist.Add(jsMath.mItem.Fraction('over',num,den)); + }, + + /* + * Implements \sqrt[n]{...} + */ + Sqrt: function (name) { + var n = this.GetBrackets(this.cmd+name); if (this.error) return; + var arg = this.ProcessArg(this.cmd+name); if (this.error) return; + var box = jsMath.mItem.Atom('radical',arg); + if (n != '') {box.root = this.Process(n); if (this.error) return} + this.mlist.Add(box); + }, + + /* + * Implements \root...\of{...} + */ + Root: function (name) { + var n = this.ProcessUpto(this.cmd+name,'of'); if (this.error) return; + var arg = this.ProcessArg(this.cmd+name); if (this.error) return; + var box = jsMath.mItem.Atom('radical',arg); + box.root = n; this.mlist.Add(box); + }, + + + /* + * Implements \buildrel...\over{...} + */ + BuildRel: function (name) { + var top = this.ProcessUpto(this.cmd+name,'over'); if (this.error) return; + var bot = this.ProcessArg(this.cmd+name); if (this.error) return; + var op = jsMath.mItem.Atom('op',bot); + op.limits = 1; op.sup = top; + this.mlist.Add(op); + }, + + /* + * Create a delimiter of the type and size specified in the parameters + */ + MakeBig: function (name,data) { + var type = data[0]; var h = data[1] * jsMath.p_height; + var delim = this.GetDelimiter(this.cmd+name); if (this.error) return; + this.mlist.Add(jsMath.mItem.Atom(type,jsMath.Box.Delimiter(h,delim,'T'))); + }, + + /* + * Insert the specified character in the given font. + * (Try to load the font if it is not already available.) + */ + Char: function (name) { + var font = this.GetArgument(this.cmd+name); if (this.error) return; + var n = this.GetArgument(this.cmd+name); if (this.error) return; + if (!jsMath.TeX[font]) { + jsMath.TeX[font] = []; + this.Extension(null,[jsMath.Font.URL(font)]); + } else { + this.mlist.Add(jsMath.mItem.Typeset(jsMath.Box.TeX(n-0,font,this.mlist.data.style,this.mlist.data.size))); + } + }, + + /* + * Create an array or matrix. + */ + Matrix: function (name,delim) { + var data = this.mlist.data; + var arg = this.GetArgument(this.cmd+name); if (this.error) return; + var parse = new jsMath.Parser(arg+this.cmd+'\\',null,data.size,delim[5] || 'T'); + parse.matrix = name; parse.row = []; parse.table = []; parse.rspacing = []; + parse.Parse(); if (parse.error) {this.Error(parse); return} + parse.HandleRow(name,1); // be sure the last row is recorded + var box = jsMath.Box.Layout(data.size,parse.table,delim[2]||null,delim[3]||null,parse.rspacing,delim[4]||null); + // Add parentheses, if needed + if (delim[0] && delim[1]) { + var left = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[0]],'T'); + var right = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[1]],'T'); + box = jsMath.Box.SetList([left,box,right],data.style,data.size); + } + this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box)); + }, + + /* + * When we see an '&', try to add a matrix entry to the row data. + * (Use all the data in the current mList, and then clear it) + */ + HandleEntry: function (name) { + if (!this.matrix) + {this.Error(name+" can only appear in a matrix or array"); return} + if (this.mlist.data.openI != null) { + var open = this.mlist.Get(this.mlist.data.openI); + if (open.left) {this.Error("Missing "+this.cmd+"right")} + else {this.Error("Missing close brace")} + } + if (this.mlist.data.overI != null) {this.mlist.Over()} + var data = this.mlist.data; + this.mlist.Atomize(data.style,data.size); + var box = this.mlist.Typeset(data.style,data.size); + box.entry = data.entry; delete data.entry; if (!box.entry) {box.entry = {}}; + this.row[this.row.length] = box; + this.mlist = new jsMath.mList(null,null,data.size,data.style); + }, + + /* + * When we see a \cr or \\, try to add a row to the table + */ + HandleRow: function (name,last) { + var dimen; + if (!this.matrix) {this.Error(this.cmd+name+" can only appear in a matrix or array"); return} + if (name == "\\") { + dimen = this.GetBrackets(this.cmd+name); if (this.error) return; + if (dimen) {dimen = this.ParseDimen(dimen,this.cmd+name,0,1)} + } + this.HandleEntry(name); + if (!last || this.row.length > 1 || this.row[0].format != 'null') + {this.table[this.table.length] = this.row} + if (dimen) {this.rspacing[this.table.length] = dimen} + this.row = []; + }, + + /* + * Look for \vskip or \vspace in \noalign parameters + */ + HandleNoAlign: function (name) { + var arg = this.GetArgument(this.cmd+name); if (this.error) return; + var skip = arg.replace(/^.*(vskip|vspace)([^a-z])/i,'$2'); + if (skip.length == arg.length) return; + var d = this.ParseDimen(skip,this.cmd+RegExp.$1,0,1); if (this.error) return; + this.rspacing[this.table.length] = (this.rspacing[this.table.length] || 0) + d; + }, + + /* + * LaTeX array environment + */ + Array: function (name,delim) { + var columns = delim[2]; var cspacing = delim[3]; + if (!columns) { + columns = this.GetArgument(this.cmd+'begin{'+name+'}'); + if (this.error) return; + } + columns = columns.replace(/[^clr]/g,''); + columns = columns.split(''); + var data = this.mlist.data; var style = delim[5] || 'T'; + var arg = this.GetEnd(name); if (this.error) return; + var parse = new jsMath.Parser(arg+this.cmd+'\\',null,data.size,style); + parse.matrix = name; parse.row = []; parse.table = []; parse.rspacing = []; + parse.Parse(); if (parse.error) {this.Error(parse); return} + parse.HandleRow(name,1); // be sure the last row is recorded + var box = jsMath.Box.Layout(data.size,parse.table,columns,cspacing,parse.rspacing,delim[4],delim[6],delim[7]); + // Add parentheses, if needed + if (delim[0] && delim[1]) { + var left = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[0]],'T'); + var right = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[1]],'T'); + box = jsMath.Box.SetList([left,box,right],data.style,data.size); + } + this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box)); + }, + + /* + * LaTeX \begin{env} + */ + Begin: function (name) { + var env = this.GetArgument(this.cmd+name); if (this.error) return; + if (env.match(/[^a-z*]/i)) {this.Error('Invalid environment name "'+env+'"'); return} + if (!this.environments[env]) {this.Error('Unknown environment "'+env+'"'); return} + var cmd = this.environments[env]; + if (typeof(cmd) == "string") {cmd = [cmd]} + this[cmd[0]](env,cmd.slice(1)); + }, + + /* + * LaTeX \end{env} + */ + End: function (name) { + var env = this.GetArgument(this.cmd+name); if (this.error) return; + this.Error(this.cmd+name+'{'+env+'} without matching '+this.cmd+'begin'); + }, + + /* + * LaTeX equation environment (just remove the environment) + */ + Equation: function (name) { + var arg = this.GetEnd(name); if (this.error) return; + this.string = arg+this.string.slice(this.i); this.i = 0; + }, + + /* + * Add a fixed amount of horizontal space + */ + Spacer: function (name,w) { + this.mlist.Add(jsMath.mItem.Space(w-0)); + }, + + /* + * Add horizontal space given by the argument + */ + Hskip: function (name) { + var w = this.GetDimen(this.cmd+name); if (this.error) return; + this.mlist.Add(jsMath.mItem.Space(w)); + }, + + /* + * Typeset the argument as plain text rather than math. + */ + HBox: function (name) { + var text = this.GetArgument(this.cmd+name); if (this.error) return; + var box = jsMath.Box.InternalMath(text,this.mlist.data.size); + this.mlist.Add(jsMath.mItem.Typeset(box)); + }, + + /* + * Insert a rule of a particular width, height and depth + * This replaces \hrule and \vrule + * @@@ not a standard TeX command, and all three parameters must be given @@@ + */ + Rule: function (name,style) { + var w = this.GetDimen(this.cmd+name,1); if (this.error) return; + var h = this.GetDimen(this.cmd+name,1); if (this.error) return; + var d = this.GetDimen(this.cmd+name,1); if (this.error) return; + h += d; var html; + if (h != 0) {h = Math.max(1.05/jsMath.em,h)} + if (h == 0 || w == 0 || style == "blank") + {html = jsMath.HTML.Blank(w,h)} else {html = jsMath.HTML.Rule(w,h)} + if (d) { + html = '' + + html + ''; + } + this.mlist.Add(jsMath.mItem.Typeset(new jsMath.Box('html',html,w,h-d,d))); + }, + + /* + * Inserts an empty box of a specific height and depth + */ + Strut: function () { + var size = this.mlist.data.size; + var box = jsMath.Box.Text('','normal','T',size).Styled(); + box.bh = box.bd = 0; box.h = .8; box.d = .3; box.w = box.Mw = 0; + this.mlist.Add(jsMath.mItem.Typeset(box)); + }, + + /* + * Handles \phantom, \vphantom and \hphantom + */ + Phantom: function (name,data) { + var arg = this.ProcessArg(this.cmd+name); if (this.error) return; + this.mlist.Add(new jsMath.mItem('phantom',{phantom: arg, v: data[0], h: data[1]})); + }, + + /* + * Implements \smash + */ + Smash: function (name,data) { + var arg = this.ProcessArg(this.cmd+name); if (this.error) return; + this.mlist.Add(new jsMath.mItem('smash',{smash: arg})); + }, + + /* + * Puts an accent on the following argument + */ + MathAccent: function (name,accent) { + var c = this.ProcessArg(this.cmd+name); if (this.error) return; + var atom = jsMath.mItem.Atom('accent',c); atom.accent = accent[0]; + this.mlist.Add(atom); + }, + + /* + * Handles functions and operators like sin, cos, sum, etc. + */ + NamedOp: function (name,data) { + var a = (name.match(/[^acegm-su-z]/)) ? 1: 0; + var d = (name.match(/[gjpqy]/)) ? .2: 0; + if (data[1]) {name = data[1]} + var box = jsMath.mItem.TextAtom('op',name,jsMath.TeX.fam[0],a,d); + if (data[0] != null) {box.limits = data[0]} + this.mlist.Add(box); + }, + + /* + * Implements \limits + */ + Limits: function (name,data) { + var atom = this.mlist.Last(); + if (!atom || atom.type != 'op') + {this.Error(this.cmd+name+" is allowed only on operators"); return} + atom.limits = data[0]; + }, + + /* + * Implements macros like those created by \def. The named control + * sequence is replaced by the string given as the first data value. + * If there is a second data value, this specifies how many arguments + * the macro uses, and in this case, those arguments are substituted + * for #1, #2, etc. within the replacement string. + * + * See the jsMath.Macro() command below for more details. + * The "newcommand" extension implements \newcommand and \def + * and are loaded automatically if needed. + */ + Macro: function (name,data) { + var text = data[0]; + if (data[1]) { + var args = []; + for (var i = 0; i < data[1]; i++) + {args[args.length] = this.GetArgument(this.cmd+name); if (this.error) return} + text = this.SubstituteArgs(args,text); + } + this.string = this.AddArgs(text,this.string.slice(this.i)); + this.i = 0; + }, + + /* + * Replace macro paramters with their values + */ + SubstituteArgs: function (args,string) { + var text = ''; var newstring = ''; var c; var i = 0; + while (i < string.length) { + c = string.charAt(i++); + if (c == this.cmd) {text += c + string.charAt(i++)} + else if (c == '#') { + c = string.charAt(i++); + if (c == "#") {text += c} else { + if (!c.match(/[1-9]/) || c > args.length) + {this.Error("Illegal macro parameter reference"); return null} + newstring = this.AddArgs(this.AddArgs(newstring,text),args[c-1]); + text = ''; + } + } else {text += c} + } + return this.AddArgs(newstring,text); + }, + + /* + * Make sure that macros are followed by a space if their names + * could accidentally be continued into the following text. + */ + AddArgs: function (s1,s2) { + if (s2.match(/^[a-z]/i) && s1.match(/(^|[^\\])(\\\\)*\\[a-z]+$/i)) {s1 += ' '} + return s1+s2; + }, + + /* + * Replace the control sequence with the given text + */ + Replace: function (name,data) { + this.mlist.Add(jsMath.mItem.TextAtom(data[0],data[1],data[2],data[3])); + }, + + /* + * Error for # (must use \#) + */ + Hash: function (name) { + this.Error("You can't use 'macro parameter character #' in math mode"); + }, + + /* + * Insert space for ~ + */ + Tilde: function (name) { + this.mlist.Add(jsMath.mItem.TextAtom('ord',' ','normal')); + }, + + /* + * Implements \llap, \rlap, etc. + */ + HandleLap: function (name) { + var box = this.ProcessArg(); if (this.error) return; + box = this.mlist.Add(new jsMath.mItem('lap',{nuc: box, lap: name})); + }, + + /* + * Adds the argument as a specific type of atom (for commands like + * \overline, etc.) + */ + HandleAtom: function (name,data) { + var arg = this.ProcessArg(this.cmd+name); if (this.error) return; + this.mlist.Add(jsMath.mItem.Atom(data[0],arg)); + }, + + + /* + * Process the character associated with a specific \mathcharcode + */ + HandleMathCode: function (name,code) { + this.HandleTeXchar(code[0],code[1],code[2]); + }, + + /* + * Add a specific character from a TeX font (use the current + * font if the type is 7 (variable) or the font is not specified) + * Load the font if it is not already loaded. + */ + HandleTeXchar: function (type,font,code) { + if (type == 7 && this.mlist.data.font != null) {font = this.mlist.data.font} + font = jsMath.TeX.fam[font]; + if (!jsMath.TeX[font]) { + jsMath.TeX[font] = []; + this.Extension(null,[jsMath.Font.URL(font)]); + } else { + this.mlist.Add(jsMath.mItem.TeXAtom(jsMath.TeX.atom[type],code,font)); + } + }, + + /* + * Add a TeX variable character or number + */ + HandleVariable: function (c) {this.HandleTeXchar(7,1,c.charCodeAt(0))}, + HandleNumber: function (c) {this.HandleTeXchar(7,0,c.charCodeAt(0))}, + + /* + * For unmapped characters, just add them in as normal + * (non-TeX) characters + */ + HandleOther: function (c) { + this.mlist.Add(jsMath.mItem.TextAtom('ord',c,'normal')); + }, + + /* + * Ignore comments in TeX data + * ### Some browsers remove the newlines, so this might cause + * extra stuff to be ignored; look into this ### + */ + HandleComment: function () { + var c; + while (this.i < this.string.length) { + c = this.string.charAt(this.i++); + if (c == "\r" || c == "\n") return; + } + }, + + /* + * Add a style change (e.g., \displaystyle, etc) + */ + HandleStyle: function (name,style) { + this.mlist.data.style = style[0]; + this.mlist.Add(new jsMath.mItem('style',{style: style[0]})); + }, + + /* + * Implements \small, \large, etc. + */ + HandleSize: function (name,size) { + this.mlist.data.size = size[0]; + this.mlist.Add(new jsMath.mItem('size',{size: size[0]})); + }, + + /* + * Set the current font (e.g., \rm, etc) + */ + HandleFont: function (name,font) { + this.mlist.data.font = font[0]; + }, + + /* + * Look for and process a control sequence + */ + HandleCS: function () { + var cmd = this.GetCommand(); if (this.error) return; + if (this.macros[cmd]) { + var macro = this.macros[cmd]; + if (typeof(macro) == "string") {macro = [macro]} + this[macro[0]](cmd,macro.slice(1)); return; + } + if (this.mathchardef[cmd]) { + this.HandleMathCode(cmd,this.mathchardef[cmd]); + return; + } + if (this.delimiter[this.cmd+cmd]) { + this.HandleMathCode(cmd,this.delimiter[this.cmd+cmd].slice(0,3)) + return; + } + this.Error("Unknown control sequence '"+this.cmd+cmd+"'"); + }, + + /* + * Process open and close braces + */ + HandleOpen: function () {this.mlist.Open()}, + HandleClose: function () { + if (this.mlist.data.openI == null) {this.Error("Extra close brace"); return} + var open = this.mlist.Get(this.mlist.data.openI); + if (!open || open.left == null) {this.mlist.Close()} + else {this.Error("Extra close brace or missing "+this.cmd+"right"); return} + }, + + /* + * Implements \left + */ + HandleLeft: function (name) { + var left = this.GetDelimiter(this.cmd+name); if (this.error) return; + this.mlist.Open(left); + }, + + /* + * Implements \right + */ + HandleRight: function (name) { + var right = this.GetDelimiter(this.cmd+name); if (this.error) return; + var open = this.mlist.Get(this.mlist.data.openI); + if (open && open.left != null) {this.mlist.Close(right)} + else {this.Error("Extra open brace or missing "+this.cmd+"left");} + }, + + /* + * Implements generalized fractions (\over, \above, etc.) + */ + HandleOver: function (name,data) { + if (this.mlist.data.overI != null) + {this.Error('Ambiguous use of '+this.cmd+name); return} + this.mlist.data.overI = this.mlist.Length(); + this.mlist.data.overF = {name: name}; + if (data.length > 0) { + this.mlist.data.overF.left = this.delimiter[data[0]]; + this.mlist.data.overF.right = this.delimiter[data[1]]; + } else if (name.match(/withdelims$/)) { + this.mlist.data.overF.left = this.GetDelimiter(this.cmd+name); if (this.error) return; + this.mlist.data.overF.right = this.GetDelimiter(this.cmd+name); if (this.error) return; + } else { + this.mlist.data.overF.left = null; + this.mlist.data.overF.right = null; + } + if (name.match(/^above/)) { + this.mlist.data.overF.thickness = this.GetDimen(this.cmd+name,1); + if (this.error) return; + } else { + this.mlist.data.overF.thickness = null; + } + }, + + /* + * Add a superscript to the preceeding atom + */ + HandleSuperscript: function () { + var base = this.mlist.Last(); + if (this.mlist.data.overI == this.mlist.Length()) {base = null} + if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac')) + {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))} + if (base.sup) { + if (base.sup.isPrime) {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))} + else {this.Error("Double exponent: use braces to clarify"); return} + } + base.sup = this.ProcessScriptArg('superscript'); if (this.error) return; + }, + + /* + * Add a subscript to the preceeding atom + */ + HandleSubscript: function () { + var base = this.mlist.Last(); + if (this.mlist.data.overI == this.mlist.Length()) {base = null} + if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac')) + {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))} + if (base.sub) {this.Error("Double subscripts: use braces to clarify"); return} + base.sub = this.ProcessScriptArg('subscript'); if (this.error) return; + }, + + /* + * Parse a TeX math string, handling macros, etc. + */ + Parse: function () { + var c; + while (this.i < this.string.length) { + c = this.string.charAt(this.i++); + if (this.mathchar[c]) {this.HandleMathCode(c,this.mathchar[c])} + else if (this.special[c]) {this[this.special[c]](c)} + else if (this.letter.test(c)) {this.HandleVariable(c)} + else if (this.number.test(c)) {this.HandleNumber(c)} + else {this.HandleOther(c)} + } + if (this.mlist.data.openI != null) { + var open = this.mlist.Get(this.mlist.data.openI); + if (open.left) {this.Error("Missing "+this.cmd+"right")} + else {this.Error("Missing close brace")} + } + if (this.mlist.data.overI != null) {this.mlist.Over()} + }, + + /* + * Perform the processing of Appendix G + */ + Atomize: function () { + var data = this.mlist.init; + if (!this.error) this.mlist.Atomize(data.style,data.size) + }, + + /* + * Produce the final HTML. + * + * We have to wrap the HTML it appropriate tags to hide its + * actual dimensions when these don't match the TeX dimensions of the + * results. We also include an image to force the results to take up + * the right amount of space. The results may need to be vertically + * adjusted to make the baseline appear in the correct place. + */ + Typeset: function () { + var data = this.mlist.init; + var box = this.typeset = this.mlist.Typeset(data.style,data.size); + if (this.error) {return ''+this.error+''} + if (box.format == 'null') {return ''}; + + box.Styled().Remeasured(); var isSmall = 0; var isBig = 0; + if (box.bh > box.h && box.bh > jsMath.h+.001) {isSmall = 1} + if (box.bd > box.d && box.bd > jsMath.d+.001) {isSmall = 1} + if (box.h > jsMath.h || box.d > jsMath.d) {isBig = 1} + + var html = box.html; + if (isSmall) {// hide the extra size + if (jsMath.Browser.allowAbsolute) { + var y = 0; + if (box.bh > jsMath.h+.001) {y = jsMath.h - box.bh} + html = jsMath.HTML.Absolute(html,box.w,jsMath.h,0,y); + } else if (jsMath.Browser.valignBug) { + // remove line height + html = '' + + html + ''; + } else if (!jsMath.Browser.operaLineHeightBug) { + // remove line height and try to hide the depth + var dy = jsMath.HTML.Em(Math.max(0,box.bd-jsMath.hd)/3); + html = '' + html + ''; + } + isBig = 1; + } + if (isBig) { + // add height and depth to the line + // (force a little extra to separate lines if needed) + html += jsMath.HTML.Blank(0,box.h+.05,box.d+.05); + } + return ''+html+''; + } + +}); + +/* + * Make these characters special (and call the given routines) + */ +jsMath.Parser.prototype.AddSpecial({ + cmd: 'HandleCS', + open: 'HandleOpen', + close: 'HandleClose' +}); + + +/* + * The web-page author can call jsMath.Macro to create additional + * TeX macros for use within his or her mathematics. See the + * author's documentation for more details. + */ + +jsMath.Add(jsMath,{ + Macro: function (name) { + var macro = jsMath.Parser.prototype.macros; + macro[name] = ['Macro']; + for (var i = 1; i < arguments.length; i++) + {macro[name][macro[name].length] = arguments[i]} + } +}); + +/* + * Use these commands to create macros that load + * JavaScript files and reprocess the mathematics when + * the file is loaded. This lets you to have macros or + * LaTeX environments that autoload their own definitions + * only when they are needed, saving initial download time + * on pages where they are not used. See the author's + * documentation for more details. + * + */ + +jsMath.Extension = { + + safeRequire: 1, // disables access to files outside of jsMath/extensions + + Macro: function (name,file) { + var macro = jsMath.Parser.prototype.macros; + if (file == null) {file = name} + macro[name] = ['Extension',file]; + }, + + LaTeX: function (env,file) { + var latex = jsMath.Parser.prototype.environments; + latex[env] = ['Extension',file,'environments']; + }, + + Font: function (name,font) { + if (font == null) {font = name + "10"} + var macro = jsMath.Parser.prototype.macros; + macro[name] = ['Extension',jsMath.Font.URL(font)]; + }, + + MathChar: function (font,defs) { + var fam = jsMath.TeX.famName[font]; + if (fam == null) { + fam = jsMath.TeX.fam.length; + jsMath.TeX.fam[fam] = font; + jsMath.TeX.famName[font] = fam; + } + var mathchardef = jsMath.Parser.prototype.mathchardef; + for (var c in defs) {mathchardef[c] = [defs[c][0],fam,defs[c][1]]} + }, + + Require: function (file,show) { + if (this.safeRequire && (file.match(/\.\.\/|[^-a-z0-9.\/:_+=%~]/i) || + (file.match(/:/) && file.substr(0,jsMath.root.length) != jsMath.root))) { + jsMath.Setup.loaded[file] = 1; + return; + } + jsMath.Setup.Script(this.URL(file),show); + }, + + URL: function (file) { + file = file.replace(/^\s+|\s+$/g,''); + if (!file.match(/^([a-z]+:|\/|fonts|extensions\/)/i)) {file = 'extensions/'+file} + if (!file.match(/\.js$/)) {file += '.js'} + return file; + } +} + + +/***************************************************************************/ + +/* + * These routines look through the web page for math elements to process. + * There are two main entry points you can call: + * + * + * or + * + * + * The first will process the page asynchronously (so the user can start + * reading the top of the file while jsMath is still processing the bottom) + * while the second does not update until all the mathematics is typeset. + */ + +jsMath.Add(jsMath,{ + /* + * Call this at the bottom of your HTML page to have the + * mathematics typeset asynchronously. This lets the user + * start reading the mathematics while the rest of the page + * is being processed. + */ + Process: function (obj) { + jsMath.Setup.Body(); + jsMath.Script.Push(jsMath.Translate,'Asynchronous',obj); + }, + + /* + * Call this at the bottom of your HTML page to have the + * mathematics typeset before the page is displayed. + * This can take a long time, so the user could cancel the + * page before it is complete; use it with caution, and only + * when there is a relatively small amount of math on the page. + */ + ProcessBeforeShowing: function (obj) { + jsMath.Setup.Body(); + var method = (jsMath.Controls.cookie.asynch ? "Asynchronous": "Synchronous"); + jsMath.Script.Push(jsMath.Translate,method,obj); + }, + + /* + * Process the contents of a single element. It must be of + * class "math". + */ + ProcessElement: function (obj) { + jsMath.Setup.Body(); + jsMath.Script.Push(jsMath.Translate,'ProcessOne',obj); + } + +}); + +jsMath.Translate = { + + element: [], // the list of math elements on the page + cancel: 0, // set to 1 to cancel asynchronous processing + + /* + * Parse a TeX string in Text or Display mode and return + * the HTML for it (taking it from the cache, if available) + */ + Parse: function (style,s,noCache) { + var cache = jsMath.Global.cache[style]; + if (!cache[jsMath.em]) {cache[jsMath.em] = {}} + var HTML = cache[jsMath.em][s]; + if (!HTML || noCache) { + var parse = jsMath.Parse(s,null,null,style); + parse.Atomize(); HTML = parse.Typeset(); + if (!noCache) {cache[jsMath.em][s] = HTML} + } + return HTML; + }, + + TextMode: function (s,noCache) {this.Parse('T',s,noCache)}, + DisplayMode: function (s,noCache) {this.Parse('D',s,noCache)}, + + /* + * Return the text of a given DOM element + */ + GetElementText: function (element) { + if (element.childNodes.length == 1 && element.childNodes[0].nodeName === "#comment") { + var result = element.childNodes[0].nodeValue.match(/^\[CDATA\[(.*)\]\]$/); + if (result != null) {return result[1]}; + } + var text = this.recursiveElementText(element); + element.alt = text; + if (text.search('&') >= 0) { + text = text.replace(/</g,'<'); + text = text.replace(/>/g,'>'); + text = text.replace(/"/g,'"'); + text = text.replace(/&/g,'&'); + } + return text; + }, + recursiveElementText: function (element) { + if (element.nodeValue != null) { + if (element.nodeName !== "#comment") {return element.nodeValue} + return element.nodeValue.replace(/^\[CDATA\[((.|\n)*)\]\]$/,"$1"); + } + if (element.childNodes.length === 0) {return " "} + var text = ''; + for (var i = 0; i < element.childNodes.length; i++) + {text += this.recursiveElementText(element.childNodes[i])} + return text; + }, + + /* + * Move hidden to the location of the math element to be + * processed and reinitialize sizes for that location. + */ + ResetHidden: function (element) { + element.innerHTML = + '' + + jsMath.Browser.operaHiddenFix; // needed by Opera in tables + element.className = ''; + jsMath.hidden = element.firstChild; + if (!jsMath.BBoxFor("x").w) {jsMath.hidden = jsMath.hiddenTop} + jsMath.ReInit(); + }, + + + /* + * Typeset the contents of an element in \textstyle or \displaystyle + */ + ConvertMath: function (style,element,noCache) { + var text = this.GetElementText(element); + this.ResetHidden(element); + if (text.match(/^\s*\\nocache([^a-zA-Z])/)) + {noCache = true; text = text.replace(/\s*\\nocache/,'')} + text = this.Parse(style,text,noCache); + element.className = 'typeset'; + element.innerHTML = text; + }, + + /* + * Process a math element + */ + ProcessElement: function (element) { + this.restart = 0; + if (!element.className.match(/(^| )math( |$)/)) return; // don't reprocess elements + var noCache = (element.className.toLowerCase().match(/(^| )nocache( |$)/) != null); + try { + var style = (element.tagName.toLowerCase() == 'div' ? 'D' : 'T'); + this.ConvertMath(style,element,noCache); + element.onclick = jsMath.Click.CheckClick; + element.ondblclick = jsMath.Click.CheckDblClick; + } catch (err) { + if (element.alt) { + var tex = element.alt; + tex = tex.replace(/&/g,'&') + .replace(//g,'>'); + element.innerHTML = tex; + element.className = 'math'; + if (noCache) {element.className += ' nocache'} + } + jsMath.hidden = jsMath.hiddenTop; + } + }, + + /* + * Asynchronously process all the math elements starting with + * the k-th one + */ + ProcessElements: function (k) { + jsMath.Script.blocking = 1; + if (k >= this.element.length || this.cancel) { + this.ProcessComplete(); + if (this.cancel) { + jsMath.Message.Set("Process Math: Canceled"); + jsMath.Message.Clear() + } + jsMath.Script.blocking = 0; + jsMath.Script.Process(); + } else { + var savedQueue = jsMath.Script.SaveQueue(); + this.ProcessElement(this.element[k]); + if (this.restart) { + jsMath.Script.Push(this,'ProcessElements',k); + jsMath.Script.RestoreQueue(savedQueue); + jsMath.Script.blocking = 0; + setTimeout('jsMath.Script.Process()',jsMath.Browser.delay); + } else { + jsMath.Script.RestoreQueue(savedQueue); + k++; var p = Math.floor(100 * k / this.element.length); + jsMath.Message.Set('Processing Math: '+p+'%'); + setTimeout('jsMath.Translate.ProcessElements('+k+')',jsMath.Browser.delay); + } + } + }, + + /* + * Start the asynchronous processing of mathematics + */ + Asynchronous: function (obj) { + if (!jsMath.initialized) {jsMath.Init()} + this.element = this.GetMathElements(obj); + jsMath.Script.blocking = 1; + this.cancel = 0; this.asynchronous = 1; + jsMath.Message.Set('Processing Math: 0%',1); + setTimeout('jsMath.Translate.ProcessElements(0)',jsMath.Browser.delay); + }, + + /* + * Do synchronous processing of mathematics + */ + Synchronous: function (obj,i) { + if (i == null) { + if (!jsMath.initialized) {jsMath.Init()} + this.element = this.GetMathElements(obj); + i = 0; + } + this.asynchronous = 0; + while (i < this.element.length) { + this.ProcessElement(this.element[i]); + if (this.restart) { + jsMath.Synchronize('jsMath.Translate.Synchronous(null,'+i+')'); + jsMath.Script.Process(); + return; + } + i++; + } + this.ProcessComplete(1); + }, + + /* + * Synchronously process the contents of a single element + */ + ProcessOne: function (obj) { + if (!jsMath.initialized) {jsMath.Init()} + this.element = [obj]; + this.Synchronous(null,0); + }, + + /* + * Look up all the math elements on the page and + * put them in a list sorted from top to bottom of the page + */ + GetMathElements: function (obj) { + var element = []; var k; + if (!obj) {obj = jsMath.document} + if (typeof(obj) == 'string') {obj = jsMath.document.getElementById(obj)} + if (!obj.getElementsByTagName) return null; + var math = obj.getElementsByTagName('div'); + for (k = 0; k < math.length; k++) { + if (math[k].className && math[k].className.match(/(^| )math( |$)/)) { + if (jsMath.Browser.renameOK && obj.getElementsByName) + {math[k].setAttribute('name','_jsMath_')} + else {element[element.length] = math[k]} + } + } + math = obj.getElementsByTagName('span'); + for (k = 0; k < math.length; k++) { + if (math[k].className && math[k].className.match(/(^| )math( |$)/)) { + if (jsMath.Browser.renameOK && obj.getElementsByName) + {math[k].setAttribute('name','_jsMath_')} + else {element[element.length] = math[k]} + } + } + // this gets the SPAN and DIV elements interleaved in order + if (jsMath.Browser.renameOK && obj.getElementsByName) { + element = obj.getElementsByName('_jsMath_'); + } else if (jsMath.hidden.sourceIndex) { + element.sort(function (a,b) {return a.sourceIndex - b.sourceIndex}); + } + return element; + }, + + /* + * Remove the window message about processing math + * and clean up any marked or
tags + */ + ProcessComplete: function (noMessage) { + if (jsMath.Browser.renameOK) { + var element = jsMath.document.getElementsByName('_jsMath_'); + for (var i = element.length-1; i >= 0; i--) { + element[i].removeAttribute('name'); + } + } + jsMath.hidden = jsMath.hiddenTop; + this.element = []; this.restart = null; + if (!noMessage) { + jsMath.Message.Set('Processing Math: Done'); + jsMath.Message.Clear(); + } + jsMath.Message.UnBlank(); + if (jsMath.Browser.safariImgBug && + (jsMath.Controls.cookie.font == 'symbol' || + jsMath.Controls.cookie.font == 'image')) { + // + // For Safari, the images don't always finish + // updating, so nudge the window to cause a + // redraw. (Hack!) + // + if (this.timeout) {clearTimeout(this.timeout)} + this.timeout = setTimeout("jsMath.window.resizeBy(-1,0); " + + "jsMath.window.resizeBy(1,0); " + + "jsMath.Translate.timeout = null",2000); + } + }, + + /* + * Cancel procesing elements + */ + Cancel: function () { + jsMath.Translate.cancel = 1; + if (jsMath.Script.cancelTimer) {jsMath.Script.cancelLoad()} + } + +}; + +jsMath.Add(jsMath,{ + // + // Synchronize these with the loading of the tex2math plugin. + // + ConvertTeX: function (element) {jsMath.Script.Push(jsMath.tex2math,'ConvertTeX',element)}, + ConvertTeX2: function (element) {jsMath.Script.Push(jsMath.tex2math,'ConvertTeX2',element)}, + ConvertLaTeX: function (element) {jsMath.Script.Push(jsMath.tex2math,'ConvertLaTeX',element)}, + ConvertCustom: function (element) {jsMath.Script.Push(jsMath.tex2math,'ConvertCustom',element)}, + CustomSearch: function (om,cm,od,cd) {jsMath.Script.Push(null,function () {jsMath.tex2math.CustomSearch(om,cm,od,cd)})}, + tex2math: { + ConvertTeX: function () {}, + ConvertTeX2: function () {}, + ConvertLaTeX: function () {}, + ConvertCustom: function () {}, + CustomSearch: function () {} + } +}); +jsMath.Synchronize = jsMath.Script.Synchronize; + +/***************************************************************************/ + + +/* + * Initialize things + */ +try { + if (window.parent != window && window.jsMathAutoload) { + window.parent.jsMath = jsMath; + jsMath.document = window.parent.document; + jsMath.window = window.parent; + } +} catch (err) {} + + +jsMath.Global.Register(); +jsMath.Loaded(); +jsMath.Controls.GetCookie(); +jsMath.Setup.Source(); +jsMath.Global.Init(); +jsMath.Script.Init(); +jsMath.Setup.Fonts(); +if (jsMath.document.body) {jsMath.Setup.Body()} +jsMath.Setup.User("onload"); + +}} diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/madis-screen.png b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/madis-screen.png new file mode 100644 index 0000000..9543d47 Binary files /dev/null and b/interactive-mining-3rdparty-madis/madis/src/docs/source/_static/madis-screen.png differ diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/about.txt b/interactive-mining-3rdparty-madis/madis/src/docs/source/about.txt new file mode 100644 index 0000000..66df0e4 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/about.txt @@ -0,0 +1,54 @@ +About +********** + +madIS is a extensible relational database system build upon the SQLite database and with extensions written in Python. + +It was designed and created by a small team of developers at the MaDgIK lab of the National and Kapodistrian University of Athens, under the surpevising of professor Yannis Ioannidis. + +The extensibility permits quick experimentation concerning data analysis tasks, rapid development of data processing workflows and serves in general as a simple and easy environment to test database related ideas without much effort. +madIS' query language is SQL with some syntactic "extensions" aiming to simplify query composition. + + +madIS main design goals are: + +- To be easy, and versatile + +- To be extremely productive for data analysis and data processing tasks + +- Maximum reusability of extensions + +In practice madIS has proved to be extremely easy when adding new functionalities to it, very fast in developing new workflows and most of all the majority of the external functions written for madIS, have proven to be reusable in new tasks for which they were not designed for. + +madIS is suitable for +======================= + +Complex data analysis tasks +---------------------------- + +In madIS it is very easy to create additional relational functions, or join against external files without first importing them into the database. + +Additionally madIS offers a very fast multidimensional index, greatly speeding up multi-constraint joins, even when joining against external sources. + +Data transformations +--------------------- + +madIS can already use the file system or network sources as tables. In addition, with a little Python knowledge, complex data transformation functions can be created and be used inside the database. All these can be done even without importing anything inside the database. + +In addition madIS offers a very easy, to work with, workflow engine to automate the data transformation steps. + +Database research +------------------- + +If you wish to develop and test a new indexing structure, it can easily be developed in madIS. madIS uses Python for its extensions and already has plenty of code to start from. + + +.. note:: + Due to madIS' SQLite core, the database format of madIS is exactly the same as SQLite's one. + This means that all SQLite databases are directly usable with madIS. + +.. seealso:: + + * `SQLite `_ + * `Python `_ + * `APSW `_ + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/conf.py b/interactive-mining-3rdparty-madis/madis/src/docs/source/conf.py new file mode 100644 index 0000000..51b9a1b --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/conf.py @@ -0,0 +1,215 @@ +# -*- coding: utf-8 -*- +# +# madIS documentation build configuration file, created by +# sphinx-quickstart on Thu Nov 26 16:25:19 2009. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.append(os.path.abspath('.')) +sys.path.append(os.path.abspath(os.path.dirname(__file__)+'../../../')) +import functions + +#sys.path.append(os.path.abspath(os.path.dirname(__file__)+'\\..\\..\\')) +# -- General configuration ----------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.jsmath', 'sphinx.ext.ifconfig'] + +# JSMath extension option +jsmath_path='jsMath/easy/load.js' + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.txt' + +# The encoding of source files. +#source_encoding = 'utf-8' + +def process_signature(app, what, name, obj, opts, sig, ann): + if what == 'function': + return "" + +def setup(app): + app.connect('autodoc-process-signature', process_signature) + + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'madIS' +copyright = u'2009-2010, L. Stamatogiannakis, M. Triantafyllidi, M. Vayanou, M. Kyriakidi' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = functions.VERSION +# The full version, including alpha/beta/rc tags. +release = version + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +add_module_names = False + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. Major themes that come with +# Sphinx are currently 'default' and 'sphinxdoc'. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} +html_theme_options = {} #{'stickysidebar': True} + + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +html_logo = 'madislog.png' + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_use_modindex = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +html_split_index = True + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'madisdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'madis.tex', u'madIS Documentation', + u'mlmlml', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/examples.txt b/interactive-mining-3rdparty-madis/madis/src/docs/source/examples.txt new file mode 100644 index 0000000..321930c --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/examples.txt @@ -0,0 +1,192 @@ +Examples +******** + +.. _pivoting: + +.. highlight:: mysql + +Pivot +===== + +First import data from a tsv file (Tab Separated Values) with :func:`~functions.vtable.file.file` virtual table function. +:download:`sales.tsv <../../functions/row/testing/sales.tsv>` + +.. code-block:: python + + >>> sql("""create table sales as + ... select Product,Region,Month,cast(Sales as int) as Sales + ... from + ... (file 'testing/sales.tsv' 'dialect:tsv' header:t)""") + >>> sql("select * from sales") + Product | Region | Month | Sales + ---------------------------------- + Cars | Athens | 2010-01 | 200 + Cars | Athens | 2010-02 | 130 + Bikes | NY | 2010-01 | 10 + Bikes | NY | 2010-02 | 30 + Cars | NY | 2010-01 | 100 + Cars | NY | 2010-02 | 160 + Cars | Paris | 2010-01 | 70 + Cars | Paris | 2010-02 | 20 + Bikes | Paris | 2010-01 | 100 + Bikes | Paris | 2010-02 | 20 + Boats | Paris | 2010-01 | 200 + +Let's say we want the result to be a table with columns: + +- Product +- NY: the total sales in NY for this product +- Paris: the total sales in Paris for this product +- Athens: the total sales in Athens for this product + +We will perform the aggregate function *sum* over *Sales* column, grouping by *Product* and *Region* columns. +Then :func:`~functions.aggregate.packing.vecpack` must be performed over *Region* and *Sales* sums, grouping on *Product*. + +To use :func:`~functions.aggregate.packing.vecpack` the first argument must be a pack of the dimensions. This is the +result of packing the distinct *Region* values, grouping over all the table. + +.. code-block:: python + + >>> sql("""select Product,unpackcol(vpck) + ... from + ... (select Product,vecpack(rpk,Region,salessum) as vpck + ... from + ... (select pack(distinct Region) as rpk from sales), + ... (select Product,Region,sum(sales) as salessum + ... from sales group by Product,Region) + ... group by Product)""") + Product | Paris | NY | Athens + ------------------------------ + Bikes | 120 | 40 | 0 + Boats | 200 | 0 | 0 + Cars | 90 | 260 | 330 + + +.. _applexample: + + +Application scenario +==================== + + +In this example we implement a simple application for query recommendation based on user's country of origin. The input data come from a web portal's logs. + +The query mining workflow includes the following five main steps: + +1. Import the portal log files into a relational table +2. Use time-heuristics so as to identify coherent query sessions. + Assign and store a new, reconstructed session id for each record in the logs +3. Preprocess and clean logged queries text +4. Retrieve IP-to-country information from the web and combine this with the IP information from portal log files + so as to assign a country code to each one of the logged sessions +5. Apply an `Apriori-based `_ technique for extracting frequent term sets per country. + +A sample from the log file used is presented below: + +.. code-block:: none + + 36506 guest X.X.X.134 p93t9q5eqaa0u0p8isd9skp1n6 en ("paradis riedinger") search_sim 2010-01-01 00:28:23 + 36507 guest X.X.X.134 p93t9q5eqaa0u0p8isd9skp1n6 en ("paradis riedinger") view_brief 2010-01-01 00:28:34 + 36508 guest X.X.X.134 p93t9q5eqaa0u0p8isd9skp1n6 en ("paradis riedinger") view_brief 2010-01-01 00:28:34 + 36509 guest X.X.X.134 p93t9q5eqaa0u0p8isd9skp1n6 en ("paradis riedinger") view_full 2010-01-01 00:28:42 + 36510 guest X.X.X.55 a9qo379qnl5hbbria6tj6nlp95 de (creator all "frank leonhard") search_adv 2010-01-01 00:28:44 + 36511 guest X.X.X.55 a9qo379qnl5hbbria6tj6nlp95 de (creator all "frank leonhard") view_brief 2010-01-01 00:29:10 + 36512 guest X.X.X.55 a9qo379qnl5hbbria6tj6nlp95 de (creator all "frank leonhard") search_res 2010-01-01 00:29:18 + + +**Step 1** + +Initially, log files which are available in the Tab Separated Value format, are imported into a relational table. +The import process is easily implemented in madIS using the :func:`~functions.vtable.file.file` function, +by selecting the appropriate columns from the ".tsv" file. + +:: + + create table logs as + select C1 as id, C2 as userid, C3 as userip, C4 as sesid, C6 as query, c7 as action, C8 as date + from file('raw_logs.tsv','delimiter:\t','quoting:QUOTE_NONE'); + +**Step 2** + +Thereafter, session reconstruction, a common task in web usage mining, is performed. +In this example it uses a predefined inactivity thresholds to break in-coming sessions. +Such functionality is performed in madIS through the :func:`~functions.aggregate.subgroup.datediffbreak` function, +which takes as an argument the inactivity threshold (as well as some additional parameters) and returns the new session ids. +In the following madSQL segment, where the efficient employment of the described function is presented, +the inactivity threshold has been set to 30 minutes (provided in milliseconds). + +:: + + alter table logs add sesidnew text; + update logs + set sesidnew= + (select bgroupid + from + ( cache select datediffbreak(sesid,id,date,30*60*1000,'order',date,id) + from logs + where sesid not null group by sesid) + where C1=id ) + where sesid is not null; + +**Step 3** + +Then, focusing on issued queries, the distinct queries per session are retrieved from the logs +and a variety of query text processing steps take place. +However, a great amount of malformed queries has been observed, so it is only queries of valid text in utf8 encoding that are selected. +This filtering step is performed using the :func:`~functions.row.text.isvalidutf8` function in the where clause of the corresponding madSQL fragment.  + +Thereafter, stop word removal is performed over the selected queries through the corresponding function. +Moreover, since queries are issued and logged using the Common Query Language (CQL) syntax, an additional filtering step is executed for removing *CQL* constructs, +through the madIS function :func:`~functions.row.text.cqlkeywords`. The processed queries are then stored in table *QueriesPerSession*. +One of the advantages offered by madIS framework, is that all the powerful Python capabilities and +open source libraries for text processing can be exploited for the rapid implementation of customized functions, +hence significantly easing the “flow-level programmingâ€, in madSQL. + +:: + + create table QueriesPerSession as + select filterstopwords(cqlkeywords(query)) as cleanquery , sesidnew, userid + from logs + where action like 'search%' and cleanquery!='' and isvalidutf8(query) + group by query, sesidnew; + +**Step 4** + +Aiming towards the extraction of term associations per country, an external data source is fetched from the web, +containing the mapping between IP ranges and countries. +Again, the :func:`~functions.vtable.file.file` function is employed for fetching the URL resource and importing the corresponding data in a main memory +indexed table using the :func:`~functions.vtable.cache.cache` function of madIS. The fetched data source specifies the IP ranges in IP long number format, +so the logged IPs have to be converted to the same format by using :func:`~functions.row.iptools.ip2long` function, and then to be subsequently matched +to the imported ranges. However, since each session may contain requests from multiple IPs (due to dynamic IPs, etc.), +it is only the first encountered IP that is considered for each session. +The first IP for each session is obtained using the :func:`~functions.aggregate.selection.minrow` function, comparing the corresponding records’ ids. +The generated mapping from each session to a country code is stored in table Session2Country. + +:: + + create temporary table Session2Country as + select sesidnew, CountryCode + from + (select ip2long(minrow(id,userip)) as iplong, sesidnew + from logs + group by sesidnew), + (cache select cast(C3 as integer) as ipfrom, cast(C4 as integer) as ipto, C5 as CountryCode + from file('http://.../GeoIPCountryCSV.zip','dialect:csv','compression:t')) + where iplong>=ipfrom and iplong <= ipto; + +**Step 5** + +Then information regarding text of queries, and session to country mappings is jointly used so as to extract term associations, +with an `apriori-like `_ technique, using the aggregate function :func:`~functions.aggregate.mining.freqitemsets`. +Frequent query term sets are computed over each one of the country codes that occur in Session2Country table. + +:: + + create table FrequentItemsets as + select 'nat', CountryCode, + freqitemsets(cleanquery,'threshold:2','maxlen:5') + from QueriesPerSession as qs, Session2Country as sc + where qs.sesidnew = sc.sesidnew + group by CountryCode; + + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/extending.txt b/interactive-mining-3rdparty-madis/madis/src/docs/source/extending.txt new file mode 100644 index 0000000..e275cea --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/extending.txt @@ -0,0 +1,20 @@ +Where to create functions +------------------------- + +Row functions HOWTO +------------------- + +Aggregate functions HOWTO +------------------------- + + +Virtual table functions HOWTO +----------------------------- + + +Debugging +--------- + + +Global settings +--------------- \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/index.txt b/interactive-mining-3rdparty-madis/madis/src/docs/source/index.txt new file mode 100644 index 0000000..1c04585 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/index.txt @@ -0,0 +1,49 @@ +.. madIS documentation master file, created by + sphinx-quickstart on Thu Nov 26 16:25:19 2009. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +madIS documentation +=================== + ++--------------------------------------------------------------+ +| | +|" Making the simple complicated is commonplace; | +| making the complicated simple, awesomely simple... | +| that's creativity. " | +| | ++--------------------------------------------------------------+ + +.. centered:: madIS |version| + +madIS is a extensible relational database system build upon the SQLite database and with extensions written in Python. + +The extensibility permits quick experimentation concerning data analysis tasks, rapid development of data processing workflows and serves in general as a simple and easy environment to test database related ideas without much effort. +madIS' query language is SQL with some syntactic "extensions" aiming to simplify query composition. + +madIS is hosted at http://code.google.com/p/madis/ + +Contents: + +.. toctree:: + :maxdepth: 3 + + install + about + manual + usefulnotes + examples + row + aggregate + vtable + people + license + thanks + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/install.txt b/interactive-mining-3rdparty-madis/madis/src/docs/source/install.txt new file mode 100644 index 0000000..4fb0557 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/install.txt @@ -0,0 +1,60 @@ +Installing madIS +================ + +The requirements for using madIS are: + +1. **Python 2.6.x** or **2.7.x**: You can download a windows distribution of Python from + http://www.python.org/download/releases/ .You need to download the latest + Python in the 2.6 or 2.7 series. madIS doesn't currently work with Python 3.0. + +.. note:: + Most Linux distributions come with Python 2.6 or Python 2.7 preinstalled. + +2. **APSW**: + + Windows: + + Download the windows distribution of `APSW` from http://code.google.com/p/apsw/downloads/list . + + Linux: + + Most Linux distributions contain in their repositories a sufficiently recent version of `APSW`. + If you use Ubuntu 10.04 and later, install the `python-apsw` package:: + + sudo apt-get install python-apsw + + In case `APSW` is not provided with your Linux distribution of choise, `APSW` should be build from source. + The detailed instructions for building `APSW` can be found at: + + http://apidoc.apsw.googlecode.com/hg/build.html#recommended + + A quick command line to build and install `APSW` is:: + + sudo python setup.py fetch --all --missing-checksum-ok build install + + If you are using Ubuntu and wish to build `APSW` from source, you also need the packages:: + + build-essential libreadline5-dev zlib1g-dev python-dev + + MacOS: + + On *MacOS 10.6* install `APSW` and `readline` via `easy_install`:: + + easy_install apsw + easy_install readline + + On *MacOS 10.7* you have to build `APSW` from source (as showed above), for which you'll + also need *Xcode*. + + After building `APSW`, install `readline` via `easy_install`:: + + sudo easy_install readline + +3. Download the madIS archive (.zip) from: + + http://code.google.com/p/madis/downloads/list + +4. Uncompress above zip file + +5. Use madis by entering into the new "madis/" path and executing "python mterm.py" + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/license.txt b/interactive-mining-3rdparty-madis/madis/src/docs/source/license.txt new file mode 100644 index 0000000..983ea9f --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/license.txt @@ -0,0 +1,32 @@ +Copyright and License +===================== + +Copyright (C) 2009-2013 Lefteris Stamatogiannakis, Mei Li Triantafyllidi, +Ioannis Foufoulas, Maria Vayanou, Marialena Kyriakidi. + +The external libraries used throughout the madIS project are copyright +of their respective authors. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +* The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + +* Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. + +* This notice may not be removed or altered from any source + distribution. + + +Alternatively you may strike the license above and use it under any +OSI approved open source license such as those listed at +http://opensource.org/licenses/alphabetical diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/madislog.png b/interactive-mining-3rdparty-madis/madis/src/docs/source/madislog.png new file mode 100644 index 0000000..db2098c Binary files /dev/null and b/interactive-mining-3rdparty-madis/madis/src/docs/source/madislog.png differ diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/manual.txt b/interactive-mining-3rdparty-madis/madis/src/docs/source/manual.txt new file mode 100644 index 0000000..280cd1a --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/manual.txt @@ -0,0 +1,564 @@ +.. highlight:: sql + +Manual +######### + +Functions +********* + +Functions are the main mechanism with which extensions are implemented. +The are three kinds of functions: + +- Row functions + +- Aggregate functions + +- Virtual tables + +madIS also provides syntactic extensions, in its supported SQL, that simplify the use of above functions. + +.. seealso:: + + * :ref:`row-functions-list` + * :ref:`aggregate-functions-list` + * :ref:`vtable-functions-list` + +Row functions + +Programmable row functions work in a similar way as standard SQL row functions such as *abs()*, *lower()* and *upper()*. +Their implementation is done in Python, and they are able to use all Python facilities and libraries. + +An example of an SQL statement using an external row function is:: + + mterm> select detectlang('Il en est des livres comme du feu de nos foyers'); + french + +Above statement executes the *detectlang* function, which tries to detect the language of a snippet of text by analysing its statistical properties. +On the above example the snippet is a Voltaire quote, and the correct answer from *detectlang* is that it is in french. + +If we wished to do the same for multiple quotes then we could use the following SQL statement (assuming the existence of a *quotes_table* which contains the column *quote*):: + + mterm> select detectlang(quote) from quotes_table; + french + english + ... + +In general external row functions can be used in exactly the same way as SQLite's internal row functions. + +.. seealso:: + + * :ref:`row-functions-list` + * :func:`~functions.row.langtools.detectlang` + +Creating and using a simple row function +---------------------------------------- + +Python files that implement row functions live in "/src/functions/row". A single python file can contain many row functions. +Now lets create a simple "hello world" row function. + +Go to the "src/functions/row/" path of madIS, and create "hello.py". Then write the following code in it: + +.. sourcecode:: python + + def hello(*args): + return "hello "+args[0] + + hello.registered=True + +The code above, looks like and indeed is, a simple python function that takes multiple arguments. +The only peculiarity is the "hello.registered=True" line. +What this line does, is to instruct madIS to register this function with the SQLite core. +This way, Python functions that we don't wish to become SQLite row functions, can simply be used without any change to them. + +To execute the above row function we start madIS and execute an SQL query which uses the new *hello* row function:: + + % python mterm.py + mterm> select hello("world"); + hello world + + +The SQL query above, shows the results of calling *hello* function with "world" as a parameter. +As happens very often in SQL queries, parameter values are retrieved from tables. +Below we show such an example:: + + mterm> select "world" as a UNION select "all" as a; + all + world + Query executed in 0 min. 0 sec 3 msec + mterm> select hello(a) from (select "world" as a UNION select "all" as a); + hello all + hello world + Query executed in 0 min. 0 sec 7 msec + +When developing custom row functions it is very useful to browse through the already developed row functions, in the "functions/row" path of madIS. +Most of the time a custom function can be based on an already existing one. + +.. note:: + If a developer wishes to add a row function that in essence is a part of a pre-existing Python library. + The madIS convention is to put the library files in the "src/lib/" path of madIS and then create a row function in the "row" path of madIS which imports and calls the necessary methods of the actual library in "lib" path. + For an example of this see *detectlang.* + +.. seealso:: + + * :ref:`row-functions-list` + +Aggregate functions + +Programmable aggregate functions work in a similar way as standard SQL aggregate functions such as *sum()*, *min()* and *max()*. +Their implementation is done in Python, and as is also the case for row functions, all Python facilities and libraries are available. + +An example of an SQL statement using an external aggregate function is:: + + mterm> select "term1+term2" as a UNION select "term2 term3" as a; + term1+term2 + term2 term3 + mterm> select concatterms(a) + from (select "term1+term2" as a UNION select "term2 term3" as a); + term1+term2 term2 term3 + +The statement above, executes the :func:`~functions.aggregate.text.concatterms` function, which concatenates strings of terms together, while keeping the terms disjoint. + +Using the aggregate function above, together with a row function is also possible. +To concatenate together only the input string keywords we could execute the following SQL:: + + mterm> select concatterms(keywords(a)) + from (select "term1+term2" as a UNION select "term2 term3" as a); + term1 term2 term2 term3 + +.. seealso:: + + * :ref:`aggregate-functions-list` + * :func:`~functions.aggregate.text.concatterms` + * :func:`~functions.row.keywords.keywords` + + +Creating and using a simple aggregate function +---------------------------------------------- + +Python files that implement aggregate functions live in +"/src/functions/aggregate". A single python file can contain many aggregate functions. +Now, lets create a simple aggregate function. + +Go to the "src/functions/aggregate/" path of madIS, and create "myconcat.py". Then write the following code in it: + +.. sourcecode:: python + + class quotedconcatterms: + + registered=True + + def __init__(self): + self.result=[] + + def step(self, *args): + if len(args[0])!=0: + self.result.append("'"+args[0]+"'") + + def final(self): + return ' '.join(self.result) + +What the aggregate function above does, is to concatenate strings of terms together while inserting single quotes around each string. + +In the "__init__" method of class *quotedconcatterms* we initialize all needed variables (self.result). +The "step" method, is called by SQLite's engine for every tuple of the group which is fed into the aggregate function. +At the end of the group, the "final" method is called to return the final result. + +The "registered=True" line above, as in row functions, instructs madIS to load the class into the SQLite engine as an aggregate function. + +To execute the above aggregate function we start madIS and execute an SQL query which uses the new *quotedconcatterms* +aggregate function (notice the single quotes around each input string in the results):: + + % python mterm.py + mterm> select quotedconcatterms(keywords(a)) from (select "term1+term2" as a UNION select "term2 term3" as a); + 'term1 term2' 'term2 term3' + +As is the case with aggregate functions it is very useful to browse through the +already developed aggregate functions, in the "functions/aggregate" path of +madIS, to find snippets of code implementing wished for, functionality. + +.. seealso:: + + * :ref:`aggregate-functions-list` + +Virtual tables + +Virtual tables are actually functions that take parameters and output table like data. They can be used in the SQL syntax wherever +a regular table would be placed. + +Virtual tables are one of the most powerful function classes in madIS. They can function in a regular table fashion, +where the output data is finite in number, or in a streaming fashion, where the output stream can be infinite. + +This, together with the SQL syntax extensions of madIS, creates a very powerful environment with which a variety +of standard madIS features have been developed, such as the *multisets*, *workflow engine*, +*direct data load from filesystem or network*, etc. + + +Typical examples of virtual tables sources are files, SQL query resulsets, or even external programs output. + +In addition to the above, virtual tables can also function as programmable indexes on the input data, +negotiating with the database engine about which constraints or ordering they'll be able to answer/produce quickly. +The only madIS virtual table that implements and works as an index is :ref:`cache `, which offers, a created on the fly, +multidimensional index. + +Using virtual tables can be done in a variety of ways. +The first is **parametric table**:: + + % python mterm.py + mterm> select * from file('./demo/continents.tsv') limit 2; + Asia|AF + Europe|AL + +What the example above does, is to read the tab separated "continents.tsv" filesystem file as a table. +Using the standard *limit* SQL directive, the output is limited to only 2 rows. + +An example showing the streaming nature of virtual tables is:: + + mterm> select output from pipe('query:date'); + Fri Feb 1 12:34:55 EET 2000 + "" + mterm> select strsplit(output,'delimiter: ') from pipe('query:date'); + Mon|Feb||1|12:34:56|EET|2000 + +The first of the above examples executes system's "date" command through the use of the :mod:`~functions.vtable.pipe` virtual table. +Notice that the :mod:`~functions.vtable.pipe` virtual table has a default returned schema, having one column named *output.* + +The second of the above examples does the same as the previous one, however it also splits :mod:`~functions.vtable.pipe`'s output, +using space as a delimiter, into multiple columns through :func:`~functions.row.formating.strsplit` row function. + +At this point, we should skip a little ahead, and mention two peculiarities on the queries above. +The first one is the "query:date" parameter of :mod:`~functions.vtable.pipe`. +This in madIS is called a *named parameter*, where the part before the ":" is a parameter's name and the second part is a parameter's value. + +The second peculiarity is the that the row function :func:`~functions.row.formating.strsplit` returns multiple columns. +This is a :ref:`multiset ` function, able to return as many columns and rows as it wishes. +To see the column names and column types of second query above, we can execute:: + + mterm> coltypes select strsplit(output,'delimiter: ') from pipe('query:date'); + C1|text + C2|text + C3|text + C4|text + C5|text + C6|text + C7|text + + +The "coltypes" in the above query may look like a special function of the terminal but in essence it is also +a virtual table that takes as input a query and returns a table having as first column the column names +of the inside query and as second column the column types of the inside query. + + +.. note:: + - :mod:`~functions.vtable.coltypes` is able to be used in front of a query because it is in its :ref:`inverted form `. + We'll discuss madIS SQL extensions in the following section. + - We won't present a simple virtual table implementation as they are too complex to be presented here. + For more see the already existing tables in the "/src/functions/vtable" path of madIS, and the + `APSW documentation `_ concerning virtual tables. + +.. seealso:: + + * :ref:`vtable-functions-list` + * :mod:`~functions.vtable.file` + * :mod:`~functions.vtable.pipe` + * :func:`~functions.row.formating.strsplit` + * :mod:`~functions.vtable.coltypes` + +.. _inversion: + +madIS SQL extensions +******************** + +While developing madIS, we realized that some simple ideas like virtual table chaining, were too difficult to be written in plain SQL. +In addition using a virtual table was more difficult than it needed to be, due to having to "create" a virtual table before using it. + +To solve the problems above, we've extended SQL with the following features: + +- Parametric virtual tables are automatically created and deleted + +- Syntax inversion + +The first of above features, is quite apparent. The user doesn't have to manage virtual tables, +madIS does everything it is needed automatically in the background, creating a virtual table just before a query using it, is executed, and +deleting it after the query's execution completes. This is why we could directly +read from the file system, with the *file* virtual table, in the previous section. + +Inversions are slightly more complex. +So lets start with a simple virtual table chaining example and invert it:: + + mterm> select * from output('d.txt', "query:select * from pipe('query:date')"); + 1 + +What the query above does, is to call system's "date" command, through the *pipe* virtual table, and write the output back to the file system (in the file named "d.txt"). +The *output* virtual table returns back if it succeeded or not (1 or 0). + +Because chaining virtual tables on the manner shown above, proved to require a lot of effort and in addition was error prone, syntax inversion was added to madIS' accepted SQL syntax. +The inversion syntax is:: + + VTname 'param1' 'param2'... namedparam1:valueofnamedparam1 ... SQL_query + + +Whenever madIS' SQL preprocessor "sees" above syntax it turns it into:: + + select * from Vtname('param1', 'param2' ..., 'namedparam1:valueofnamedparam1' ... , 'query:SQL_query') + +So lets use the inverted syntax, to reissue the query above:: + + mterm> output 'd.txt' pipe date; + 1 + +In practice a wide range of functionalities has been possible with inversions. +The *coltypes* example shown in the previous section "feels" like special functionality that is implemented execution engine in other DB systems. +In madIS, most of the special commands are in essence virtual tables (or row functions) in their inverted form. + +The same inverted syntax is also offered by madIS, for row functions. +So instead of:: + + mterm> select detectlang('Il en est des livres comme du feu de nos foyers'); + french + +We could have written it as such:: + + mterm> detectlang 'Il en est des livres comme du feu de nos foyers'; + french + +A problem arises with row inversions. +How to distinguish between the case of passing the actual query to a row function, and passing the **results** of the query to the row function. + +madIS has the *var* row function, which sets and retrieves a madIS variable. +Some examples of its usage:: + + mterm> var 'demo' 'time'; -- This puts value 'time' to the variable named 'demo' + time + mterm> var 'demo'; -- This retrieves the value of variable 'demo' + time + mterm> select var('demo','time');--The same queries in their not inverted forms + time + mterm> select var('demo'); + time + +What would happen if instead of the value "time" we had a plain query?:: + + mterm> var 'demo2' select var('demo'); + select var('demo') + mterm> var 'demo2'; + select var('demo') + +We see above, that instead of putting the result of the query "select var('demo')" into "demo2", it put the query's text in it. +This makes it complex to pass values between variables, forcing us to do:: + + mterm> select var('demo2', (select var('demo'))); --Non inverted syntax + time + mterm> var 'demo2'; + time + +Due to this, a directive which forces the use of the results of the embedded query has been created, to ease use cases such as above:: + + mterm> var 'demo2' 'essence of'; + essence of + mterm> var 'demo' 'time'; + time + mterm> var 'demo2' FROM var 'demo'; + time + mterm> var 'demo2'; + time + +Notice the "FROM" keyword after the "var 'demo2'" part of the query. +What "FROM" does is to transform the query in its non inverted syntax shown above. + +.. note:: + Both "FROM" and "OF" are accepted as synonyms, when specifying the use of embedded query results. + +.. seealso:: + + * :mod:`~functions.vtable.output` + * :mod:`~functions.vtable.pipe` + * :func:`~functions.row.langtools.detectlang` + * :func:`~functions.row.variables.var` + + +.. _tutmultiset: + +Multisets +********* + +Early in the development of madIS, the need to return multiple rows and columns from row and aggregate functions, arose. +This need was satisfied through the use of *expand* virtual table and an accompanying Python API (*CompBuffer*) to create multisets. + +Virtual table *expand* works by looking into the results of a SQL query, and if +it finds a specially formatted tuple (in *CompBuffer's* format), it decompresses it, +looks for schema information, and then starts returning one by one the compressed data to the outside query. +If more than one *CompBuffers* are found, then their schemata are consolidated into one. + +CompBuffer tries to avoid writing on the hard disk, by compressing in memory, the data fed +into it and only after a threshold of 10 Mb of compressed data is reached, spilling over into the hard disk. + +To make multiset usage transparent to the user, madIS' SQL preprocessor, inserts automatically +the *expand* virtual table whenever a multiset producing function is met. +To flag a row or aggregate function as a multiset one, the programmer has to set the function's attribute +"multiset" to "True". This is done in the same way as for the "registered" function's attribute. + + +An example of a multiset row function which produces multiple columns is:: + + mterm> select strsplit("one,two,three"); + one|two|three + +And one which produces multiple rows is:: + + mterm> select strsplitv("one,two,three"); + one + two + three + +Both of the functions above, break their input on "comma" by default. + +.. seealso:: + + * :func:`~functions.row.formating.strsplit` + * :func:`~functions.row.formating.strsplitv` + + +.. _tutcache: + +On the fly multidimensional indexing (the *cache* virtual table) +**************************************************************** + +Working with external sources directly, has the major problem of not being able to put acceleration structures on them (indexing), unless materializing them in the form of a database table. +Joins with external sources, in particular, are very slow, forcing the SQLite core to do multiple sequential passes on the virtual tables tied to the external sources. + +To solve the problems above, the *cache* virtual table was created. +The way it works is this: + +- At the beginning it does one pass over the results of the input query, and keeps them in memory + +- Then it negotiates with SQLite's core about what constraints and order bys, the core would like to have answered as fast as possible + +- It builds a very fast multidimensional index based on the negotiations above + +- It waits until the core starts sending queries on the above constraints, and returns the results using the just build multidimensional index + +- At the end of the query it throws away the cached query's data and the multidimensional index + +The multidimensional index is based on kd-trees and is implemented in Python, using the virtual table indexing API. +It is a very fast to be build index, and extremely fast on answering queries involving many constraints. +The multidimensional index is also designed to be memory efficient, needing O(number_of_dataset_rows) memory no matter the number of indexed dimensions. + +In practice, it has been up to 10 times faster on interval joins compared to SQLite's native indexing, and as the dimensions grow in number its speed advantage becomes bigger. + +An example of *cache* use is:: + + % cd demo + % python mterm.py + mterm> select country.c2, continent.c1 + from file('countries.tsv') as country, + file('continents.tsv') as continent + where country.c1=continent.c2; + Aruba|Americas + Antigua and Barbuda|Americas + United Arab Emirates|Asia + Afghanistan|Asia + . . . . . . . . . + Query executed in 0 min 2 sec 40 msec + mterm> select country.c2, continent.c1 + from file('countries.tsv') as country, + (CACHE file 'continents.tsv') as continent + where country.c1=continent.c2; + Aruba|Americas + Antigua and Barbuda|Americas + United Arab Emirates|Asia + Afghanistan|Asia + . . . . . . . . . + Query executed in 0 min 0 sec 71 msec + +The queries above, do a direct join on the filesystem's files "countries.tsv" and "continents.tsv" (in the "demo" path of madIS). +The first query doesn't do any caching at all, so it is forced to do multiple sequential reads of the "continents" file, to execute the join. +The second query, using the inverted syntax, caches the "continents" file and creates the required indexes to execute the join quickly. + +The speed difference between the two queries is quite significant (cached version of query is 28x faster). +For bigger datasets and more constraints the speed advantage could be even greater. + +.. seealso:: + + * :mod:`~functions.vtable.cache` + * :mod:`~functions.vtable.file` + +Workflows +********* + +From the beginning madIS was designed for building complete data processing systems with it. +In madIS, workflows are viewed as a series of queries to be executed sequentially. + +The main function that implements madIS' workflow engine is :mod:`~functions.vtable.exec` virtual table:: + + mterm> select 'select 5'; + select 5 + mterm> exec select 'select 5'; + 1 + +Virtual table :mod:`~functions.vtable.exec`, takes as input an SQL query, executes it and then operates on the **results** of the input query, executing them sequentially and returning "1" if all the queries executed successfully, or throwing an error if any queries failed to execute correctly. + +This peculiar design (its a meta-meta function), enables :mod:`~functions.vtable.exec` to work in tandem with other virtual tables that feed to it the workflows to be executed. +The most frequent combination is:: + + mterm> exec flow file 'workflow.sql'; + +What the query above does, is to open and read the "workflow.sql" filesystem file via +the *file* virtual table, then feed its results into the *flow* virtual table +which collects in one line the "broken into multiple lines" queries, and finally +to feed the resulting queries to :mod:`~functions.vtable.exec` virtual table which will execute them. + +The above combination of virtual tables presents, one the most powerful aspects of madIS. +Namely the ability to create complex functionality (in this instance a workflow engine), by quickly combining simple entities. + +.. note:: + Another benefit of using (or abusing) a relational database to implement a workflow engine, is that all ACID properties + of the database are still present during the workflow processing. Unfortunately due to limitations of the SQLite core, + transactional execution of madIS workflows isn't fully working yet (see :ref:`tutlimitations`). + +.. seealso:: + + * :mod:`~functions.vtable.exec` + * :mod:`~functions.vtable.flow` + * :mod:`~functions.vtable.file` + +Designing and building a data processing system with madIS +********************************************************** + +Concerning the design of a data processing system. +The required steps that have to be made when **designing** a data processing system with madIS are: + +1. Define the problem you are trying to solve + +2. Break the problem into workflows + +3. Break the workflows into queries + +4. Find the functions that the queries will need + +5. Find the Python libraries that the functions will need + +The steps above, are mostly self evident, and should be made in the order that they are presented. + +To **build** the data processing system, the above steps have to be followed, finding/building the required entities (functions, queries), for each step, **going from bottom to top** (Step 5 to Step 2), + +In practice we have found that there is always some overlap between the designing and building stages and between steps. +Great care should be given, when designing, on the most difficult and time consuming step, which is step 1. When step 1 is successfully executed, the speed with which the rest of the steps are designed and following that, building them from bottom to top, is extremely fast in our experience. + +.. note:: + + An example of a madIS workflow can be found in the :ref:`examples section `. + +.. _tutlimitations: + +Limitations of madIS +******************** + +The limitations of madIS are: + +- Due to SQLite's inability to simultaneously use multiple CPUs to execute a query, madIS' query execution is done by only one CPU. + This will be partially solved in the future through the use of the *map* virtual table, which will be able to execute a row function on multiple data rows in parallel. + For more heavy processing concurrency, functions and virtual tables enabling madIS to be used on clusters are in the planning stage + +- Due to SQLite's locking semantics, workflows inside a parent workflow, aren't in their own transactions. + So when a child workflow fails, the whole parent transaction rolls back. + This will be solved whenever SQLite fixes the problem where the database's system schema table is locked whenever a table is deleted diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/modules.txt b/interactive-mining-3rdparty-madis/madis/src/docs/source/modules.txt new file mode 100644 index 0000000..fa18159 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/modules.txt @@ -0,0 +1,14 @@ +Project Documentation +===================== + +This page contains the Project Modules documentation. + +Modules +------- + +.. toctree:: + :maxdepth: 4 + + row + aggregate + vtable diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/people.txt b/interactive-mining-3rdparty-madis/madis/src/docs/source/people.txt new file mode 100644 index 0000000..ac2f71a --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/people.txt @@ -0,0 +1,12 @@ +People +====== + +Core developers +--------------- +- Lefteris Stamatogiannakis +- Mei Li Triantafyllidi + +Extensions developers +--------------------- +- Maria Vayanou +- Marialena Kyriakidi \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/quickstart.txt b/interactive-mining-3rdparty-madis/madis/src/docs/source/quickstart.txt new file mode 100644 index 0000000..e69de29 diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/thanks.txt b/interactive-mining-3rdparty-madis/madis/src/docs/source/thanks.txt new file mode 100644 index 0000000..b1b5f80 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/thanks.txt @@ -0,0 +1,18 @@ +Thanks +====== +madIS project wouldn't exist without the amazing work of several other people, and the +Open Source spirit. + +Specifically we would like to thank: + +- APSW's Roger Binns +- SQLite's authors + +In both of above projects, the work ethic and quality of their code are of an +extremely high level. Nearly every line of their code is extensively tested. + +In madIS we stressed the code of both of above projects as much as we could, and +they handled it beautifully. + + + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/usefulnotes.txt b/interactive-mining-3rdparty-madis/madis/src/docs/source/usefulnotes.txt new file mode 100644 index 0000000..f5f3dcb --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/usefulnotes.txt @@ -0,0 +1,190 @@ +Useful notes +************* + +This section contains useful tips to help with understanding function usage, ease +shell interaction and introduce some basic characteristics of the dynamic virtual tables. + +.. _unotesexamples: + +Understanding function examples +=============================== + +While reading each function's description, you will notice examples like this: + + >>> sql("select ifthenelse(1>0,'yes','no') as answer") + answer + ------ + yes + +Because examples also serve as tests for madIS's functions, they are coded and displayed as actual Python code. The string inside Python function "sql()" is +an SQL query, having its results displayed in the lines following it. Query results in examples also include the column names for clarity. +However in the interactive shell column names are not shown. In the interactive shell, the same as above example, would look like the following:: + + mterm> select ifthenelse(1>0,'yes','no') as answer; + yes + Query executed in 0 min. 0 sec 33 msec + + +.. _unotesparameters: + +Understanding function parameters +================================= + +**Named parameters** + +All types of functions (row, aggregate and virtual table) can take simple or named parameters. +For simple parameters, ordering is important and should follow function's definition. Named +parameters can be placed anywhere in the parameters lists, with few exceptions that are clearly stated. +Named parameters are strings (so they must be placed inside quotes) using the format *paramname:paramvalue*. + +For example :mod:`~functions.vtable.file` function is declared as:: + + file(location[, formatting options]) + +where *location* is a simple parameter containing the file name or network resource to read from, +and *formatting options* is a list of named parameters (eg. parameter *dialect* which accepts one of values *tsv* or *csv*). +So using this function to import a csv file would look like this:: + + select * from file('myfile','dialect:csv'); + +By using inverted syntax (see :ref:`SQL extensions `), the query would look like this:: + + select * from (file 'myfile' dialect:csv); + +Notice that non named parameters must be quoted. However named parameters quoting is optional. Also parameters are separated with spaces instead of commas. +If a space character appears in a named parameter's value field, quoting should be used. +So importing a file that uses spaces as value delimiters, would look like following (using inverted syntax):: + + select * from (file 'myfile' 'delimiter: '); + +An example of a function definition which contains named parameters is :mod:`~functions.vtable.output`:: + + output(query:None, file[, formatting options]) + +The definition above states, that the function output receives the named parameter *query* which has no default value (the value following the ":" character +of a named parameter in a functions' definition, represents the default value). + +.. _unoteqparameter: + +**The query parameter** + +Named parameter *query* shown in the definition above, defines which SQL query the function *output* will execute +and then write the query's results in the given *file*. +When using, in inverted syntax, a function that takes a *query* parameter (see :ref:`SQL extensions `) the *query* keyword should be omitted. +Instead the actual query should be placed at the end of the statement. For example to output, in inverted syntax, some query's result, the following could be used:: + + output 'outfile' dialect:tsv select * from table1; + +In non inverted syntax, this is equivalent to:: + + select * from output('query:select * from table1','outfile','dialect:tsv'); + +Inverting queries that include the *query* parameter, permits "pipelining" of many virtual table functions, while using an easy to read syntax. +So to re-order a file and add line numbers you can do:: + + output 'outfile.csv' rowidvt select * from (file 'infile.csv') order by C2; + +Let's look at the details of this query. :mod:`~functions.vtable.file` function reads *infile.csv* and returns the data as a table. +Returned data are then ordered by column C2. +The result of the query, *select \* from (file 'infile.csv') order by C2* is the *query* parameter for :mod:`~functions.vtable.rowidvt` function. +This function adds a *rowid* column to the query result that indicates the order of the row in the result (and not in the initial table). +The result of :mod:`~functions.vtable.rowidvt` function is forwarded into :mod:`~functions.vtable.output` which writes the result in the *outfile.csv* file. + + +.. _unotesreturntypes: + +Understanding function return types +=================================== + +To understand how function return types works, make sure you understand how `SQLite types `_ work. +The return type of the row and aggregate madIS functions refers to the storage class typically returned by the function. +Virtual table functions return a table having a static (or dynamic) schema with column names and `types affinity `_. +To clarify the difference of the returned types of row/aggregate functions and virtual table functions consider the following example:: + + mterm> select * from (select kwnum('lol') as a) where a=='1'; + Query executed in 0 min. 0 sec 17 msec + +Here :func:`~functions.row.text.kwnum` function returns the number of keywords of the 'lol' string which is an integer. +Although the first returned column (named *a*) is of integer type, the literal text '1' in the *where* part is not converted to an integer, +so the condition fails. In the following example, by using the built in SQLite function *cast*, an integer type affinity +is suggested so the text literal '1' is automatically converted to an integer and the condition is evaluated to true. + +:: + + mterm> select * from (select cast(kwnum('lol') as int) as a) where a=='1'; + 1 + Query executed in 0 min. 0 sec 21 msec + +In conclusion, the returned values from row and aggregate functions, even :ref:`multisets ` do not also imply data affinity. + +.. note:: + + The same result could be reached using the virtual table functions, eg. :mod:`~functions.vtable.typing` or :mod:`~functions.vtable.setschema`. + +.. _unotesshell: + +Shell interaction +================= + +In madIS's interactive shell mode some helpful shell commands and functions helping with complex query composition are supported. +These can be listed in the terminal with the *.help* command. + +**Names function** + +Function :mod:`~functions.vtable.names` is a virtual table function that operates over a query (See :ref:`unotesparameters`) +and returns the column names of the query result. + +:: + + mterm> names select * from file('test.csv','header:t') ; + City|Region|Country|Population + Query executed in 0 min. 0 sec 24 msec + +Function :mod:`~functions.vtable.coltypes`, has similar functionality, additionally presenting the column's +`type affinity `_ when this information is contained in its input. + +:: + + mterm> coltypes select * from file('/home/meili/Desktop/test.csv','header:t') ; + City|text + Region|text + Country|text + Population|text + + +.. _unotesemptyschema: + +Empty schema exception +====================== + +A price to pay for using virtual tables having dynamic schema creation, is that if no data are provided, for example an empty file +to the :mod:`~functions.vtable.file` function or +a query that returns no rows to virtual tables that accept input *queries* (eg. :mod:`~functions.vtable.cache` function), is an exception as a result:: + + mterm> select * from (cache select 5 as a where a!=5); + Madis SQLError: operator cache: Cannot initialise dynamic schema virtual table without data + +To avoid this issue, especially in automatic flow execution where a flow crash is undesirable, the :mod:`~functions.vtable.setschema` function can be used. +*Setschema* is virtual table function that enforces a given schema. In the case of non empty resultsets, it can be used to project, +rename and typecast inner query columns, while in case of an empty resultset, it works as a static schema definition. +:: + + mterm> select * from (setschema 'a' cache select 5 as a where a!=5); + Query executed in 0 min. 0 sec 62 msec + +In the example above, *cache* function has a possibility of producing an empty schema exception. Applying the *setschema* function with the desirable schema +(column a with NONE type) this problem is avoided. + +Other possible causes of empty schema exceptions are also :ref:`multiset ` functions which are actually implemented +through the :mod:`~functions.vtable.expand` virtual table function. + +.. _unotesefficiencyvt: + +Efficiency in streaming virtual tables +====================================== + +Virtual table functions that work as streams do not need to materialise the whole input/output data streams before returning them, they can produce them on demand. +So executing, for example a *join*, between streaming virtual tables for a huge volume of data is not a good idea, as the data will have to be re-produced +over and over again. Using :ref:`cache ` virtual table function on one of the *streaming* queries will significantly increase performance. + + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/vtablehowto.txt b/interactive-mining-3rdparty-madis/madis/src/docs/source/vtablehowto.txt new file mode 100644 index 0000000..fc1a88c --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/vtablehowto.txt @@ -0,0 +1,175 @@ +Virtual table concept in madIS +============================== + +Virtual table can be any piece of code that returns its results as list of lists. It will be used in madSQL in the FROM part of a query. + +Example:: + + select * from file('data.tsv'); + +In this case data are produced from external sources. Many madis virtual tables take a query as an input, execute it and returns its results transformed. +(See :ref:`Query parameter `). In that case the vtable "call" could be inverted in the query. (see :ref:`SQL extensions `). + +Example:: + + rowidvt select * from table1 limit 3; + + +Creating a virtual table function +---------------------------------------- + +Virtual table fuctions are the most advanced operator in madIS. Existing virtual table functions can be organized by increasing implementation complexity in three categories: + + - Single boolean output vt functions with query input: Virtual table functions that take an input, do sth and return 1 or 0. Example table fuctions are :mod:`~functions.vtable.exec` + + - Iterative output: Vts that take input and returns many data (iterator of list). + Its call of the iterator retuns a list with each row data. In this category falls :mod:`~functions.vtable.file` operator, as well as :mod:`~functions.vtable.expand`, :mod:`~functions.vtable.rowidvt`, etc. + + - Advanced: Advanced vt's that need the index capability of virtual tables. In this category falls only :mod:`~functions.vtable.cache` functions. These functions must implement virtual tables from scratch as described in + `APSW documentation `_. + + +All virtual table functions are created in XXXX folder. Every virtual table function must be single module. +Detailed documentation of virtual table API could be found in `APSW documentation `_. +In madIS there are used mostly two specific types of Virtual table functions, that helper libraries have been implemented to simplify +their implementation. +So implementing a virtual table function, is feasible either by following the `APSW API `_ +and adding the flags for madIS, either by using the helper libraries, as explained below. +To continue reading, have a look to the Virtual table function API in APSW and play with toggle function and a virtual table call. +Example:: + + mterm> toggle tracing; + tracing is now: True + Query executed in 0 min. 0 sec 4 msec + + mterm> select * from (file 'data.csv'); + executetrace(u"create virtual table temp.vt_144176563 using file('data.csv','automatic_vtable:1')") + executetrace(u'select * from (SELECT * FROM vt_144176563 );',None) + ... + executetrace(u'drop table temp.vt_144176563;') + Query executed in 0 min. 0 sec 14 msec + + mterm> toggle vtdebug; + executetrace(u"SELECT toggle('vtdebug');",None) + vtdebug is now: True + Query executed in 0 min. 0 sec 4 msec + + mterm> select * from (file 'data.csv'); + .... + +Toggle is a row function that toggles the value of :ref:`madIS global settings<>` + +Important flags for madIS VT functions +-------------------------------------- + + registered=True # set this flag to register in madis the function, if set to false the module is not loaded. + + external_stream=True # Set this flag if no query parameter can be used. + + + + + +Impementing single boolean output virtual table function +-------------------------------------------------------- + +The + + def function() + from madis.vtout import SourceNtoOne + + class SourceNtoOne: + def __init__(self,func,boolargs=None,nonstringargs=None,needsescape=None,notsplit=None,connectionhandler=False,retalways=False): + + +To create iterative VT's the madIS vtiterable could be used that hide some of the implementation details, or it can be build from scratch as in APSW, documentation. (http://apsw.googlecode.com/svn/publish/vtable.html) If vtiterable is not used, no standard parameter parsing will be available. + +MUST BE SET TO USE VT in madis: + One VT - one file in vtable folder + registered=True ( as in all operators) + external_stream=True (if the operator does not accept query parameter) + + Source function must be implemented!! + + + +:: + + #Cursor Iterator + + class TableCursor: # INTERFACE + def __init__(self): # when called for first time, it must probably identify the schema, if it is not dynamic + pass + def __iter__(self): + pass + def next(self): + pass + def close(self): + pass + +:: + + + class TableVT: #INTERFACE + + def __init__(self,envdict,largs,dictargs): #DO NOT DO ANYTHING HEAVY it, will be called before querying the table + pass + + def getdescription(self): + """ + must return a list of tuples (column name, columntype), if type not available leave it empty or None eg.(col,) + example: + [('column1','int'),('column2',),('column3','text')] + """ + return schemalist + + def open(self): + """ + After the first time it is called getdescription function must return table instance schema + Must returns VT cursor + """ + return TableCursor() + + def destroy(self): # Called when Table instance is destroyed (on drop statement), OPTIONAL + pass + +.. function:: TableVT.__init__(self,envdict,largs,dictargs) + +Parameters: + + :envdict: + Dictionary with enviromental variables (correspond to APSW parameters of VTModule.Create) + :tablename: name of the table that will be created. + :db: instance of the connection to the database + :dbname: database name + :modulename: The string name under which the module was registered??????? + + :largs: table function list arguments + + :dictargs: dictionary table function named arguments eg. type:int -> dictargs['type']='int' + + + +def Source(): + return SourceVT(TableVT,boolargs,nonstringargs,needsescape,notsplit) + +class SourceVT: + def __init__(self,table,boolargs=None,nonstringargs=None,needsescape=None,staticschema=False,notsplit=None): + +.. params: + +Parameters + + :table: Class implementing TableVT interface + :boolargs: List of parameter names that will be chnged to True/False if they are accordingly t/f + :nonstringargs: Dictionary of parameter names that will be tranformed according to their value , eg. string input to dialect object {'dialect':{'line':line(),'tsv':tsv(),'csv':defaultcsv()}} + :needsescape: List of parameter names that that include escape sequences eg. \n, \t etc. + :staticschema: True if TableVT.open does not need to be executed before getdescription can be called + :notsplit: List of parameter names that should not be splitted in named parameters eg. ['http'] for do not splitting http://server.com + + + + + + + diff --git a/interactive-mining-3rdparty-madis/madis/src/docs/source/workflows.txt b/interactive-mining-3rdparty-madis/madis/src/docs/source/workflows.txt new file mode 100644 index 0000000..c4b1779 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/docs/source/workflows.txt @@ -0,0 +1,12 @@ +executing madSQL workflow + +logging on workflows + flowname + +variables in workflows + +passing variable in new workflow execution + +Transcactions in workflows + + diff --git a/interactive-mining-3rdparty-madis/madis/src/examples/citeseer/cite.sql b/interactive-mining-3rdparty-madis/madis/src/examples/citeseer/cite.sql new file mode 100644 index 0000000..49f2f83 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/examples/citeseer/cite.sql @@ -0,0 +1,22 @@ +-- This is a simple example of bulk harvesting an OAI-PMH service. The data are then converted from XML to a single relational table. +-- Due to the extreme slowness and unreliability of OAI-PMH protocol, we first fetch all data into a plain text file. If the transmission breaks, you should continue the transfer on a different file (e.g. 'rawdata1.txt'), so as to no overwrite previously fetched data. + +output 'rawdata.txt' select * from (oaiget metadataPrefix:oai_dc 'http://citeseerx.ist.psu.edu/oai2'); + +-- After fetching all of the above 'rawdataX' files, concatenate them into a single one ('rawdata.txt'). + + +-- We then want to find out which XML keys the 'rawdata' file contains. We restrict our key search to keys under "record". + +select jgroupunion(jdictkeys(c1)) from (xmlparse root:record fast:1 file 'rawdata.txt.gz'); + +-- ["record/header/identifier","record/header/datestamp","record/metadata/dc/@/schemalocation","record/metadata/dc/title","record/metadata/dc/creator","record/metadata/dc/subject","record/metadata/dc/description","record/metadata/dc/contributor","record/metadata/dc/publisher","record/metadata/dc/date","record/metadata/dc/format","record/metadata/dc/type","record/metadata/dc/identifier","record/metadata/dc/source","record/metadata/dc/language","record/metadata/dc/relation","record/metadata/dc/rights"] + + +-- Finally we create the "article" table using the keys from above that interest us + +create table article as +select regexpr(':([^:]*)$', header_identifier) as header_identifier, header_datestamp, metadata_dc_schemalocation, metadata_dc_title, metadata_dc_creator, metadata_dc_subject, metadata_dc_description, metadata_dc_contributor, metadata_dc_publisher, metadata_dc_date, metadata_dc_format, metadata_dc_type, metadata_dc_identifier, metadata_dc_source, metadata_dc_language, metadata_dc_relation, metadata_dc_rights +from ( +xmlparse strict:0 '["record/header/identifier","record/header/datestamp","record/metadata/dc/@/schemalocation","record/metadata/dc/title","record/metadata/dc/creator","record/metadata/dc/subject","record/metadata/dc/description","record/metadata/dc/contributor","record/metadata/dc/publisher","record/metadata/dc/date","record/metadata/dc/format","record/metadata/dc/type","record/metadata/dc/identifier","record/metadata/dc/source","record/metadata/dc/language","record/metadata/dc/relation","record/metadata/dc/rights"]' +file 'rawdata.txt' ); diff --git a/interactive-mining-3rdparty-madis/madis/src/examples/dblp/dblp.sql b/interactive-mining-3rdparty-madis/madis/src/examples/dblp/dblp.sql new file mode 100644 index 0000000..28a9cff --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/examples/dblp/dblp.sql @@ -0,0 +1,85 @@ +-- First of all download http://dblp.uni-trier.de/xml/dblp.xml.gz + +-- To find the XML keys inside above XML and under the "article" tag, execute. + +select jgroupunion(jdictkeys(c1)) from (xmlparse root:article fast:1 file 'dblp.xml.gz'); + +-- ["article/@/mdate","article/@/key","article/author","article/title/*","article/journal","article/volume","article/month","article/year","article/cdrom","article/ee","article/url","article/@/publtype","article/editor","article/publisher","article/pages","article/number","article/cite","article/cite/@/label","article/crossref","article/booktitle","article/note","article/@/rating","article/@/reviewid"] + +-- We do the same for "www" and "inproceedings" tags. + +select jgroupunion(jdictkeys(c1)) from (xmlparse root:www fast:1 file 'dblp.gz'); + +--["www/@/mdate","www/@/key","www/author","www/title","www/year","www/url","www/editor","www/booktitle","www/note","www/crossref","www/cite","www/ee","www/note/@/type","www/author/@/bibtex"] + +select jgroupunion(jdictkeys(c1)) from (xmlparse root:inproceedings fast:1 file 'dblp.xml.gz'); + +--["inproceedings/@/mdate","inproceedings/@/key","inproceedings/author","inproceedings/title/*","inproceedings/pages","inproceedings/year","inproceedings/booktitle","inproceedings/month","inproceedings/url","inproceedings/note","inproceedings/cdrom","inproceedings/ee","inproceedings/crossref","inproceedings/cite","inproceedings/editor","inproceedings/cite/@/label","inproceedings/@/publtype","inproceedings/number"] + +-- We create the article, www and inproceedings tables. + +create table article as +select * from ( +xmlparse '["article/@/mdate","article/@/key","article/author","article/title/*","article/journal","article/volume","article/month","article/year","article/cdrom","article/ee","article/url","article/@/publtype","article/editor","article/publisher","article/pages","article/number","article/cite","article/cite/@/label","article/crossref","article/booktitle","article/note","article/@/rating","article/@/reviewid"]' fast:1 file 'dblp.xml.gz' ); + +create table www as select * from (xmlparse '["www/@/mdate","www/@/key","www/author","www/title","www/year","www/url","www/editor","www/booktitle","www/note","www/crossref","www/cite","www/ee","www/note/@/type","www/author/@/bibtex"]' fast:1 file 'dblp.xml.gz'); + +create table inproceedings as select * from (xmlparse '["inproceedings/@/mdate","inproceedings/@/key","inproceedings/author","inproceedings/title/*","inproceedings/pages","inproceedings/year","inproceedings/booktitle","inproceedings/month","inproceedings/url","inproceedings/note","inproceedings/cdrom","inproceedings/ee","inproceedings/crossref","inproceedings/cite","inproceedings/editor","inproceedings/cite/@/label","inproceedings/@/publtype","inproceedings/number"]' fast:1 file 'dblp.xml.gz'); + +-- Lets say that we want to find the author tenure dates from the data. We'll do it by using a heuristic method, where the "oldest" author among a paper's author list is considered to be the "professor". Please NOTE that the used heuristic is very unreliable. + +-- We start by creating a table that will contain author and his publication years. + +create table authorpubyear as select jsplitv(t2j(author)) as author, year from article; + +-- From author's publications we find the oldest one. + +create table authorminyear as select author,min(year) as year from authorpubyear group by author; + +create index idxauthorminyear on authorminyear(author); + +-- For articles that have multiple authors (XMLPARSE uses TAB for multiple values on the same key, this is why we use "like '%TAB%'" below), find their minyear and select the author having the minimum minyear among them. + +create table professors as +select minrow(myear,author) as pauthor,pyear from ( +select +key, +author, +(select authorminyear.year from authorminyear where authorminyear.author=a.author) as myear, +pyear +from +(select key,jsplitv(t2j(author)) as author,year as pyear from article where author like '% %') as a +) group by key; + +-- We assume that the first time that an author appeared as a professor in a paper, is his tenure year. + +create table tenures as select pauthor,min(pyear) as tyear from professors group by pauthor; + +-- Now, lets calculate some other statistics. + +-- Number of per author publications before tenure +select pauthor,count(year) from authorpubyear, tenures where authorpubyear.author=tenures.pauthor and authorpubyear.yearYYYY-MM-DD.... field in the data you've recieved + +-- After fetching all of the above 'rawdataY' files, concatenate them into a single one ('rawdata.txt'). + + +-- We then want to find out which XML keys the 'rawdata' file contains. We restrict our key search to keys under "decisionexpanded". + +select jgroupunion(jdictkeys(c1)) from (xmlparse root:decisionexpanded select utf8clean(c1) from (file 'rawdata.txt')); + +-- ["decisions/decisionexpanded/ada","decisions/decisionexpanded/submissiontimestamp","decisions/decisionexpanded/metadata/protocolnumber","decisions/decisionexpanded/metadata/date","decisions/decisionexpanded/metadata/subject","decisions/decisionexpanded/metadata/organization/@/uid","decisions/decisionexpanded/metadata/organization/label","decisions/decisionexpanded/metadata/organization/latinname","decisions/decisionexpanded/metadata/organizationunit/@/uid","decisions/decisionexpanded/metadata/organizationunit/label","decisions/decisionexpanded/metadata/decisiontype/@/uid","decisions/decisionexpanded/metadata/decisiontype/label","decisions/decisionexpanded/metadata/tags/tag/@/uid","decisions/decisionexpanded/metadata/tags/tag/label","decisions/decisionexpanded/metadata/relativefek/issue","decisions/decisionexpanded/metadata/relativefek/year","decisions/decisionexpanded/url","decisions/decisionexpanded/documenturl","decisions/decisionexpanded/metadata/relativefek/feknumber","decisions/decisionexpanded/metadata/extrafields/extrafield/@/name","decisions/decisionexpanded/metadata/extrafields/extrafield/label","decisions/decisionexpanded/metadata/extrafields/extrafield/value","decisions/decisionexpanded/metadata/tags/tag/@/nil","decisions/decisionexpanded/metadata/iscorrectedbyada","decisions/decisionexpanded/metadata/relativeada","decisions/decisionexpanded/metadata/organization/units/unit/@/uid","decisions/decisionexpanded/metadata/organization/units/unit/label","decisions/decisionexpanded/metadata/iscorrectionofada"] + + +-- We then create the "decisions" table using the keys from above that interest us + +create table decisions as +select * from ( +xmlparse '["decisionexpanded/ada","decisionexpanded/submissiontimestamp","decisionexpanded/metadata/protocolnumber","decisionexpanded/metadata/date","decisionexpanded/metadata/subject","decisionexpanded/metadata/organization/@/uid","decisionexpanded/metadata/organization/label","decisionexpanded/metadata/organization/latinname","decisionexpanded/metadata/organizationunit/@/uid","decisionexpanded/metadata/organizationunit/label","decisionexpanded/metadata/decisiontype/@/uid","decisionexpanded/metadata/decisiontype/label","decisionexpanded/metadata/tags/tag/@/uid","decisionexpanded/metadata/tags/tag/label","decisionexpanded/metadata/relativefek/issue","decisionexpanded/metadata/relativefek/year","decisionexpanded/url","decisionexpanded/documenturl","decisionexpanded/metadata/relativefek/feknumber","decisionexpanded/metadata/extrafields/extrafield/@/name","decisionexpanded/metadata/extrafields/extrafield/label","decisionexpanded/metadata/extrafields/extrafield/value","decisionexpanded/metadata/tags/tag/@/nil","decisionexpanded/metadata/iscorrectedbyada","decisionexpanded/metadata/relativeada","decisionexpanded/metadata/organization/units/unit/@/uid","decisionexpanded/metadata/organization/units/unit/label","decisionexpanded/metadata/iscorrectionofada"]' +select utf8clean(c1) from +(file 'rawdata.txt') +); + + +-- Finally we delete the duplicate ada (decision ids) + +delete from decisions where rowid not in ( +select rowid from decisions group by ada +); + + + + diff --git a/interactive-mining-3rdparty-madis/madis/src/examples/diavgeia/diavgeiaget.py b/interactive-mining-3rdparty-madis/madis/src/examples/diavgeia/diavgeiaget.py new file mode 100644 index 0000000..3e22929 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/examples/diavgeia/diavgeiaget.py @@ -0,0 +1,137 @@ +""" +.. function:: diavgeiaget(url, verb, metadataPrefix,...) + + Fetches data from an OAIPMH service, using resumption tokens to fetch large datasets. + + - If no *verb* is provided then *verb* is assumed to be 'ListRecords'. + - If no *metadataPrefix* is provided then *verb* is assumed to be 'ListMetadataFormats', which will list + all metadata formats. + +:Returned table schema: + Column C1 as text + +Examples: + + >>> sql("select * from diavgeiaget('verb:ListRecords', 'metadataPrefix:ctxo')") # doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator OAIGET: An OAIPMH URL should be provided + + >>> sql("select * from (diavgeiaget verb:ListRecords metadataPrefix:ctxo 'http://oaiurl' )") # doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator OAIGET: + +""" +from functions.vtable import vtbase +import functions +import time + +registered=True +external_stream=True + +class diavgeiaget(vtbase.VT): + def VTiter(self, *parsedArgs, **envars): + + def buildURL(baseurl, opts): + return '?'.join([ baseurl, '&'.join([x+'='+unicode(y) for x,y in opts if y!=None]) ]) + + import urllib2 + import re + + opts= self.full_parse(parsedArgs)[1] + + yield ('c1', 'text') + + if 'datefrom' not in opts: + opts['datefrom']='01-01-1000' + if 'output' not in opts: + opts['output']='full' + if 'order' not in opts: + opts['order']='asc' + if 'http' not in opts: + opts['http']='//opendata.diavgeia.gov.gr/api/decisions' + + baseurl='http:'+opts['http'] + + findcount=re.compile(r"""[^\d]*?(\d+)[^\d]*?""", re.DOTALL| re.UNICODE) + findtotal=re.compile(r"""[^\d]*?(\d+)[^\d]*?""", re.DOTALL| re.UNICODE) + findfrom=re.compile(r"""[^\d]*?(\d+)[^\d]*?""", re.DOTALL| re.UNICODE) + + count=total=fromv=lastfromv=None + firsttime=True + + del(opts['http']) + opts=list(opts.iteritems()) + url=buildURL(baseurl, opts) + + def buildopener(): + o = urllib2.build_opener() + o.addheaders = [ + ('Accept', '*/*'), + ('Connection', 'Keep-Alive'), + ('Content-type', 'text/xml') + ] + return o + + opener=buildopener() + + errorcount=0 + while True: + try: + for i in opener.open( url, timeout=1200 ): + if count==None: + t=findcount.search(i) + if t: + count=int(t.groups()[0]) + if total==None: + t=findtotal.search(i) + if t: + errorcount=0 + total=int(t.groups()[0]) + if fromv==None: + t=findfrom.search(i) + if t: + errorcount=0 + fromv=int(t.groups()[0]) + yield (unicode(i.rstrip("\n"), 'utf-8'),) + if count==None or total==None or fromv==None: + break + fromv=fromv+count + if fromv>total: + break + url=buildURL(baseurl, opts+[('from', fromv)]) + lastfromv=fromv + count=total=fromv=None + firsttime=False + except Exception,e: + if errorcount<10 and not firsttime: + time.sleep(2**errorcount) + errorcount+=1 + else: + if lastfromv==None: + raise functions.OperatorError(__name__.rsplit('.')[-1], e) + else: + raise functions.OperatorError(__name__.rsplit('.')[-1], str(e)+'\n'+'To continue, use the following "from" parameter:\n'+str(lastfromv)) + +def Source(): + return vtbase.VTGenerator(diavgeiaget) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + diff --git a/interactive-mining-3rdparty-madis/madis/src/examples/readme.txt b/interactive-mining-3rdparty-madis/madis/src/examples/readme.txt new file mode 100644 index 0000000..40c84d7 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/examples/readme.txt @@ -0,0 +1,29 @@ +Inside the subdirectories you'll find madIS' usage examples. + +To execute the examples you'll need to enter inside a subdirectory and start +mterm with a database name argument: + +> cd dblp +> mterm dblp.db + +You can execute the entirety of a particular SQL flow by using: + +exec flow file 'dblp.sql'; + +Or by opening "dblp.sql" in a text editor and copy pasting one by one the +SQL commands, from text editor's window into mterm's window. + +To optimize the resulting database, it is best to execute (inside mterm) the +following SQLite pragmas as soon as you open mterm, and before executing any +other SQL query: + +pragma page_size = 16384; +pragma default_cache_size = 10000; +pragma journal_mode = PERSIST; +pragma journal_size_limit = 10000000; +pragma legacy_file_format = false; +pragma synchronous = 1; +pragma auto_vacuum = 2; + +Above pragmas optimize SQLite's default options for analytic (bulk/OLAP) SQL queries. + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/__init__.py b/interactive-mining-3rdparty-madis/madis/src/functions/__init__.py new file mode 100755 index 0000000..43c7204 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/__init__.py @@ -0,0 +1,612 @@ +"""functions +""" +VERSION = "1.9" + +import setpath +import os.path +import os +import apsw +import sqltransform +import traceback +import logging +import re +import sys +import copy + +try: + from collections import OrderedDict +except ImportError: + # Python 2.6 + from lib.collections26 import OrderedDict + +try: + from inspect import isgeneratorfunction +except ImportError: + # Python < 2.6 + def isgeneratorfunction(obj): + return bool((inspect.isfunction(object) or inspect.ismethod(object)) and + obj.func_code.co_flags & CO_GENERATOR) + +sys.setcheckinterval(1000) + +sqlite_version = apsw.sqlitelibversion() +apsw_version = apsw.apswversion() + +VTCREATE = 'create virtual table temp.' +SQLITEAFTER3711 = False +SQLITEAFTER380 = False +sqlite_version_split = [int(x) for x in sqlite_version.split('.')] + +if sqlite_version_split[0:3] >= [3,8,0]: + SQLITEAFTER380 = True + +try: + if sqlite_version_split[0:3] >= [3,7,11]: + VTCREATE = 'create virtual table if not exists temp.' + SQLITEAFTER3711 = True +except Exception, e: + VTCREATE = 'create virtual table if not exists temp.' + SQLITEAFTER3711 = True + +firstimport=True +test_connection = None + +settings={ +'tracing':False, +'vtdebug':False, +'logging':False, +'syspath':str(os.path.abspath(os.path.expandvars(os.path.expanduser(os.path.normcase(sys.path[0]))))) +} + +functions = {'row': {}, 'aggregate': {}, 'vtable': {}} +multiset_functions = {} +iterheader = 'ITER'+chr(30) + +variables = lambda _: _ +variables.flowname = '' +variables.execdb = None +variables.filename = '' + +privatevars=lambda _: _ + +rowfuncs=lambda _: _ + +oldexecdb=-1 + +ExecutionCompleteError = apsw.ExecutionCompleteError + +def getvar(name): + return variables.__dict__[name] + +def setvar(name, value): + variables.__dict__[name] = value + +def mstr(s): + if s==None: + return None + + try: + return unicode(s, 'utf-8', errors='replace') + except KeyboardInterrupt: + raise + except: + # Parse exceptions that cannot be converted by unicode above + try: + return str(s) + except KeyboardInterrupt: + raise + except: + pass + + o=repr(s) + if (o[0:2]=="u'" and o[-1]=="'") or (o[0:2]=='u"' and o[-1]=='"'): + o=o[2:-1] + elif (o[0]=="'" and o[-1]=="'") or (o[0]=='"' and o[-1]=='"'): + o=o[1:-1] + o=o.replace('''\\n''','\n') + o=o.replace('''\\t''','\t') + return o + +class MadisError(Exception): + def __init__(self,msg): + self.msg=mstr(msg) + def __str__(self): + merrormsg="Madis SQLError: \n" + if self.msg.startswith(merrormsg): + return self.msg + else: + return merrormsg+self.msg + +class OperatorError(MadisError): + def __init__(self,opname,msg): + self.msg="Operator %s: %s" %(mstr(opname.upper()),mstr(msg)) + +class DynamicSchemaWithEmptyResultError(MadisError): + def __init__(self,opname): + self.msg="Operator %s: Cannot initialize dynamic schema virtual table without data" %(mstr(opname.upper())) + +def echofunctionmember(func): + def wrapper(*args, **kw): + if settings['tracing']: + if settings['logging']: + try: + lg = logging.LoggerAdapter(logging.getLogger(__name__),{ "flowname" : variables.flowname }) + if hasattr(lg.logger.parent.handlers[0],'baseFilename'): + lg.info("%s(%s)" %(func.__name__,','.join(list([repr(el) for el in args[1:]])+["%s=%s" %(k,repr(v)) for k,v in kw.items()]))) + except Exception: + pass + print "%s(%s)" %(func.__name__,','.join(list([repr(el)[:200]+('' if len(repr(el))<=200 else '...') for el in args[1:]])+["%s=%s" %(k,repr(v)) for k,v in kw.items()])) + return func(*args, **kw) + return wrapper + +def iterwrapper(con, func, *args): + global iterheader + i=func(*args) + si=iterheader+str(i) + con.openiters[si]=i + return buffer(si) + +def iterwrapperaggr(con, func, self): + global iterheader + i=func(self) + si=iterheader+str(i) + con.openiters[si]=i + return buffer(si) + +class Cursor(object): + def __init__(self,w): + self.__wrapped=w + self.__vtables=[] + self.__permanentvtables=OrderedDict() + self.__query = '' + self.__initialised=True #this should be last in init + + def __getattr__(self, attr): + if self.__dict__.has_key(attr): + return self.__dict__[attr] + return getattr(self.__wrapped, attr) + + def __setattr__(self, attr, value): + if self.__dict__.has_key(attr): + return object.__setattr__(self, attr, value) + if not self.__dict__.has_key('_Cursor__initialised'): # this test allows attributes to be set in the __init__ method + return object.__setattr__(self, attr, value) + return setattr(self.__wrapped, attr, value) + + @echofunctionmember + def executetrace(self,statements,bindings=None): + try: + return self.__wrapped.execute(statements,bindings) + except Exception, e: + try: # avoid masking exception in recover statements + raise e, None, sys.exc_info()[2] + finally: + try: + self.cleanupvts() + except: + pass + + def execute(self,statements,bindings=None,parse=True, localbindings=None): # overload execute statement + if localbindings!=None: + bindings=localbindings + else: + if bindings==None: + bindings=variables.__dict__ + else: + if type(bindings) is dict: + bindings.update(variables.__dict__) + + if not parse: + self.__query = statements + return self.executetrace(statements,bindings) + + svts=sqltransform.transform(statements, multiset_functions.keys(), functions['vtable'], functions['row'].keys(), substitute=functions['row']['subst']) + s=svts[0] + try: + if self.__vtables != []: + self.executetrace(''.join(['drop table ' + 'temp.'+x +';' for x in reversed(self.__vtables)])) + self.__vtables = [] + for i in svts[1]: + createvirtualsql=None + if re.match(r'\s*$', i[2]) is None: + sep=',' + else: + sep='' + createvirtualsql = VTCREATE+i[0]+ ' using ' + i[1] + "(" + i[2] + sep + "'automatic_vtable:1'" +")" + try: + self.executetrace(createvirtualsql) + except Exception, e: + strex = mstr(e) + if SQLITEAFTER3711 or type(e) != apsw.SQLError or strex.find('already exists')==-1 or strex.find(i[0])==-1: + raise e, None, sys.exc_info()[2] + else: + self.__permanentvtables[i[0]]=createvirtualsql + + if len(i)==4: + self.__permanentvtables[i[0]]=createvirtualsql + else: + self.__vtables.append(i[0]) + self.__query = s + return self.executetrace(s, bindings) + except Exception, e: + if settings['tracing']: + traceback.print_exc(limit=sys.getrecursionlimit()) + try: # avoid masking exception in recover statements + raise e, None, sys.exc_info()[2] + finally: + try: + self.cleanupvts() + except: + pass + + def getdescriptionsafe(self): + try: + # Try to get the schema the normal way + schema = self.__wrapped.getdescription() + except apsw.ExecutionCompleteError: + # Else create a tempview and query the view + if not self.__query.strip().lower().startswith('select'): + raise apsw.ExecutionCompleteError + try: + list(self.executetrace('create temp view temp.___schemaview as '+ self.__query + ';')) + schema = [(x[1], x[2]) for x in list(self.executetrace('pragma table_info(___schemaview);'))] + list(self.executetrace('drop view temp.___schemaview;')) + except Exception, e: + raise apsw.ExecutionCompleteError + + return schema + + def close(self, force=False): + self.cleanupvts() + return self.__wrapped.close(force) + + def cleanupvts(self): + if self.__vtables!=[]: + for t in reversed(self.__vtables): + self.executetrace('drop table if exists ' + 'temp.'+t) + self.__vtables=[] + + +class Connection(apsw.Connection): + def cursor(self): + if 'registered' not in self.__dict__: + self.registered=True + register(self) + self.openiters = {} + + return Cursor(apsw.Connection.cursor(self)) + + def queryplan(self, statements, bindings=None, parse=True, localbindings=None): + def authorizer(operation, paramone, paramtwo, databasename, triggerorview): + """Called when each operation is prepared. We can return SQLITE_OK, SQLITE_DENY or SQLITE_IGNORE""" + # find the operation name + plan.append([apsw.mapping_authorizer_function[operation], paramone, paramtwo, databasename, triggerorview]) + return apsw.SQLITE_OK + + def buststatementcache(): + c = self.cursor() + for i in xrange(110): + a = list(c.execute("select "+str(i))) + + plan = [] + + buststatementcache() + + cursor = self.cursor() + + cursor.setexectrace(lambda v1, v2, v3: apsw.SQLITE_DENY) + + self.setauthorizer(authorizer) + + cursor.execute(statements) + + self.setauthorizer(None) + + cursor.close() + + yield (('operation', 'text'), ('paramone', 'text'), ('paramtwo', 'text'), ('databasename', 'text'), ('triggerorview', 'text')) + + for r in plan: + if r[1] not in ('sqlite_temp_master', 'sqlite_master'): + yield r + + @echofunctionmember + def close(self): + apsw.Connection.close(self) + +def register(connection=None): + global firstimport, oldexecdb + + if connection == None: + if 'SQLITE_OPEN_URI' in apsw.__dict__: + connection = Connection(':memory:', flags=apsw.SQLITE_OPEN_READWRITE | apsw.SQLITE_OPEN_CREATE | apsw.SQLITE_OPEN_URI) + else: + connection = Connection(':memory:') + + connection.openiters = {} + connection.registered = True + connection.cursor().execute("attach database ':memory:' as mem;", parse=False) + + variables.filename = connection.filename + + # To avoid db corruption set connection to fullfsync mode when MacOS is detected + if sys.platform == 'darwin': + c = connection.cursor().execute('pragma fullfsync=1;', parse=False) + + functionspath=os.path.abspath(__path__[0]) + + def findmodules(abspath, relativepath): + return [ os.path.splitext(file)[0] for file + in os.listdir(os.path.join(abspath , relativepath)) + if file.endswith(".py") and not file.startswith("_") ] + + ## Register main functions of madis (functions) + rowfiles = findmodules(functionspath, 'row') + aggrfiles = findmodules(functionspath, 'aggregate') + vtabfiles = findmodules(functionspath, 'vtable') + + [__import__("functions.row" + "." + module) for module in rowfiles] + [__import__("functions.aggregate" + "." + module) for module in aggrfiles] + [__import__("functions.vtable" + "." + module) for module in vtabfiles] + + # Register aggregate functions + for module in aggrfiles: + moddict = aggregate.__dict__[module] + register_ops(moddict,connection) + + # Register row functions + for module in rowfiles: + moddict = row.__dict__[module] + register_ops(moddict,connection) + + register_ops(vtable,connection) + + ## Register madis local functions (functionslocal) + functionslocalpath=os.path.abspath(os.path.join(functionspath,'..','functionslocal')) + + flrowfiles = findmodules(functionslocalpath, 'row') + flaggrfiles = findmodules(functionslocalpath, 'aggregate') + flvtabfiles = findmodules(functionslocalpath, 'vtable') + + for module in flrowfiles: + tmp=__import__("functionslocal.row." + module) + register_ops(tmp.row.__dict__[module], connection) + + for module in flaggrfiles: + tmp=__import__("functionslocal.aggregate." + module) + register_ops(tmp.aggregate.__dict__[module], connection) + + localvtable=lambda x:x + for module in flvtabfiles: + localvtable.__dict__[module]=__import__("functionslocal.vtable." + module, fromlist=['functionslocal.vtable']) + + if len(flvtabfiles)!=0: + register_ops(localvtable,connection) + + ## Register db local functions (functions in db path) + if variables.execdb!=oldexecdb: + oldexecdb=variables.execdb + dbpath=None + + if variables.execdb!=None: + dbpath=os.path.join(os.path.abspath(os.path.dirname(variables.execdb)),'functions') + + if dbpath==None or not os.path.exists(dbpath): + currentpath=os.path.abspath(os.path.join(os.path.abspath('.'), 'functions')) + if os.path.exists(currentpath): + dbpath=currentpath + + if dbpath!=None and os.path.exists(dbpath): + if os.path.abspath(dbpath)!=os.path.abspath(functionspath): + + sys.path.append(dbpath) + + if os.path.exists(os.path.join(dbpath, 'row')): + lrowfiles = findmodules(dbpath, 'row') + sys.path.append((os.path.abspath(os.path.join(os.path.join(dbpath),'row')))) + for module in lrowfiles: + tmp=__import__(module) + register_ops(tmp, connection) + + if os.path.exists(os.path.join(dbpath, 'aggregate')): + sys.path.append((os.path.abspath(os.path.join(os.path.join(dbpath),'aggregate')))) + laggrfiles = findmodules(dbpath, 'aggregate') + for module in laggrfiles: + tmp=__import__(module) + register_ops(tmp, connection) + + if os.path.exists(os.path.join(dbpath, 'vtable')): + sys.path.append((os.path.abspath(os.path.join(os.path.join(dbpath),'vtable')))) + lvtabfiles = findmodules(dbpath, 'vtable') + tmp=lambda x:x + for module in lvtabfiles: + tmp.__dict__[module]=__import__(module) + + if localvtable!=None: + register_ops(tmp,connection) + + firstimport=False + +def register_ops(module, connection): + global rowfuncs, firstimport + + def opexists(op): + if firstimport: + return op in functions['vtable'] or op in functions['row'] or op in functions['aggregate'] + else: + return False + + + def wrapfunction(con, opfun): + return lambda *args: iterwrapper(con, opfun, *args) + + def wrapaggr(con, opfun): + return lambda self: iterwrapperaggr(con, opfun, self) + + def wrapaggregatefactory(wlambda): + return lambda cls: (cls(), cls.step, wlambda) + + + for f in module.__dict__: + fobject = module.__dict__[f] + if hasattr(fobject, 'registered') and type(fobject.registered).__name__ == 'bool' and fobject.registered == True: + opname=f.lower() + + if firstimport: + if opname!=f: + raise MadisError("Extended SQLERROR: Function '"+module.__name__+'.'+f+"' uses uppercase characters. Functions should be lowercase") + + if opname.upper() in sqltransform.sqlparse.keywords.KEYWORDS: + raise MadisError("Extended SQLERROR: Function '"+module.__name__+'.'+opname+"' is a reserved SQL function") + + if type(fobject).__name__ == 'module': + if opexists(opname): + raise MadisError("Extended SQLERROR: Vtable '"+opname+"' name collision with other operator") + functions['vtable'][opname] = fobject + modinstance = fobject.Source() + modinstance._madisVT = True + connection.createmodule(opname, modinstance) + + if type(fobject).__name__ == 'function': + if opexists(opname): + raise MadisError("Extended SQLERROR: Row operator '"+module.__name__+'.'+opname+"' name collision with other operator") + functions['row'][opname] = fobject + if isgeneratorfunction(fobject): + fobject=wrapfunction(connection, fobject) + fobject.multiset=True + setattr(rowfuncs, opname, fobject) + connection.createscalarfunction(opname, fobject) + + if type(fobject).__name__ == 'classobj': + if opexists(opname): + raise MadisError("Extended SQLERROR: Aggregate operator '"+module.__name__+'.'+opname+"' name collision with other operator") + functions['aggregate'][opname] = fobject + + if isgeneratorfunction(fobject.final): + wlambda = wrapaggr(connection, fobject.final) + fobject.multiset = True + setattr(fobject, 'factory', classmethod(wrapaggregatefactory(wlambda))) + connection.createaggregatefunction(opname, fobject.factory) + else: + setattr(fobject, 'factory', classmethod(lambda cls:(cls(), cls.step, cls.final))) + connection.createaggregatefunction(opname, fobject.factory) + + try: + if fobject.multiset: + multiset_functions[opname] = True + except: + pass + + +def testfunction(): + global test_connection, settings + + test_connection = Connection(':memory:') + register(test_connection) + variables.execdb=':memory:' + +def settestdb(testdb): + global test_connection, settings + + abstestdb=str(os.path.abspath(os.path.expandvars(os.path.expanduser(os.path.normcase(testdb))))) + test_connection = Connection(abstestdb) + register(test_connection) + variables.execdb=abstestdb + +def sql(sqlquery): + import locale + from lib import pptable + global test_connection + + language, output_encoding = locale.getdefaultlocale() + + if output_encoding==None: + output_encoding="UTF8" + + test_cursor=test_connection.cursor() + + e=test_cursor.execute(sqlquery.decode(output_encoding)) + try: + desc=test_cursor.getdescription() + print pptable.indent([[x[0] for x in desc]]+[x for x in e], hasHeader=True), + except apsw.ExecutionCompleteError: + print '', + test_cursor.close() + +def table(tab, num=''): + import shlex + """ + Creates a test table named "table". It's columns are fitted to the data + given to it and are automatically named a, b, c, ... + + 'num' parameter: + If a 'num' parameter is given then the table will be named for example + table1 when num=1, table2 when num=2 ... + + Example: + + table(''' + 1 2 3 + 4 5 6 + ''') + + will create a table named 'table' having the following data: + + a b c + --------- + 1 2 3 + 4 5 6 + + """ + + colnames="abcdefghijklmnop" + import re + tab=tab.splitlines() + tab=[re.sub(r'[\s\t]+',' ',x.strip()) for x in tab] + tab=[x for x in tab if x!=''] + # Convert NULL to None + tab=[[(y if y!='NULL' else None) for y in shlex.split(x)] for x in tab] + + numberofcols=len(tab[0]) + + if num=='': + num='0' + + createsql='create table table'+str(num)+'(' + insertsql="insert into table"+str(num)+" values(" + for i in range(0,numberofcols): + createsql=createsql+colnames[i]+' str'+',' + insertsql=insertsql+'?,' + + createsql=createsql[0:-1]+')' + insertsql=insertsql[0:-1]+')' + + test_cursor=test_connection.cursor() + try: + test_cursor.execute(createsql) + except: + test_cursor.execute("drop table table"+str(num)) + test_cursor.execute(createsql) + + test_cursor.executemany(insertsql, tab) + +def table1(tab): + table(tab, num=1) + +def table2(tab): + table(tab, num=2) + +def table3(tab): + table(tab, num=3) + +def table4(tab): + table(tab, num=4) + +def table5(tab): + table(tab, num=5) + +def table6(tab): + table(tab, num=6) + +def setlogfile(file): + pass diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/__init__.py b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/date.py b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/date.py new file mode 100644 index 0000000..74e9853 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/date.py @@ -0,0 +1,271 @@ +import Queue +import setpath +import functions +import datetime +from lib import iso8601 + +__docformat__ = 'reStructuredText en' + +def timedelta2millisec(tdelta): + return tdelta.days*24*60*60*1000+tdelta.seconds*1000+tdelta.microseconds/1000 + +class mindtdiff: + """ + .. function:: mindtdiff(date) + + Returns the minimum difference *date* values of the group in milliseconds. Input dates should be in :ref:`ISO 8601 format `. + + Examples: + + >>> table1(''' + ... '2007-01-01 00:03:13' + ... '2007-01-01 00:03:27' + ... '2007-01-01 00:03:36' + ... '2007-01-01 00:04:39' + ... '2007-01-01 00:04:40' + ... '2007-01-01 00:04:49' + ... ''') + >>> sql("select mindtdiff(a) from table1") + mindtdiff(a) + ------------ + 1000 + +.. doctest:: + :hide: + + >>> sql("select mindtdiff(a) from (select '2005-01-01' as a) ") + mindtdiff(a) + ------------ + None + >>> sql("select mindtdiff(a) from (select 5 as a where a!=5) ") + mindtdiff(a) + ------------ + None + + """ + registered=True + + def __init__(self): + self.dates=Queue.PriorityQueue() + + def step(self, *args): + if not args: + raise functions.OperatorError("mindtdiff","No arguments") + dt=iso8601.parse_date(args[0]) + self.dates.put_nowait(dt) + + + + def final(self): + mindiff=None + dtp=None + if not self.dates: + return + while not self.dates.empty(): + if not mindiff: + if not dtp: + dtp=self.dates.get_nowait() + continue + dt=self.dates.get_nowait() + diff=timedelta2millisec(dt-dtp) + if mindiff==None: + mindiff=diff + elif mindiff>diff: + mindiff=diff + dtp=dt + import types + + return mindiff + +class avgdtdiff: + """ + .. function:: avgdtdiff(date) + + Returns the average difference *date* values of the group in milliseconds. Input dates should be in :ref:`ISO 8601 format `. + + Examples: + + >>> table1(''' + ... '2007-01-01 00:04:37' + ... '2007-01-01 00:04:39' + ... '2007-01-01 00:04:40' + ... '2007-01-01 00:04:49' + ... ''') + >>> sql("select avgdtdiff(a) from table1") + avgdtdiff(a) + ------------ + 3000.0 + + +.. doctest:: + :hide: + + + >>> sql("select avgdtdiff(a) from (select '2005-01-01' as a) ") + avgdtdiff(a) + ------------ + None + >>> sql("select avgdtdiff(a) from (select 5 as a where a!=5) ") + avgdtdiff(a) + ------------ + None + """ + registered=True + + def __init__(self): + self.dates=Queue.PriorityQueue() + + def step(self, *args): + if not args: + raise functions.OperatorError("avgdtdiff","No arguments") + dt=iso8601.parse_date(args[0]) + self.dates.put_nowait(dt) + + + + def final(self): + avgdiff=0 + cntdiff=0 + dtp=None + while not self.dates.empty(): + if avgdiff==0: + if not dtp: + cntdiff+=1 + dtp=self.dates.get_nowait() + continue + dt=self.dates.get_nowait() + diff=timedelta2millisec(dt-dtp) + cntdiff+=1 + avgdiff+=diff + dtp=dt + if cntdiff<2: + return None + return float(avgdiff)/cntdiff + +class dategroupduration: + """ + .. function:: dategroupduration(date) + + Returns the duration of the group of dates in seconds. Input dates should be in :ref:`ISO 8601 format `. + + Examples: + + >>> table1(''' + ... '2007-01-01 00:04:37' + ... '2007-01-01 00:04:39' + ... '2007-01-01 00:04:40' + ... '2007-01-01 00:04:49' + ... ''') + >>> sql("select dategroupduration(a) from table1") + dategroupduration(a) + -------------------- + 12 + + >>> sql("select dategroupduration(a) from (select '2005-01-01' as a) ") + dategroupduration(a) + -------------------- + 0 + + """ + registered=True + + def __init__(self): + self.datemin = None + self.datemax = None + + def step(self, *args): + pdate = iso8601.parse_date(args[0]) + + if self.datemin == None: + self.datemin = pdate + + if self.datemax == None: + self.datemax = pdate + + if pdate < self.datemin: + self.datemin = pdate + + if pdate > self.datemax: + self.datemax = pdate + + def final(self): + if self.datemin == None or self.datemax == None: + return 0 + + diff=self.datemax - self.datemin + + return diff.days*86400+diff.seconds + + +class frecencyindex: + """ + .. function:: frecencyindex(date) + + Returns the frecency Index which is computed based on a set of *date* values, using predifend time-windows. + Input dates should be in :ref:`ISO 8601 format `. + + Examples: + + >>> table1(''' + ... '2011-04-01 00:04:37' + ... '2011-01-01 00:04:39' + ... '2011-02-12 00:04:40' + ... '2011-02-14 00:04:49' + ... ''') + >>> sql("select frecencyindex(a) from table1") + frecencyindex(a) + ---------------- + 2.9 + + """ + registered=True + + def __init__(self): + self.monthCounter=0 + self.trimesterCounter=0 + self.semesterCounter=0 + self.yearCounter=0 + self.twoyearsCounter=0 + + def step(self, *args): + if not args: + raise functions.OperatorError("frecencyindex","No arguments") + + now = datetime.datetime.now() + now = iso8601.parse_date(now.strftime("%Y-%m-%d %H:%M:%S")) + d = args[0].replace('T',' ') + dt = iso8601.parse_date(args[0].replace('Z','')) + diff=now-dt + + if (diff.days)<30: + self.monthCounter+=1 + elif (diff.days)<3*30: + self.trimesterCounter+=1 + elif (diff.days)<6*30: + self.semesterCounter+=1 + elif (diff.days)<12*30: + self.yearCounter+=1 + elif (diff.days)<24*30: + self.twoyearsCounter+=1 + + + + def final(self): + + return self.monthCounter*1 + self.trimesterCounter*0.7 + self.semesterCounter*0.5 + self.yearCounter*0.3+ self.twoyearsCounter*0.2 + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/graph.py b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/graph.py new file mode 100644 index 0000000..738922b --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/graph.py @@ -0,0 +1,635 @@ +__docformat__ = 'reStructuredText en' + +import setpath +import json +from hashlib import md5 +from binascii import b2a_base64 +import math +import collections +import functions + +class graphpowerhash: + """ + .. function:: graphpowerhash(steps, [undirected_edge], node1, node2, [node1_details, edge_details, node2_details]) -> jpack of graph node hashes + + Graph power hashing is based on a `power iteration algorithm `_ + that calculates hashes on every processing step. The produced output, contains for every node in the input graph + a hash that "describes" its "surroundings". + + Parameters: + + :steps: + The *steps* option controls the number of steps that the power hashing will be executed for. Another + way to conceptualize the *steps* parameter is to think of it as the radius of the graph around + a particular node that the node's hash covers. + + Steps parameter's possible value are: + + - null (default). When steps=null, then steps is automatically set to number_of_nodes/2 + - Positive integer value. + - -1 . Steps is set to number_of_nodes + - Negative integers, steps is set to number_of_nodes / absolute_value(steps) + + :undirected_edge': + + This option can only have the *null* value. + + - Parameter absent. The graph is assumed to be directed. + - Parameter present and having a *null* value. The graph is assumed to be undirected + + :node1,node2: + + Node1 connects to Node2. If node1 doesn't connect to any node, then *node2*'s value should be null. + + :node and edge details: + + Optional details, that are processed with the graph's structure. In essence these + parameters define "tags" on the nodes and edges of the graph. + + .. note:: + The graph power hash algorithm is an experimental algorithm created by me, Lefteris Stamatogiannakis. I haven't + proved its correctness, so please use it with care. Due to its hash usage, there is a (very low probability) + that two different graphs could hash to the same power hash. + + I would be very very thankfull to anyone knowledgable in graph theory, who could prove it to be wrong (or correct). + If the reader knows of a paper that describes another algorithm similar to this algorithm, i would be glad to be pointed towards it. + + .. note:: + The computational complexity of the powerhash algorithm is O(n * steps * average_node_degree). The optimal value for + the hash to fully cover the graph, is to set the steps parameter to *graph_diameter* / 2. + + Right now for steps=null, we take the worse upper bound of n / 2, so the computational complexity becomes + O(n * ~(n/2) * average_node_degree). + + Examples: + + Directed graph: + + >>> table1(''' + ... 1 2 + ... 2 3 + ... 3 4 + ... 4 5 + ... 5 3 + ... ''') + + >>> sql("select graphpowerhash(null, a,b) from table1") + graphpowerhash(null, a,b) + ------------------------------------------------------------------------------------------------------------------------------ + ["OaNj+OtIZPqcwjc3QVvKpg","Um7OU79ApcRNA2TKrdcBcA","ZyQT/AoKyjIkwWMNvceK2A","3vaHWSLU/H32HvHTVBkpUQ","+3uZjYUMSXwyZs7HFHKNVg"] + + + Above graph having its nodes renumbered (its powerhash is the same as above): + + >>> table2(''' + ... 2 5 + ... 5 4 + ... 4 1 + ... 1 3 + ... 3 4 + ... ''') + + >>> sql("select graphpowerhash(null, a,b) from table2") + graphpowerhash(null, a,b) + ------------------------------------------------------------------------------------------------------------------------------ + ["OaNj+OtIZPqcwjc3QVvKpg","Um7OU79ApcRNA2TKrdcBcA","ZyQT/AoKyjIkwWMNvceK2A","3vaHWSLU/H32HvHTVBkpUQ","+3uZjYUMSXwyZs7HFHKNVg"] + + + Above graph with a small change (its hash differs from above graphs): + + >>> table3(''' + ... 2 5 + ... 5 4 + ... 4 1 + ... 1 3 + ... 3 5 + ... ''') + + >>> sql("select graphpowerhash(null, a,b) from table3") + graphpowerhash(null, a,b) + ------------------------------------------------------------------------------------------------------------------------------ + ["APq1eISun1GpYjgUhiMrLA","NPPh9FLzC5cUedxldXV77Q","VVZ93zo6gePuMeRf6f00Zg","df/4yDABlitCTfOGut0NvA","lqo+lY4fcjqujlgsYr+3Yw"] + + + Actual testing of equality or inequality of above graphs: + + >>> sql("select hashmd5( (select graphpowerhash(null, a,b) from table1) )=hashmd5( (select graphpowerhash(null, a,b) from table2) ) as grapheq") + grapheq + ------- + 1 + + >>> sql("select hashmd5( (select graphpowerhash(null, a,b) from table1) )=hashmd5( (select graphpowerhash(null, a,b) from table3) ) as grapheq") + grapheq + ------- + 0 + + + Graph with only one node: + + >>> sql("select graphpowerhash(null, a, null) from (select * from table1 limit 1)") + graphpowerhash(null, a, null) + ----------------------------- + ["TOiuilAk4RLkg01tIwyvcg"] + + + Undirected version of table1's graph: + + >>> sql("select graphpowerhash(null, null, a,b) from table1") + graphpowerhash(null, null, a,b) + ------------------------------------------------------------------------------------------------------------------------------ + ["JudlYSkYV7rFHjk94abY/A","W88IN4kgDSeVX9kaY36SJg","W88IN4kgDSeVX9kaY36SJg","6ez9ee0N2ogdvKJVQ8VKWA","7gz+LT/LtsyFc+GxMUlL8g"] + + + Same graph as above, but some of the edges have been reversed (the undirected powerhash matches the powerhash above): + + >>> table4(''' + ... 2 1 + ... 2 3 + ... 3 4 + ... 4 5 + ... 3 5 + ... ''') + + >>> sql("select graphpowerhash(null, null, a,b) from table4") + graphpowerhash(null, null, a,b) + ------------------------------------------------------------------------------------------------------------------------------ + ["JudlYSkYV7rFHjk94abY/A","W88IN4kgDSeVX9kaY36SJg","W88IN4kgDSeVX9kaY36SJg","6ez9ee0N2ogdvKJVQ8VKWA","7gz+LT/LtsyFc+GxMUlL8g"] + + + Graph similarity, using the step parameter (value of step defines the radius of the similar subgraphs that can be found): + + >>> sql("select jaccard( (select graphpowerhash(3, a, b) from table1), (select graphpowerhash(3, a, b) from table3) ) as jacsim") + jacsim + ------ + 0.0 + + >>> sql("select jaccard( (select graphpowerhash(1, a, b) from table1), (select graphpowerhash(1, a, b) from table3) ) as jacsim") + jacsim + ------ + 0.25 + + + Powerhash of graph having details (using a chemical composition): + + >>> table5(''' + ... 1 2 O = C + ... 2 3 C = O + ... ''') + + First without details: + + >>> sql("select graphpowerhash(null, null, a, b) from table5") + graphpowerhash(null, null, a, b) + ---------------------------------------------------------------------------- + ["Rw3sDN24TI7YARBNOOmYSg","9m5wcZf9iUxDwgzQkzu6Ag","9m5wcZf9iUxDwgzQkzu6Ag"] + + Second with all details: + + >>> sql("select graphpowerhash(null, null, a, b, c, d, e) from table5") + graphpowerhash(null, null, a, b, c, d, e) + ---------------------------------------------------------------------------- + ["CPebw+eZYzw5bWgx47/tkg","CPebw+eZYzw5bWgx47/tkg","WNn4aDDBKcoMMi+nrz5JEA"] + + """ + + registered=True + + def __init__(self): + self.nodes={} + self.steps=None + + def step(self, *args): + directed=True + argslen=len(args) + largs=args + + if largs[0]!=None: + self.steps=largs[0] + + if largs[1]==None: + directed=False + largs=list(largs) + del(largs[1]) + argslen-=1 + + if directed: + if argslen>4: + edgedetailslr='1'+chr(30)+str(largs[4]) + edgedetailsrl='0'+chr(30)+str(largs[4]) + else: + edgedetailslr='1' + edgedetailsrl='0' + else: + if argslen>4: + edgedetailslr='1'+ chr(30)+str(largs[4]) + edgedetailsrl=edgedetailslr + else: + edgedetailslr='1' + edgedetailsrl=edgedetailslr + + if largs[1] not in self.nodes: + if argslen>3: + self.nodes[largs[1]]=[ [( largs[2],edgedetailslr )] , str(largs[3])] + else: + self.nodes[largs[1]]=[ [( largs[2],edgedetailslr )] , ''] + else: + self.nodes[largs[1]][0].append( ( largs[2],edgedetailslr ) ) + + + if largs[2]!=None: + if largs[2] not in self.nodes: + if argslen>5: + self.nodes[largs[2]]=[ [(largs[1],edgedetailsrl )], str(largs[5])] + else: + self.nodes[largs[2]]=[ [(largs[1],edgedetailsrl )] , ''] + else: + self.nodes[largs[2]][0].append( ( largs[1],edgedetailsrl ) ) + + def final(self): + ncount=len(self.nodes) + + for n,v in self.nodes.iteritems(): + v[1]=str(len(v[0]))+chr(31)+v[1] + + if ncount==1: + self.steps=1 + + if self.steps==None: + # Calculate approximate worse case diameter + degreeseq=set() + mindegree=ncount + maxdegree=0 + invdegree=0.0 + + for n,v in self.nodes.iteritems(): + ndegree=len(v[0]) + mindegree=min(mindegree, ndegree) + maxdegree=max(maxdegree, ndegree) + degreeseq.add(ndegree) + invdegree+=1.0/ndegree + + self.steps=int(min( + # Obvious upper bounds + ncount-max(2, maxdegree) + 2, + # P. Dankelmann "Diameter and inverse degree" + (3*invdegree+3)*math.log(ncount)/math.log(math.log(ncount)) if ncount>16 else ncount, + # Simon Mukwembi "A note on diameter and the degree sequence of a graph" + 1+3*(ncount - len(degreeseq)+1)/float((mindegree+1)), ncount - len(degreeseq)+2))/2 + + if self.steps<0: + self.steps=ncount/abs(self.steps) + + nhashes={} + + for n,v in self.nodes.iteritems(): + nhashes[n]=md5(str(v[1]+chr(30))).digest() + + if ncount>1: + for s in xrange(self.steps): + nhashes1={} + nhashcount={} + for n, v in self.nodes.iteritems(): + nhash=md5(v[1]+chr(30)+chr(30).join(sorted([nhashes[x]+chr(29)+y for x,y in v[0]]))).digest() + nhashes1[n]=nhash + if nhash in nhashcount: + nhashcount[nhash]+=1 + else: + nhashcount[nhash]=1 + nhashes=nhashes1 + +# TODO Find new upper bound of diameter via calculating Spanning Tree starting from distincthash +# if len(nhashcount)>0: +# distincthash=min([x for x,y in nhashcount.iteritems() if y==1]) + + + return json.dumps([b2a_base64(x)[0:-3] for x in sorted(nhashes.values())], separators=(',',':'), ensure_ascii=False) + +class graphtodot: + """ + .. function:: graphtodot(graphname, [undirected_edge], node1, node2, [node1_details, edge_details, node2_details]) -> graphviz dot graph + + Returns the *Graphviz* DOT representation of the input graph. + + Examples: + + Directed graph: + + >>> table1(''' + ... 1 2 + ... 2 3 + ... 3 4 + ... 4 5 + ... 5 3 + ... ''') + + >>> sql("select graphtodot(null, a,b) from table1") + graphtodot(null, a,b) + ------------------------------------------------------------------------ + digraph { + "1" -> "2"; + "2" -> "3"; + "3" -> "4"; + "4" -> "5"; + "5" -> "3"; + } + + Undirected graph: + + >>> table2(''' + ... 2 5 + ... 5 4 + ... 4 1 + ... 1 3 + ... 3 4 + ... ''') + + >>> sql("select graphtodot(null, null, a,b) from table2") + graphtodot(null, null, a,b) + ---------------------------------------------------------------------- + graph { + "1" -- "3"; + "2" -- "5"; + "3" -- "4"; + "4" -- "1"; + "5" -- "4"; + } + + Graph with details: + + >>> table5(''' + ... 1 2 O = C + ... 2 3 C = O + ... ''') + + >>> sql("select graphtodot('chem_comp_1', null, a, b, c, d, e) from table5") + graphtodot('chem_comp_1', null, a, b, c, d, e) + ------------------------------------------------------------------------------------------------------------------------ + graph chem_comp_1 { + "1" [label="O"]; + "1" -- "2" [label="="]; + "2" [label="C"]; + "2" -- "3" [label="="]; + "3" [label="O"]; + } + + """ + + registered=True + + def __init__(self): + self.nodes={} + self.steps=None + self.graphname=None + self.directed=True + + def step(self, *args): + directed=True + argslen=len(args) + largs=args + + if largs[0]!=None: + self.graphname=largs[0] + + if largs[1]==None: + self.directed=False + largs=list(largs) + del(largs[1]) + argslen-=1 + + if argslen>4: + edgedetailslr=unicode(largs[4]) + else: + edgedetailslr=None + + if largs[1] not in self.nodes: + if argslen>3: + self.nodes[largs[1]]=[ [( largs[2],edgedetailslr )] , largs[3]] + else: + self.nodes[largs[1]]=[ [( largs[2],edgedetailslr )] , None] + else: + self.nodes[largs[1]][0].append( ( largs[2],edgedetailslr ) ) + + + if largs[2]!=None: + if largs[2] not in self.nodes: + if argslen>5: + self.nodes[largs[2]]=[ [], largs[5]] + else: + self.nodes[largs[2]]=[ [] , None] + + def final(self): + if self.graphname==None: + self.graphname='' + + if type(self.graphname) in (int, float): + self.graphname=u'g'+unicode(self.graphname) + else: + self.graphname=unicode(self.graphname) + + dot=u'' + if self.directed: + dot=u'di' + + if self.graphname==None: + self.graphname='""' + + dot+=u'graph '+self.graphname+u' {\n' + + digraph=False + + for n,v in self.nodes.iteritems(): + if v[1]!=None: + dot+=json.dumps(unicode(n))+' [label="'+unicode(v[1]).replace('"',"'")+'"];\n' + for e in v[0]: + dot+=json.dumps(unicode(n)) + ' ' + if self.directed: + dot+='-> ' + else: + dot+='-- ' + dot += json.dumps(unicode(e[0])) + if e[1]!=None: + dot+=u' [label="'+unicode(e[1]).replace('"',"'")+'"]' + dot+=u';\n' + + dot+='}' + + return dot + +class graphtotgf: + """ + .. function:: graphtotgf(node1, node2, [node1_details, edge_details, node2_details]) -> TGF graph + + Returns the TGF representation of the input graph. + + Examples: + + >>> table1(''' + ... 1 2 + ... 2 3 + ... 3 4 + ... 4 5 + ... 5 3 + ... ''') + + >>> sql("select graphtotgf(a,b) from table1") # doctest: +NORMALIZE_WHITESPACE + graphtotgf(a,b) + ------------------------------------------ + 1 + 2 + 3 + 4 + 5 + # + 1 2 + 2 3 + 3 4 + 4 5 + 5 3 + + Graph with details: + + >>> table5(''' + ... 1 2 O = C + ... 2 3 C = O + ... ''') + + >>> sql("select graphtotgf(a, b, c, d, e) from table5") + graphtotgf(a, b, c, d, e) + -------------------------- + 1 O + 2 C + 3 O + # + 1 2 = + 2 3 = + + """ + + registered=True + + def __init__(self): + self.nodes={} + self.steps=None + self.directed=True + + def step(self, *args): + argslen=len(args) + largs=args + + if argslen>3: + edgedetailslr=unicode(largs[3]) + else: + edgedetailslr=None + + if largs[0] not in self.nodes: + if argslen>2: + self.nodes[largs[0]]=[ [( largs[1],edgedetailslr )] , largs[2]] + else: + self.nodes[largs[0]]=[ [( largs[1],edgedetailslr )] , None] + else: + self.nodes[largs[0]][0].append( ( largs[1],edgedetailslr ) ) + + + if largs[1]!=None: + if largs[1] not in self.nodes: + if argslen>4: + self.nodes[largs[1]]=[ [], largs[4]] + else: + self.nodes[largs[1]]=[ [] , None] + + def final(self): + tgf='' + + def clearname(n): + return unicode(n).replace(' ','_').replace('"',"'") + + for n,v in self.nodes.iteritems(): + tgf+=clearname(n) + ' ' + (clearname(v[1]) if v[1]!=None else '') +'\n' + + tgf+='#\n' + + for n,v in self.nodes.iteritems(): + for e in v[0]: + tgf+=clearname(n)+ ' ' + clearname(e[0])+ ' '+ (clearname(e[1]) if e[1]!=None else '') + '\n' + + return tgf + +class graphcliques: + """ + .. function:: graphcliques(node1, node2) -> graph cliques + + Finds and returns the cliques in the graph defined by the node1<->node2 links. + + Examples: + + >>> table1(''' + ... n1 n2 + ... n2 n3 + ... n1 n3 + ... n3 n4 + ... n4 n5 + ... n5 n3 + ... n1 n6 + ... ''') + + >>> sql("select graphcliques(a,b) from table1") # doctest: +NORMALIZE_WHITESPACE + cliqueid | nodeid + ----------------- + 0 | n1 + 0 | n2 + 0 | n3 + 1 | n3 + 1 | n4 + 1 | n5 + + """ + + registered=True + + def __init__(self): + self.G = collections.defaultdict(set) + + def step(self, *args): + if len(args)!=2: + raise functions.OperatorError('graphcliques', 'Two parameters should be provided') + + self.G[args[0]].add(args[1]) + self.G[args[1]].add(args[0]) + + def _bors_kerbosch(self, R, P, X): + if not P and not X: # if both are empty + if len(R) > 2: + yield sorted(R) + return + + pivot = max(((len(self.G[v]), v) for v in P.union(X)))[1] + + for v in P.difference(self.G[pivot]): + for c in self._bors_kerbosch(R.union((v,)), P.intersection(self.G[v]), X.intersection(self.G[v])): + yield c + P.remove(v) + X.add(v) + + def final(self): + cid = 0 + + yield ('cliqueid', 'nodeid') + for c in self._bors_kerbosch(set([]), set(self.G.keys()), set([])): + for n in c: + yield cid, n + cid += 1 + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/jpacks.py b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/jpacks.py new file mode 100644 index 0000000..44f845b --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/jpacks.py @@ -0,0 +1,356 @@ +__docformat__ = 'reStructuredText en' + +import setpath +import lib.jopts as jopts +import json +from collections import OrderedDict + +try: + from collections import OrderedDict +except ImportError: + # Python 2.6 + from lib.collections26 import OrderedDict + + +class jgroup: + """ + .. function:: jgroup(columns) + + Groups columns of a group into a jpack. + + Example: + + >>> table1(''' + ... word1 1 + ... word2 1 + ... word3 2 + ... word4 2 + ... ''') + >>> sql("select jgroup(a) from table1 group by b") + jgroup(a) + ----------------- + ["word1","word2"] + ["word3","word4"] + >>> sql("select jgroup(a,b) from table1") + jgroup(a,b) + ------------------------------------------------- + [["word1",1],["word2",1],["word3",2],["word4",2]] + + >>> table2(''' + ... [1,2] 1 + ... [3,4] 1 + ... [5,6] 2 + ... [7,8] 2 + ... ''') + + >>> sql("select jgroup(a) from table2") + jgroup(a) + ------------------------- + [[1,2],[3,4],[5,6],[7,8]] + + >>> sql("select jgroup(a,b) from table2") + jgroup(a,b) + ----------------------------------------- + [[[1,2],1],[[3,4],1],[[5,6],2],[[7,8],2]] + + >>> sql("select jgroup(jdict('a',a,'b',b)) from table2") + jgroup(jdict('a',a,'b',b)) + ------------------------------------------------------------------------- + [{"a":[1,2],"b":1},{"a":[3,4],"b":1},{"a":[5,6],"b":2},{"a":[7,8],"b":2}] + """ + + registered = True #Value to define db operator + + def __init__(self): + self.outgroup = [] + + def step(self, *args): + if len(args) == 1: + self.outgroup += (jopts.elemfromj(args[0])) + else: + self.outgroup.append(jopts.elemfromj(*args)) + + def final(self): + return jopts.toj(self.outgroup) + + +class jdictgroup: + """ + .. function:: jdictgroup(columns) + + Groups columns of a group into a jdict. + + Example: + + >>> table1(''' + ... word1 1 + ... word2 1 + ... word3 2 + ... word4 2 + ... ''') + >>> sql("select jdictgroup(a) from table1 group by b") + jdictgroup(a) + --------------------------- + {"word1":null,"word2":null} + {"word3":null,"word4":null} + + >>> sql("select jdictgroup(a,b) from table1") + jdictgroup(a,b) + ----------------------------------------- + {"word1":1,"word2":1,"word3":2,"word4":2} + + >>> table2(''' + ... [1,2] 1 + ... [3,4] 1 + ... [5,6] 2 + ... [7,8] 2 + ... ''') + + >>> sql("select jdictgroup(a) from table2") + jdictgroup(a) + ----------------------------------------------------- + {"[1,2]":null,"[3,4]":null,"[5,6]":null,"[7,8]":null} + + >>> sql("select jdictgroup(a,b) from table2") + jdictgroup(a,b) + ----------------------------------------- + {"[1,2]":1,"[3,4]":1,"[5,6]":2,"[7,8]":2} + """ + + registered = True #Value to define db operator + + def __init__(self): + self.outgroup = OrderedDict() + + def step(self, *args): + if len(args) == 1: + self.outgroup[args[0]] = None + else: + self.outgroup[args[0]] = jopts.fromjsingle(*args[1:]) + + def final(self): + return jopts.toj(self.outgroup) + + +class jgroupunion: + """ + .. function:: jgroupunion(columns) -> jpack + + Calculates the union of the jpacks (by treating them as sets) inside a group. + + Example: + + >>> table1(''' + ... '[1,2]' 6 + ... '[2,3]' 7 + ... '[2,4]' '[8,11]' + ... 5 9 + ... ''') + >>> sql("select jgroupunion(a,b) from table1") + jgroupunion(a,b) + ---------------------- + [1,2,6,3,7,4,8,11,5,9] + + >>> sql("select jgroupunion(1)") + jgroupunion(1) + -------------- + 1 + + """ + + registered = True #Value to define db operator + + def __init__(self): + self.outgroup = OrderedDict() + self.outgroupupdate = self.outgroup.update + + def step(self, *args): + self.outgroupupdate([(x, None) for x in jopts.fromj(*args)]) + + def final(self): + return jopts.toj(list(self.outgroup)) + + +class jgroupintersection: + """ + .. function:: jgroupintersection(columns) -> jpack + + Calculates the intersection of all jpacks (by treating them as sets) inside a group. + + Example: + + >>> table1(''' + ... '[1,2]' 2 + ... '[2,3]' 2 + ... '[2,4]' '[2,11]' + ... 2 2 + ... ''') + >>> sql("select jgroupintersection(a,b) from table1") + jgroupintersection(a,b) + ----------------------- + 2 + + >>> sql("select jgroupintersection(1)") + jgroupintersection(1) + --------------------- + 1 + + """ + + registered = True #Value to define db operator + + def __init__(self): + self.outgroup = None + self.outset = None + + def step(self, *args): + if self.outgroup == None: + self.outgroup = OrderedDict([(x, None) for x in jopts.fromj(args[0])]) + self.outset = set(self.outgroup) + for jp in args: + for i in self.outset.difference(jopts.fromj(jp)): + del (self.outgroup[i]) + self.outset = set(self.outgroup) + + def final(self): + return jopts.toj(list(self.outgroup)) + + +class jdictgroupunion: + """ + .. function:: jgroupunion(jdicts) -> jdict + + Calculates the union of all jdicts inside a group. The returned jdict's key values, are + calculated as the max length of the lists (or dictionaries) that have been found inside + the individual jdicts of the group. + + Example: + + >>> table1(''' + ... '{"b":1, "a":1}' + ... '{"c":1, "d":[1,2,3]}' + ... '{"b":{"1":2,"3":4}, "d":1}' + ... ''') + >>> sql("select jdictgroupunion(a) from table1") + jdictgroupunion(a) + ------------------------- + {"b":2,"a":1,"c":1,"d":3} + + """ + + registered = True #Value to define db operator + + def __init__(self): + self.outgroup = OrderedDict() + + def step(self, *args): + for d in args: + for x, v in json.loads(d, object_pairs_hook=OrderedDict).iteritems(): + vlen = 1 + if type(v) in (list, OrderedDict): + vlen = len(v) + try: + if vlen > self.outgroup[x]: + self.outgroup[x] = vlen + except KeyError: + self.outgroup[x] = vlen + + def final(self): + return json.dumps(self.outgroup, separators=(',', ':'), ensure_ascii=False) + + +class jgroupunionkeys: + """ + .. function:: jgroupunionkeys(columns) -> jpack + + Calculates the union of the jdict keys. Use it with care, because for performance + reasons the input data are not checked at all. They should all be jdicts. + + Example: + + >>> table1(''' + ... '{"1":1, "2":3}' '{"a":5}' + ... '{"2":1, "3":3}' '{}' + ... ''') + >>> sql("select jgroupunionkeys(a,b) from table1") + jgroupunionkeys(a,b) + -------------------- + ["1","2","a","3"] + + >>> sql("select jgroupunionkeys('{}')") + jgroupunionkeys('{}') + --------------------- + [] + """ + + registered = True #Value to define db operator + + def __init__(self): + self.outgroup = OrderedDict() + self.outgroupset = set() + + def step(self, *args): + for arg in args: + v = json.loads(arg) + if not set(v).issubset(self.outgroup): + self.outgroupset.update(v) + self.outgroup.update([(k, None) for k in json.loads(arg, object_pairs_hook=OrderedDict).iterkeys()]) + + def final(self): + return jopts.toj(list(self.outgroup)) + + +class jgroupuniquelimit: + """ + .. function:: jgroupuniquelimit(jpack, k, limit) -> jpack + + Returns the k where the unique values inside all jpacks have reached limit. + + Example: + + >>> table1(''' + ... '[1,2]' 1 + ... '[2,3,4,5]' 2 + ... '[2,4]' 3 + ... 5 4 + ... ''') + >>> sql("select jgroupuniquelimit(a,b,3) from table1") + jgroupuniquelimit(a,b,3) + ------------------------ + 2 + + """ + + registered = True #Value to define db operator + + def __init__(self): + self.gset = set() + self.k = None + + def step(self, *args): + if self.k is None: + self.gset.update([(x, None) for x in jopts.fromj(args[0])]) + + if len(self.gset) >= args[-1]: + self.k = args[1] + + def final(self): + return self.k + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/mining.py b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/mining.py new file mode 100644 index 0000000..3e9819b --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/mining.py @@ -0,0 +1,415 @@ +import re +import itertools +import setpath +import functions +import lib.jopts as jopts +from operator import itemgetter +import random + +__docformat__ = 'reStructuredText en' + +re_params=re.compile('(\w*):(.*)') + +def consumer(func): + """A decorator, advances func to its first yield point when called. + """ + + from functools import wraps + + @wraps(func) + def wrapper(*args,**kw): + gen = func(*args, **kw) + gen.next() + return gen + return wrapper + + +class freqitemsets: + """ + .. function:: freqitemsets(datacol, [threshold, noautothres, stats, maxlen]) -> [itemset_id:int, itemset_length:int, itemset_frequency:int, item:text] + + Calculates frequent itemsets on a given column (datacol). The algorithm is tuned for the + case when we have many different items (in the order of millions), many input itemsets, but + small itemset length (10-20). + + Returned table schema: + + :itemset_id: Automatic itemset id + :itemset_length: Length of itemset + :itemset_frequency: How many times an itemset has been found + :item: Itemset's item value + + Parameters: + + :datacol: + + Column on which to calculate frequent itemsets + + :threshold: Default is 2 + + How many times an freq. itemset must appear for it to appear in the results + + :noautothres: 1/0 (Default is 0) + + Do not calculate the threshold automatically + + :stats: 1/0 (Default is 0) + + Return frequent itemset statistics + + :maxlen: NUMBER (Default is no limit at all) + + Maximum itemset length to search + + Examples: + + >>> table1(''' + ... 'car wood bike' 'first group' + ... 'car car wood' 'first group' + ... 'car wood' 'first group' + ... 'car wood ice' 'first group' + ... 'ice' 'second group' + ... 'car ice' 'second group' + ... 'car cream toy' 'second group' + ... 'icecream ice car toy' 'second group' + ... ''') + >>> sql("select b,freqitemsets(a, 'threshold:2', 'noautothres:1', 'maxlen:2') from table1 group by b") + b | itemset_id | itemset_length | itemset_frequency | item + --------------------------------------------------------------------- + first group | 1 | 1 | 4 | wood + first group | 2 | 1 | 4 | car + first group | 3 | 2 | 4 | car + first group | 3 | 2 | 4 | wood + second group | 1 | 1 | 3 | ice + second group | 2 | 1 | 3 | car + second group | 3 | 1 | 2 | toy + second group | 4 | 2 | 2 | car + second group | 4 | 2 | 2 | ice + second group | 5 | 2 | 2 | car + second group | 5 | 2 | 2 | toy + + >>> sql("select b,freqitemsets(a, 'stats:1') from table1 group by b") + b | MaxTransactionLength | CombinationCount | PassedTransactions | ValidKeywords + ------------------------------------------------------------------------------------------- + first group | 3 | 2 | 3 | 2 + first group | 3 | 1 | 1 | 2 + first group | 3 | 0 | 0 | 0 + second group | 4 | 3 | 3 | 3 + second group | 4 | 0 | 3 | 0 + """ + + + registered=True + multiset=True + + def __init__(self): + self.threshold=2 + self.startingthreshold=2 + self.autothres=1 + self.compress=0 + self.initstatic=False + self.input={} + self.maxlength=0 + self.kwcode={} + self.codekw={} + self.maxkwcode=0 + self.overthres={} + self.belowthres={} + self.passedkw={} + self.init=True + self.itemset_id=0 + self.maxlen=None + self.stats=False + + def initargs(self, args): + self.init=False + for i in xrange(1, len(args)): + v=re_params.match(args[i]) + if v is not None and v.groups()[0]!='' and v.groups()[1]!='' and i>0: + v=v.groups() + if v[0]=='threshold': + try: + self.threshold=int(v[1]) + self.startingthreshold=self.threshold + except KeyboardInterrupt: + raise + except: + raise functions.OperatorError("FreqItemsets",'No integer value given for threshold') + if v[0]=='noautothres': + self.autothres=0 + if v[0]=='compress': + self.compress=1 + if v[0]=='maxlen': + self.maxlen=int(v[1]) + if v[0]=='stats': + self.stats=True + + def demultiplex(self, data): + iterable=None + iterpos=-1 + + for i in xrange(len(data)): + if hasattr(data[i],'__iter__')==True: + iterable=data[i] + iterpos=i + break + + if iterpos==-1: + yield list(data) + else: + pre=list(data[0:iterpos]) + post=list(data[iterpos+1:]) + for i in iterable: + if hasattr(i,'__iter__')==False: + yield pre+[i]+post + else: + yield pre+list(i)+post + + def insertcombfreq(self, comb, freq): + if comb in self.overthres: + self.overthres[comb]+=freq + else: + if comb in self.belowthres: + self.belowthres[comb]+=freq + else: + self.belowthres[comb]=freq + + if self.belowthres[comb]>=self.threshold: + self.overthres[comb]=self.belowthres[comb] + del(self.belowthres[comb]) + for k in comb: + if self.compress==0: + self.passedkw[k]=True + elif not k in self.passedkw: + self.passedkw[k]=self.overthres[comb] + else: + self.passedkw[k]+=self.overthres[comb] + + def insertitemset(self, itemset): + if itemset not in self.input: + self.input[itemset]=1 + else: + self.input[itemset]+=1 + + def cleanitemsets(self, minlength): + newitemsets={} + for k,v in self.input.iteritems(): + itemset=tuple(i for i in k if i in self.passedkw) + if self.compress==1: + esoteric_itemset=tuple(i for i in itemset if self.passedkw[i]==v) + if len(esoteric_itemset)>0: + if len(itemset)>=minlength: + self.overthres[itemset]=v + itemset=tuple(i for i in itemset if self.passedkw[i]!=v) + if len(itemset)>=minlength: + if itemset not in newitemsets: + newitemsets[itemset]=v + else: + newitemsets[itemset]+=v + + self.input=newitemsets + + def step(self, *args): + if self.init==True: + self.initargs(args) + + if len(args[0])==0: + return + + itms=sorted(set(args[0].split(' '))) + itms=[x for x in itms if x!=''] + li=len(itms) + if li>0: + if li>self.maxlength: + self.maxlength=li + + inputkws=[] + for kw in itms: + if len(kw)==0: + print itms, args[0], len(args[0]), li + if kw not in self.kwcode: + self.kwcode[kw]=self.maxkwcode + self.codekw[self.maxkwcode]=kw + inputkws.append(self.maxkwcode) + self.insertcombfreq( (self.maxkwcode,),1 ) + self.maxkwcode+=1 + else: + itm=self.kwcode[kw] + self.insertcombfreq( (itm,),1 ) + inputkws.append(itm) + + if len(inputkws)>1: + self.insertitemset(tuple(inputkws)) + + def final(self): + if not self.stats: + yield ('itemset_id', 'itemset_length', 'itemset_frequency', 'item') + else: + yield ('MaxTransactionLength', 'CombinationCount', 'PassedTransactions', 'ValidKeywords') + + splist=[{},{}] + del(self.kwcode) + splist[1]=self.overthres + + if self.stats: + yield [self.maxlength, len(splist[1]), len(self.input), len(self.passedkw)] + + if not self.stats: + for its,v in sorted(splist[1].items(), key=itemgetter(1),reverse=True): + self.itemset_id+=1 + for i in self.demultiplex( (self.itemset_id, len([self.codekw[i] for i in its]), v, [self.codekw[i] for i in its]) ): + yield i + + if self.maxlen==None: + self.maxlen=self.maxlength + for l in xrange(2, min(self.maxlength+1, self.maxlen+1)): + splist.append({}) + self.belowthres={} + self.overthres={} + prevl=l-1 + + # Autothresholding + if self.autothres==1: + if len(self.input)==0 or len(self.passedkw)==0: + break + else: + self.threshold=self.startingthreshold + int(len(self.passedkw)/len(self.input)) + + self.cleanitemsets(l) + self.passedkw={} + prevsplist = splist[prevl] + icombs = itertools.combinations + insertcomb = self.insertcombfreq + + for k,v in self.input.iteritems(): + for k in icombs(k,l): + insertit=True + for i1 in icombs(k, prevl): + if i1 not in prevsplist: + insertit=False + break + + if insertit: + insertcomb( k,v ) + + splist[l-1]={} + splist[l]=self.overthres + + if self.stats: + yield [self.maxlength, len(splist[l]), len(self.input), len(self.passedkw)] + + if not self.stats: + for its,v in sorted(splist[l].items(), key=itemgetter(1),reverse=True): + self.itemset_id+=1 + for i in self.demultiplex( (self.itemset_id, len([self.codekw[i] for i in its]), v, [self.codekw[i] for i in its]) ): + yield i + + del(self.overthres) + del(self.belowthres) + del(self.passedkw) + del(self.input) + del(self.codekw) + del(splist) + +class sampledistvals: + """ + + .. function:: sampledistvals(sample_size, C1, C2, C3) -> [C1, C2, C3] + + Sampledistvals returns sample_size distinct values for each of the input C1..Cn columns. + + >>> table1(''' + ... test1 2 3 + ... test1 2 3 + ... test2 4 2 + ... test4 2 t + ... ''') + >>> sql("select sampledistvals(3, a, b, c) from table1") + C1 | C2 | C3 + --------------------------------------------- + ["test1","test2","test4"] | [2,4] | [2,3,"t"] + """ + registered=True + + def __init__(self): + self.vals=None + self.lenargs = -1 + self.init=True + + def step(self, *args): + if self.init: + self.lenargs = len(args) + self.vals = a=[set() for i in xrange(self.lenargs-1)] + self.init = False + + for i in xrange(1, self.lenargs): + if len(self.vals[i-1])>> table1(''' + ... test1 2 3 + ... test1 2 3 + ... test2 4 2 + ... test4 2 t + ... ''') + + >>> sql("select samplegroup(2, a, b, c) from table1") # doctest: +ELLIPSIS + C1 | C2 | C3 + --------------- + ... + + >>> sql("select samplegroup(2) from (select 5 where 5=6)") # doctest: +ELLIPSIS + + """ + registered=True + + def __init__(self): + self.samplelist = [] + self.index = 0 + self.random = random.randint + + def step(self, *args): + # Generate the reservoir + if self.index < args[0]: + self.samplelist.append(args) + else: + r = self.random(0, self.index) + if r < args[0]: + self.samplelist[r] = args + + self.index += 1 + + def final(self): + if self.samplelist == []: + yield tuple(['C1']) + else: + yield tuple(['C'+str(i) for i in xrange(1, len(self.samplelist[0]))] ) + for r in self.samplelist: + yield list(r[1:]) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/partialsort.py b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/partialsort.py new file mode 100644 index 0000000..4e0afd3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/partialsort.py @@ -0,0 +1,71 @@ +import functions +import operator + +class partialsort: + """ + + .. function:: partialsort(n,col1,col2,col3,....) + + sorts the first n columns of its input + + :Returned multiset schema: + Columns are automatically named as col1, col2 ... + + + Examples: + + >>> table1(''' + ... aa 43 + ... ac 34 + ... ab 21 + ... as 23 + ... ''') + >>> sql("select partialsort(1,a,b) from table1") + c1 | c2 + ------- + aa | 43 + ab | 21 + ac | 34 + as | 23 + + """ + registered=True + + def __init__(self): + self.topn=[] + self.lessval=None + self.stepsnum=0 + self.sortnum = None + + def step(self, *args): + if len(args)<2: + raise functions.OperatorError("partialsort","Wrong number of arguments") + if not self.sortnum: + self.sortnum = tuple(i for i in xrange(args[0])) + self.topn.append(args[1:]) + self.stepsnum+=1 + pass + + def final(self): + yield tuple('c'+str(i) for i in xrange(1,len(self.topn[0])+1)) + self.topn.sort(key=operator.itemgetter(*self.sortnum)) + for el in self.topn: + yield el + + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/selection.py b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/selection.py new file mode 100644 index 0000000..fdb2fe7 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/selection.py @@ -0,0 +1,396 @@ +import setpath +import Queue +import functions + +__docformat__ = 'reStructuredText en' + +class imax: + """ + + .. function:: imax(i,value) + + Returns the i-th max value of the group. + + Examples: + + >>> table1(''' + ... 34 la + ... 18 lo + ... 120.0 all + ... ''') + >>> sql("select imax(1,a) as first from table1") + first + ----- + 120 + >>> sql("select imax(3,a) as third from table1") + third + ----- + 18 + >>> sql("select imax(2,cast( a as text)) as secstr from table1") + secstr + ------ + 18 + >>> sql("select imax(4,a) from table1") + imax(4,a) + --------- + None + >>> sql("select imax(4,a) from (select 5 as a where a!=5)") + imax(4,a) + --------- + None + + + """ + registered=True + + def __init__(self): + self.topn=None + self.size=None + self.strtype=False + self.anytype=True + self.lessval=None + self.stepsnum=0 + self.valarg=None + + def step(self, *args): + if not args: + raise functions.OperatorError("imax","No arguments") + if len(args)<2: + raise functions.OperatorError("imax","Wrong number of arguments") + if not self.size: + try: + self.size=int(args[0]) + self.topn=Queue.PriorityQueue(self.size) + except ValueError: + raise functions.OperatorError("imax","Wrong type in first argument") + + curval=args[1] + if not self.topn.full(): + self.topn.put_nowait(curval) + else: + curless=self.topn.get() + self.topn.put_nowait(max(curval,curless)) + self.stepsnum+=1 + + + def final(self): + if not self.size: + return + if self.stepsnum>> table1(''' + ... 34 la + ... 18 lo + ... 120.0 all + ... ''') + >>> sql("select minrow(a,b) as b from table1") + b + -- + lo + >>> sql("select minrow(a,a) as a from table1") + a + -- + 18 + + .. doctest:: + :hide: + + >>> sql("select minrow(a,a) as a from (select 5 as a where a!=5)") + a + ---- + None + + """ + registered=True + + + def __init__(self): + self.minv=None + + def step(self, *args): + if not args: + raise functions.OperatorError("minrow","No arguments") + if len(args)!=2: + raise functions.OperatorError("minrow","Wrong number of arguments") + if not self.minv: + self.minv=(args[0],args[1]) + elif args[0]>> table1(''' + ... 34 la + ... 18 lo + ... 120.0 all + ... ''') + >>> sql("select maxrow(a,b) as b from table1") + b + --- + all + >>> sql("select maxrow(a,a) as a from table1") + a + --- + 120 + >>> sql("select maxrow(b,a) as a from table1") + a + -- + 18 + """ + registered=True + + + def __init__(self): + self.maxv=None + self.first=True + + def step(self, *args): + if self.first: + if not args: + raise functions.OperatorError("maxrow","No arguments") + if len(args)!=2: + raise functions.OperatorError("maxrow","Wrong number of arguments") + self.maxv=(args[0],args[1]) + self.first=False + return + self.maxv=max(self.maxv,args) + + + def final(self): + if not self.maxv: + return None + return self.maxv[1] + +class groupdiff: + """ + .. function:: groupdiff(compare,values) + + Compares group members over the first argument (i.e. *compare*). It keeps only the rows where *compare* changes. + It appends a column at the end containing how many times *compare* repeats. + + Examples: + + >>> table1(''' + ... 0 a + ... 0 b + ... 1 c + ... 1 d + ... 2 e + ... 3 e + ... 3 f + ... 3 g + ... ''') + >>> sql("select groupdiff(a,b) as b from table1") + b1 | b2 | b3 + ------------ + 0 | a | 2 + 1 | c | 2 + 2 | e | 1 + 3 | e | 3 + >>> sql("select groupdiff(a) as a from table1") + a1 | a2 + ------- + 0 | 2 + 1 | 2 + 2 | 1 + 3 | 3 + >>> sql("select groupdiff(b,a) as a from table1") + a1 | a2 | a3 + ------------ + a | 0 | 1 + b | 0 | 1 + c | 1 | 1 + d | 1 | 1 + e | 2 | 2 + f | 3 | 1 + g | 3 | 1 + """ + registered=True + + def __init__(self): + self.first=True + self.data=[] + self.prevcomp=None + self.size=0 + self.repeat=1 + + def step(self, *args): + if self.first: + if not args: + raise functions.OperatorError("groupdiff","No arguments") + self.prevcomp=args[0] + self.data.append(list(args)) + self.first=False + self.size=len(args) + return + + if args[0]!=self.prevcomp: + self.prevcomp=args[0] + self.data[-1].append(self.repeat) + self.data.append(list(args)) + self.repeat=1 + else: + self.repeat+=1 + + def final(self): + self.data[-1].append(self.repeat) + yield tuple(["compid"]+["C"+str(i) for i in xrange(1,self.size)]+["repetition"]) + for i in self.data: + yield i + + +class ontop: + """ + + .. function:: ontop(n,compare,value1,value2,....) -> [colname1, colname2 ...] + + Compares group members over the second argument (i.e. *compare*), so as to locate the top *n* members + (specified in the first argument) and then returns the corresponding data under the specified columns + *value1, value2, ....*. + + :Returned multiset schema: + Columns are automatically named as *colname1 text, colname2 text...* + + .. seealso:: + + * :ref:`tutmultiset` functions + + + Examples: + + >>> table1(''' + ... 34 la + ... 18 lo + ... 120.0 all + ... ''') + >>> sql("select ontop(1,a,b) from table1") + top1 + ---- + all + >>> sql("select ontop(2,a,a,b) from table1") + top1 | top2 + ----------- + 120 | all + 34 | la + + >>> sql("select ontop(2,a,a,b,a,b) from table1") + top1 | top2 | top3 | top4 + ------------------------- + 120 | all | 120 | all + 34 | la | 34 | la + + >>> sql("select ontop(pk) from (select 5 as pk where pk!=5)") + top1 + - + """ + registered=True + multiset=True + + + def __init__(self): + self.topn=None + self.size=None + self.lessval=None + self.stepsnum=0 + self.argnum = 1 + + def step(self, *args): + if not args: + raise functions.OperatorError("ontop","No arguments") + if len(args)<3: + raise functions.OperatorError("ontop","Wrong number of arguments") + if not self.size: + try: + self.size=int(args[0]) + self.topn=Queue.PriorityQueue(self.size) + self.argnum = len(args)-2 + except ValueError: + raise functions.OperatorError("ontop","Wrong type in first argument") + + inparg=args[1] + outarg=args[2:] + + if not self.topn.full(): + self.topn.put_nowait((inparg,outarg)) + else: + inparg_old , outarg_old=self.topn.get_nowait() + self.topn.put_nowait(max((inparg,outarg),(inparg_old ,outarg_old))) + + self.stepsnum+=1 + + + def final(self): + output=[] + if self.topn: + while not self.topn.empty(): + output+=[self.topn.get_nowait()[1]] + + yield tuple(["top"+str(i+1) for i in xrange(self.argnum)]) + + for el in reversed(output): + yield el + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/setpath.py b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/setpath.py new file mode 100644 index 0000000..8ad90a0 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/setpath.py @@ -0,0 +1,3 @@ +import sys, os +curmodulepath = os.path.dirname( os.path.abspath(__file__) ) +sys.path.append(os.path.abspath(os.path.join(curmodulepath,'..','..'))) \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/statistics.py b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/statistics.py new file mode 100644 index 0000000..69621ab --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/statistics.py @@ -0,0 +1,1023 @@ +import setpath +import functions +import math +from lib import iso8601 +import re +import datetime +from fractions import Fraction +import json +from fractions import Fraction + + +__docformat__ = 'reStructuredText en' + +class modeop: + + """ + .. function:: modeop(X) -> [ModeOpElements int/str, ModeOpValue int] + + Returns the mode (i.e. the value that occurs the most frequently in a data set), along with the modevalue (i.e. the maximum frequency of occurrence) + When more than one modes are found in a data set (i.e. when more than one values appear with the maximum frequency), all values are returned. + + For a sample from a continuous distribution, such as [0.935..., 1.211..., 2.430..., 3.668..., 3.874...], the concept of mode is unusable in its raw form, + since each value will occur precisely once. Following the usual practice, data is discretized by rounding to the closer int value. + For a textual sample, values are first converted to lowercase. + + :Returned multiset schema: + Columns are automatically named as *ModeOpElements, ModeOpValue* + + .. seealso:: + + * :ref:`tutmultiset` functions + + Examples: + + >>> table1(''' + ... 1 + ... 3 + ... 6 + ... 6 + ... 6 + ... 6 + ... 7 + ... 7 + ... 7 + ... 7 + ... 12 + ... 12 + ... 17 + ... ''') + >>> sql("select modeop(a) from table1") + ModeOpElements | ModeOpValue + ---------------------------- + 6 | 4 + 7 | 4 + + + >>> table2(''' + ... 1.1235 + ... 1 + ... 5.1 + ... 5.2 + ... 5.3 + ... 5.5 + ... 5.6 + ... 5.7 + ... ''') + >>> sql("select modeop(a) from table2") + ModeOpElements | ModeOpValue + ---------------------------- + 5 | 3 + 6 | 3 + + >>> table3(''' + ... leuteris + ... maria + ... marialena + ... Meili + ... meili + ... ''') + >>> sql("select modeop(a) from table3") + ModeOpElements | ModeOpValue + ---------------------------- + meili | 2 + +.. doctest:: + :hide: + + >>> sql("delete from table3") + >>> sql("select modeop(a) from table3") + ModeOpElements | ModeOpValue + ---------------------------- + None | None + + """ + registered=True #Value to define db operator + multiset=True + + def __init__(self): + self.init=True + self.sample = [] + self.modevalue = 0 + + def initargs(self, args): + self.init=False + if not args: + raise functions.OperatorError("modeop","No arguments") + if len(args)>1: + raise functions.OperatorError("modeop","Wrong number of arguments") + + def step(self, *args): + if self.init==True: + self.initargs(args) + + if isinstance(args[0], basestring): + #For the case of textual dataset, values are converted to lowercase + self.element = (args[0]).lower() + else: + #For the case of arithmetic dataset, values are rounded and converted to int + self.element = int(round(args[0])) + self.sample.append(self.element) + + def final(self): + output=[] + + if (not self.sample): + output+=['None'] + modevalue='None' + else: + self.sample.sort() + + # Initialize a dictionary to store frequency data. + frequency = {} + # Build dictionary: key - data set values; item - data frequency. + for x in self.sample: + if (x in frequency.keys()): + frequency[x]+=1 + else: + frequency[x]=1 + # Find the modeval, i.e. the maximum frequency + modevalue = max(frequency.values()) + + # If the value of mode is 1, there is no mode for the given data set. + if (modevalue == 1): + output+=['None'] + modevalue='None' + else: + # Step through the frequency dictionary, looking for keys equaling + # the current modevalue. If found, append the key to output list. + for x in frequency: + if (modevalue == frequency[x]): + output+=[x] + + #CREATE MULTISET OUTPUT + #print all keys, along with the modevlaue + yield ("ModeOpElements", "ModeOpValue") + for el in output: + yield (el, modevalue) + + +class median: + """ + .. function:: median(X) -> [median float] + + Returns the median, i.e.numeric value separating the higher half of a sample, a population, or a probability distribution, from the lower half. + It is computed by arranging all the observations from lowest value to highest value and picking the middle one. + If there is an even number of observations, then there is no single middle value, so the mean of the two middle values is obtained. + Incoming textual values are simply ignored. + + Examples: + + >>> table1(''' + ... 1 + ... 3 + ... 6 + ... 6 + ... 6 + ... 6 + ... 7 + ... 7 + ... 7 + ... 7 + ... 12 + ... 12 + ... 17 + ... ''') + >>> sql("select median(a) from table1") + median(a) + --------- + 7.0 + + >>> table2(''' + ... 1 + ... 2 + ... 2 + ... 3 + ... 3 + ... 9 + ... ''') + >>> sql("select median(a) from table2") + median(a) + --------- + 2.5 + + >>> table3(''' + ... 1 + ... 2 + ... maria + ... lala + ... null + ... 'None' + ... 3 + ... 9 + ... ''') + >>> sql("select median(a) from table3") + median(a) + --------- + 2.5 + +.. doctest:: + :hide: + + >>> sql("delete from table3") + >>> sql("select median(a) from table3") + median(a) + --------- + None + + """ + registered=True #Value to define db operator + + def __init__(self): + self.init=True + self.sample = [] + self.counter=0 + + def initargs(self, args): + self.init=False + if not args: + raise functions.OperatorError("median","No arguments") + if len(args)>1: + raise functions.OperatorError("median","Wrong number of arguments") + + def step(self, *args): + if self.init==True: + self.initargs(args) + + if not(isinstance(args[0], basestring)) and args[0]: + self.counter +=1 + self.element = float((args[0])) + self.sample.append(self.element) + + def final(self): + if (not self.sample): + return + self.sample.sort() + + """Determine the value which is in the exact middle of the data set.""" + if (self.counter%2): # Number of elements in data set is even. + self.median = self.sample[self.counter/2] + else: # Number of elements in data set is odd. + midpt = self.counter/2 + self.median = (self.sample[midpt-1] + self.sample[midpt])/2.0 + + return self.median + + + +class variance: + """ + .. function:: variance(X,[type]) -> [variance float] + + Determine the measure of the spread of the data set about the mean. + Sample variance is determined by default; population variance can be + determined by setting the (optional) second argument to values 'true' or 'population'. + When values 'false' or 'sample' are entered for type, the default sample variance computation is performed. + + Examples: + + >>> table1(''' + ... 1 + ... 2 + ... 3 + ... 4 + ... 5 + ... 6 + ... 'text is ignored' + ... 'none' + ... ''') + >>> sql("select variance(a) from table1") + variance(a) + ----------- + 3.5 + >>> sql("select variance(a,'false') from table1") + variance(a,'false') + ------------------- + 3.5 + >>> sql("select variance(a,'sample') from table1") + variance(a,'sample') + -------------------- + 3.5 + >>> sql("select variance(a,'True') from table1") + variance(a,'True') + ------------------ + 2.91666666667 + >>> sql("select variance(a,'Population') from table1") + variance(a,'Population') + ------------------------ + 2.91666666667 + +.. doctest:: + :hide: + + >>> sql("delete from table1") + >>> sql("select variance(a) from table1") + variance(a) + ----------- + None + """ + registered=True #Value to define db operator + + def __init__(self): + self.init=True + self.population=False + self.n=0 + self.mean=Fraction(0.0) + self.M2=Fraction(0.0) + + def initargs(self, args): + self.init=False + if not args: + raise functions.OperatorError("sdev","No arguments") + elif len(args)==2: + tmp = args[1].lower() + if tmp=='false' or tmp=='sample': + self.population=False + elif tmp=='true' or tmp=='population': + self.population=True + else: + raise functions.OperatorError("sdev", "Wrong value in second argument"+'\n'+ + "Accepted Values:"+'\n' + "----False, false, FALSE, sample---- for Sample Standard Deviation"+'\n'+ + "----True, true, TRUE, population---- for Population Standard Deviation"+'\n') + elif len(args)>2: + raise functions.OperatorError("sdev","Wrong number of arguments") + + def step(self, *args): + if self.init==True: + self.initargs(args) + + try: + x=Fraction(args[0]) + except KeyboardInterrupt: + raise + except: + return + self.n+=1 + delta=x-self.mean + self.mean += delta / self.n + if self.n > 1: + self.M2 += delta * (x - self.mean) + + def final(self): + if self.n==0: + return None + try: + if (not self.population and self.n>1): # Divide sum of squares by N-1 (sample variance). + variance = self.M2/(self.n-1) + else: # Divide sum of squares by N (population variance). + variance = self.M2/self.n + except: + variance = 0.0 + + return float(variance) + + +class stdev: + """ + .. function:: stdev(X,[type]) -> [stdev float] + + Computes standard deviation of a dataset X, i.e. the square root of its variance. + Sample standard deviation is determined by default; population standard deviation can be + determined by setting the (optional) second argument to values 'true' or 'population'. + When values 'false' or 'sample' are entered for type, the default sample standard deviation + computation is performed. + + Examples: + + >>> table1(''' + ... 3 + ... 7 + ... 7 + ... 19 + ... 'text is ignored' + ... 'none' + ... ''') + >>> sql("select stdev(a) from table1") + stdev(a) + ------------- + 6.92820323028 + >>> sql("select stdev(a,'population') from table1") + stdev(a,'population') + --------------------- + 6.0 + >>> sql("select stdev(a,'true') from table1") + stdev(a,'true') + --------------- + 6.0 + +.. doctest:: + :hide: + + >>> sql("delete from table1") + >>> sql("select stdev(a) from table1") + stdev(a) + -------- + None + + """ + + registered=True #Value to define db operator + + def __init__(self): + self.init=True + self.population=False + self.n=0 + self.mean=Fraction(0.0) + self.M2=Fraction(0.0) + + def initargs(self, args): + self.init=False + if not args: + raise functions.OperatorError("sdev","No arguments") + elif len(args)==2: + tmp = args[1].lower() + if tmp=='false' or tmp=='sample': + self.population=False + elif tmp=='true' or tmp=='population': + self.population=True + else: + raise functions.OperatorError("sdev", "Wrong value in second argument"+'\n'+ + "Accepted Values:"+'\n' + "----False, false, FALSE, sample---- for Sample Standard Deviation"+'\n'+ + "----True, true, TRUE, population---- for Population Standard Deviation"+'\n') + elif len(args)>2: + raise functions.OperatorError("sdev","Wrong number of arguments") + + def step(self, *args): + if self.init==True: + self.initargs(args) + + try: + x=Fraction(args[0]) + except KeyboardInterrupt: + raise + except: + return + self.n+=1 + delta=x-self.mean + self.mean += delta / self.n + if self.n > 1: + self.M2 += delta * (x - self.mean) + + def final(self): + if self.n==0: + return None + try: + if (not self.population and self.n>1): # Divide sum of squares by N-1 (sample variance). + variance = self.M2/(self.n-1) + else: # Divide sum of squares by N (population variance). + variance = self.M2/self.n + except: + variance = 0.0 + + return math.sqrt(variance) + + +class rangef: + + """ + .. function:: rangef(X) -> [rangef float] + + Computes the numerical range for a dataset X, substracting the minimum value from the maximum value. + Textal and NULL data entries are simply ignored. + + Examples: + + >>> table1(''' + ... 1 + ... 3 + ... 6 + ... 6 + ... 7 + ... 12 + ... 12 + ... 17 + ... 'text is ignored' + ... 'None' + ... ''') + >>> sql("select rangef(a) from table1") + rangef(a) + --------- + 16.0 + +.. doctest:: + :hide: + + >>> sql("delete from table1") + >>> sql("select rangef(a) from table1") + rangef(a) + --------- + None + """ + registered=True #Value to define db operator + + + def __init__(self): + self.init=True + self.sample=[] + + def initargs(self, args): + self.init=False + if len(args)<>1: + raise functions.OperatorError("rangef","Wrong number of arguments") + + def step(self, *args): + if not(isinstance(args[0], basestring)) and args[0]: + self.sample.append(float(args[0])) + + def final(self): + if (not self.sample): + return + self.range=max(self.sample) - min(self.sample) + return self.range + + +class amean: + """ + .. function:: amean(X) -> [amean float] + + Computes the arithmetic mean, i.e. the average, thus providing an alternative choise + to traditional *avg* offered by sqlite. + + Examples: + + >>> table1(''' + ... 1 + ... 2 + ... 2 + ... 3 + ... 'text is ignored, as well as null values' + ... 'none' + ... ''') + >>> sql("select amean(a) from table1") + amean(a) + -------- + 2.0 + +.. doctest:: + :hide: + + >>> sql("delete from table1") + >>> sql("select amean(a) from table1") + amean(a) + -------- + None + + """ + registered=True #Value to define db function + + def __init__(self): + self.init=True + self.counter=0 + self.sum=0.0 + self.sample=[] + + def initargs(self, args): + self.init=False + if not args: + raise functions.OperatorError("amean","No arguments") + elif len(args)>1: + raise functions.OperatorError("amean","Wrong number of arguments") + + def step(self, *args): + if self.init==True: + self.initargs(args) + + if not(isinstance(args[0], basestring)) and args[0]: + self.sample.append(float(args[0])) + self.sum += float(args[0]) + self.counter+=1 + + def final(self): + if (not self.sample): + return + return self.sum/self.counter + + +class wamean: + """ + .. function:: wamean(W,X) -> [wamean float] + + Computes the weighted arithmetic mean, i.e. the weighted average. + First column contains the weights and second column contains the actual data values. + + .. math:: + + wamean_{\mathrm} = \sum_{i=1}^{N} w_i x_i / \sum_{i=1}^{N} w_i + + + Examples: + + >>> table1(''' + ... 2 1 + ... 2 2 + ... 1 2 + ... 'text is ignored, as well as null values' 3 + ... 'none' 2 + ... 1 'text is ignored, as well as null values' + ... 2 'none' + ... 2 3 + ... ''') + >>> sql("select wamean(a,b) from table1") + wamean(a,b) + ----------- + 2.0 + +.. doctest:: + :hide: + + >>> sql("delete from table1") + >>> sql("select wamean(a) from table1") + wamean(a) + --------- + None + + """ + registered=True #Value to define db operator + + def __init__(self): + self.init=True + self.counter=0 + self.sum=0.0 + + def initargs(self, args): + self.init=False + if (len(args)<>2): + raise functions.OperatorError("wamean","Wrong number of arguments") + + def step(self, *args): + if self.init==True: + self.initargs(args) + + if not(isinstance(args[0], basestring)) and args[0] and not(isinstance(args[1], basestring)) and args[1]: + self.sum += args[0]*args[1] + self.counter+=args[0] + + def final(self): + if (self.counter==0): + return + return self.sum/self.counter + + +class gmean: + """ + .. function:: gmean(X,[m]) -> [gmean float] + + Computes the genaralized mean (also known as the power mean or Holder mean), + which is an abstraction of the *Pythagorean means* including *arithmetic*, *geometric*, and *harmonic* means. + + It is defined for a set of *n* positive real numbers as follows: + + .. math:: + + gmean_{\mathrm} = \Big ( {1 \over N} \sum_{i=1}^{N} x_i ^p \Big ) ^{1/p} + + + + The (optional) second argument stands for the *p* paramteter, thus determining the exact mean type: + + - p=2 : *Quadratic mean* (computed for both negative and positive values) + + - p=1 : *Artihmetic mean* + + - p=0 : *Geometric mean* (only for positive real numbers) + + - p=-1: *Harmonian mean* (only for positive real numbers) + + By default, i.e. in absence of second argument, p is set to 0, computing + the geometric mean. + + Examples: + + >>> table1(''' + ... 6 + ... 50 + ... 9 + ... 1200 + ... 'text is ignored, as well as None values' + ... 'None' + ... ''') + >>> sql("select gmean(a) from table1") + gmean(a) + ------------- + 42.4264068712 + + >>> table2(''' + ... 34 + ... 27 + ... 45 + ... 55 + ... 22 + ... 34 + ... ''') + >>> sql("select gmean(a,1) from table2") + gmean(a,1) + ------------- + 36.1666666667 + >>> sql("select gmean(a,0) from table2") + gmean(a,0) + ------------- + 34.5451100372 + >>> sql("select gmean(a) from table2") + gmean(a) + ------------- + 34.5451100372 + >>> sql("select gmean(a,-1) from table2") + gmean(a,-1) + ------------- + 33.0179836512 + >>> sql("select gmean(a,2) from table2") + gmean(a,2) + ------------- + 37.8043207407 + + + + """ + registered=True #Value to define db operator + + def __init__(self): + self.init=True + self.counter=0 + self.sum=0.0 + self.p=0.0 + self.result=0.0 + + def initargs(self, args): + self.init=False + + if not args: + raise functions.OperatorError("gmean","No arguments") + elif len(args)>2: + raise functions.OperatorError("gmean","Wrong number of arguments") + elif len(args)==2: + self.p=args[1] + if self.p>2 or self.p<-1: + raise functions.OperatorError("\n gmean","Second argument takes values from -1 to 2\n"+ + "p=2 :quadratic mean (for both negative and positive values)\n"+ + "p=1 :artihmetic mean\n"+ + "p=0 :geometric mean (for positive real numbers)\n"+ + "p=-1:harmonian mean (for positive real numbers)\n") + + def step(self, *args): + if self.init==True: + self.initargs(args) + if not(isinstance(args[0], basestring)) and args[0]: + if self.p<1 and args[0]<1: + raise functions.OperatorError("gmean","The specified type of mean applies only to positive numbers") + # The easiest way to think of the geometric mean is that + #it is the average of the logarithmic values, converted back to a base 10 number. + if self.p==0: + self.sum += math.log10(args[0]) + else: + self.sum += args[0]**self.p + self.counter +=1 + + def final(self): + if (self.counter==0): + return + if self.p==0: + result = 10**(self.sum/self.counter) + return result + else: + return (self.sum/self.counter)**(1.0/self.p) + +re_now=re.compile('now:(?P.*)') + + +class frecency: + """ + .. function:: frecency(actiondate[,points[,now:date]]) + + Returns a float weighted sum assigning to each action *points* or less, depending on the *actiondate* distance to the current date (or *now:date*). + In detail the action points decrease 30% at distance 10-30 days, 50% at 1-3 months, 70% at 3-6 months and 90% at greater distance. Date parameters should be in ISO8601 format. + + .. _iso8601: + + **ISO 8601 format** : + + Year: + YYYY (eg 1997) + Year and month: + YYYY-MM (eg 1997-07) + Complete date: + YYYY-MM-DD (eg 1997-07-16) + Complete date plus hours and minutes: + YYYY-MM-DD hh:mmTZD (eg 1997-07-16 19:20+01:00) + Complete date plus hours, minutes and seconds: + YYYY-MM-DD hh:mm:ssTZD (eg 1997-07-16 19:20:30+01:00) + Complete date plus hours and minutes: + YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00) + Complete date plus hours, minutes and seconds: + YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) + + Examples: + + >>> table1(''' + ... 2009-06-01 1 + ... 2009-08-28 2 + ... 2009-09-17 3 + ... ''') + >>> sql("select frecency(a,'now:2009-09-26 04:38:30') from table1") + frecency(a,'now:2009-09-26 04:38:30') + ------------------------------------- + 200.0 + + + """ + + registered=True #Value to define db operator + + def __init__(self): + self.frecency=0 + self.initstatic=False + self.points=None + self.now=None + + def __decrease(self,offsettimedelta): + if offsettimedelta<=datetime.timedelta(days=10): + return 1.0 + if offsettimedelta<=datetime.timedelta(days=30): + return 0.7 + if offsettimedelta<=datetime.timedelta(days=(30*3)): + return 0.5 + if offsettimedelta<=datetime.timedelta(days=(30*6)): + return 0.3 + return 0.1 + + def step(self, *args): + if not args: + raise functions.OperatorError("frecency","No arguments") + # last 2 arguments are static , so they are parse only the first time + if not self.initstatic: + self.initstatic=True + self.points=100.0 + self.now=datetime.datetime.now() + if len(args)>=2: + for arg in args[1:]: + isnowarg=re_now.match(arg) + if isnowarg: + nowdate=isnowarg.groupdict()['now'] + self.now=iso8601.parse_date(nowdate) + else: + self.points=int(arg) + + input=args[0] + dt=iso8601.parse_date(input) + self.frecency+=self.__decrease(self.now-dt)*self.points + + def final(self): + return self.frecency + + +class pearson: + + """ + .. function:: pearson(X,Y) -> float + + Computes the pearson coefficient of X and Y datasets + + Examples: + + >>> sql("select pearson(c1,1/c1) from range(1,91)") + pearson(c1,1/c1) + ---------------- + -0.181568259801 + + >>> sql("select pearson(c1,17*c1+5) from range(1,91)") + pearson(c1,17*c1+5) + ------------------- + 1.0 + + >>> sql("select pearson(c1,pyfun('math.pow',2,c1)) from range(1,41)") + pearson(c1,pyfun('math.pow',2,c1)) + ---------------------------------- + 0.456349821382 + + >>> sql("select pearson(a,b) from (select 1 as a, 2 as b)") + pearson(a,b) + ------------ + 0 + """ + + registered=True #Value to define db operator + sum_x=0 + sum_y=0 + + def __init__(self): + self.sX=Fraction(0) + self.sX2=Fraction(0) + self.sY=Fraction(0) + self.sY2=Fraction(0) + self.sXY=Fraction(0) + self.n=0 + + def step(self,*args): + try: + x, y = [Fraction(i) for i in args[:2]] + except KeyboardInterrupt: + raise + except: + return + self.n+=1 + self.sX+=x + self.sY+=y + self.sX2+=x*x + self.sY2+=y*y + self.sXY+=x*y + + def final(self): + if self.n==0: + return None + + d = (math.sqrt(self.n*self.sX2-self.sX*self.sX)*math.sqrt(self.n*self.sY2-self.sY*self.sY)) + + if d == 0: + return 0 + + return float((self.n*self.sXY-self.sX*self.sY)/d) + + +class fsum: + """ + .. function:: fsum(X) -> json + + Computes the sum using fractional computation. It return the result in json format + + Examples: + + >>> table1(''' + ... 1 + ... 2 + ... 2 + ... 10 + ... ''') + + >>> sql("select fsum(a) from table1") + fsum(a) + ------- + [15, 1] + + >>> table1(''' + ... 0.99999999 + ... 3.99999999 + ... 0.78978989 + ... 1.99999999 + ... ''') + + >>> sql("select fsum(a) from table1") + fsum(a) + ------------------------------------- + [70164189421580937, 9007199254740992] + """ + + registered = True + + def __init__(self): + self.init = True + self.x = Fraction(0.0) + + def step(self, *args): + if self.init: + self.init = False + if not args: + raise functions.OperatorError("fsum","No arguments") + + try: + if type(args[0]) in (int, float, long): + x = Fraction(args[0]) + else: + try: + json_object = json.loads(args[0]) + x = Fraction(json_object[0], json_object[1]) + except ValueError, e: + return + except KeyboardInterrupt: + raise + except: + return + + self.x += x + + def final(self): + return json.dumps([self.x.numerator, self.x.denominator]) + + + + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/subgroup.py b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/subgroup.py new file mode 100644 index 0000000..5510fca --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/subgroup.py @@ -0,0 +1,667 @@ +import setpath +import Queue +import functions +from lib import iso8601 +from operator import itemgetter +from lib import jopts +from lib.unicodeops import unistr + +__docformat__ = 'reStructuredText en' + + +def timedelta2millisec(tdelta): + return tdelta.days*24*60*60*1000+tdelta.seconds*1000+tdelta.microseconds + +class groupsum: + """ + .. function:: groupsum(n,col1,col2,col3,....) + + It groups by the first n columns of the input, and sums/jsets the rest. + + :Returned schema: + Columns are automatically named as col1, col2 ... + + Examples: + + >>> table1(''' + ... aa t1 43 + ... ac t2 34 + ... aa t3 12 + ... ab t4 21 + ... ac t5 14 + ... as t6 23 + ... ''') + >>> sql("select groupsum(1,a,b,c) from table1") + c1 | c2 | c3 + --------------------- + ac | ["t2","t5"] | 48 + aa | ["t1","t3"] | 55 + ab | t4 | 21 + as | t6 | 23 + + """ + registered=True + + def __init__(self): + self.notchecked = True + self.groupsdict = {} + self.grouplen = 0 + self.numofargs = 0 + def step(self, *args): + if self.notchecked: + if len(args)<2: + raise functions.OperatorError("groupsum","Wrong number of arguments") + self.grouplen = args[0] + self.numofargs = len(args) + self.notchecked = False + + groupkey = args[1:self.grouplen+1] + try: + group = self.groupsdict[groupkey] + j = 0 + for i in xrange(self.grouplen+1,self.numofargs): + group[j].append(args[i]) + j += 1 + except KeyError: + self.groupsdict[groupkey] = [[x] for x in args[self.grouplen+1:]] + + def final(self): + yield tuple('c'+str(i) for i in xrange(1,self.numofargs)) + for groupkey, sumcols in self.groupsdict.iteritems(): + cols = list(groupkey) + for col in sumcols: + try: + cols.append(sum(col)) + except TypeError: + cols.append(jopts.toj(sorted(set( jopts.fromj(*col) )))) + yield cols + + +class groupmax: + """ + .. function:: groupmax(n,col1,col2,col3,....) + + It groups by the first n columns of the input, and returns the maximum value of the rest. + + :Returned schema: + Columns are automatically named as col1, col2 ... + + Examples: + + >>> table1(''' + ... aa t1 43 + ... ac t2 34 + ... aa t3 12 + ... ab t4 21 + ... ac t5 14 + ... as t6 23 + ... ''') + >>> sql("select groupmax(1,a,b,c) from table1") + c1 | c2 | c3 + ------------ + ac | t5 | 34 + aa | t3 | 43 + ab | t4 | 21 + as | t6 | 23 + + """ + registered=True + + def __init__(self): + self.notchecked = True + self.groupsdict = {} + self.grouplen = 0 + self.numofargs = 0 + def step(self, *args): + if self.notchecked: + if len(args)<2: + raise functions.OperatorError("groupmax","Wrong number of arguments") + self.grouplen = args[0] + self.numofargs = len(args) + self.notchecked = False + + groupkey = args[1:self.grouplen+1] + try: + group = self.groupsdict[groupkey] + j = 0 + for i in xrange(self.grouplen+1,self.numofargs): + group[j].append(args[i]) + j += 1 + except KeyError: + self.groupsdict[groupkey] = [[x] for x in args[self.grouplen+1:]] + + def final(self): + yield tuple('c'+str(i) for i in xrange(1,self.numofargs)) + for groupkey, sumcols in self.groupsdict.iteritems(): + cols = list(groupkey) + for col in sumcols: + cols.append(max(col)) + + yield cols + + + +class condbreak: + """ + + .. function:: condbreak(groupid, C1, C2 ,...., condition, orderby) -> [bgroupid,C1,C2....] + + Returns an expanded *groupid* and the *value1...valueN*, perfoming new groupings when condition is true. Rows grouped together + are the ones that order by *orderby* column have no intermediate true values for *condition*. + + :Returned multiset schema: + - *bgroupid* + *groupid* appended with an integer value indicating the subgroup of the row. + - *C1, C2 ..* + The input values of the row. + + .. seealso:: + + * :ref:`tutmultiset` functions + + >>> table1(''' + ... 1 user1 open + ... 2 user1 read + ... 3 user1 close + ... 4 user1 open + ... 5 user1 write + ... 6 user1 close + ... 7 user2 open + ... 8 user2 write + ... ''') + >>> sql("select condbreak(b,c,c='open',a) from table1 group by b") + bgroupid | C1 + ---------------- + user11 | open + user11 | read + user11 | close + user12 | open + user12 | write + user12 | close + user21 | open + user21 | write + >>> sql("select condbreak(b,c,c='open',a) from (select 4 as a, 6 as b, 9 as c where c!=9)") + + """ + registered=True + multiset=True + + + def __init__(self): + self.vals=[] + + def step(self, *args): + if not args: + raise functions.OperatorError("condbreak","No arguments") + if len(args)<4: + raise functions.OperatorError("condbreak","Wrong number of arguments") + self.vals.append(list(args)) + + + + def final(self): + self.vals.sort(key=lambda x:x[-1]) + if self.vals==[]: + size=0 + else: + size=len(self.vals[0])-2 + + if size<=0: + yield ("bgroupid","C1") + else: + yield tuple(["bgroupid"]+["C"+str(i+1) for i in xrange(size-1)]) + + counter=0 + for el in self.vals: + if el[-2]==True: + counter+=1 + bid=unistr(el[0])+str(counter) + yield [bid]+el[1:-2] + + +class datediffbreak: + """ + + .. function:: datediffbreak(groupid, C1, C2 ,...., date, maxdiff[,'order',orderbycol1,orderbycol2,...]) -> [bgroupid,C1,C2....] + + Returns an expanded *groupid* and the *value1...valueN*, perfoming new groupings when subsequent rows *date* values differ more than *maxdiff* milliseconds. Rows grouped together + are the ones that order by *orderby* column or if ommited by the given order have less *date* distance than *maxdiff*. Input dates should be in :ref:`ISO 8601 format `. + + :Returned multiset schema: + - *bgroupid* + *groupid* appended with an integer value indicating the subgroup of the row. + - *C1, C2 ..* + The input values of the row. + + .. seealso:: + + * :ref:`tutmultiset` functions + + >>> table1(''' + ... 1 session1 '2007-01-01 00:03:13' + ... 2 session1 '2007-01-01 00:03:27' + ... 3 session1 '2007-01-01 00:03:36' + ... 4 session2 '2007-01-01 00:04:39' + ... 5 session2 '2007-01-01 00:04:40' + ... 6 session3 '2007-01-01 00:04:49' + ... 7 session3 '2007-01-01 00:04:59' + ... ''') + >>> sql("select datediffbreak(b,a,c,10*1000,'order',c,a) from table1 group by b") + bgroupid | C1 + -------------- + session10 | 1 + session11 | 2 + session11 | 3 + session20 | 4 + session20 | 5 + session30 | 6 + session30 | 7 + + +.. doctest:: + :hide: + + >>> sql("select datediffbreak(b,c,c='open',a) from (select 4 as a, 6 as b, 9 as c where c!=9)") + bgroupid | C1 + --------------- + None | None + >>> sql("select datediffbreak(b,a,c,10*1000,a,c) from table1 group by b") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator DATEDIFFBREAK: Wrong date format: 1 + """ + registered=True + + def __init__(self): + self.vals=[] + self.init=True + self.position=None + self.comparesize=0 + self.fullsize=0 + + def initargs(self, args): + self.init=False + if not args: + raise functions.OperatorError("datediffbreak","No arguments") + if len(args)<4: + raise functions.OperatorError("datediffbreak","Wrong number of arguments") + self.maxdiff=args[-1] + for i in xrange(len(args)): + if args[i]=='order': + self.position=i + self.maxdiff=args[i-1] + self.comparesize=len(args)-(i+1) + if len(args)<5: + raise functions.OperatorError("datediffbreak","Wrong number of arguments") + break + + def step(self, *args): + if self.init: + self.initargs(args) + + if not self.position: + self.vals.append(list(args[:-1])) + else: + self.vals.append(list(args[:self.position-1]+args[self.position+1:])) + + + def final(self): + if self.position: + self.vals.sort(key=lambda x:tuple(x[-self.comparesize:])) + if self.vals==[]: + size=0 + else: + size=len(self.vals[0])-self.comparesize-1 + + if size<=0: + yield ("bgroupid","C1") + yield [None, None] + return + + yield tuple(["bgroupid"]+["C"+str(i) for i in xrange(1,size)]) + + counter=0 + dt=None + dtpos=self.comparesize+1 + for el in self.vals: + try: + dtnew=iso8601.parse_date(el[-dtpos]) + except Exception: + raise functions.OperatorError("datediffbreak","Wrong date format: %s" %(el[-dtpos])) + if dt and timedelta2millisec(dtnew-dt)>self.maxdiff: + counter+=1 + dt=dtnew + bid=unistr(el[0])+str(counter) + yield [bid]+el[1:-dtpos] + +class datediffnewsesid: + """ + + .. function:: datediffnewsesid(maxdiff, date, groupid, C1, C2 ,....) -> [bgroupid, C1, C2, ...] + + Returns only the C1, C2, ... that should be updated with bgroupid, so as for the input groups to be effectively broken on maxdiff times. + Input dates should be in :ref:`ISO 8601 format `. + + :Returned multiset schema: + - *bgroupid* + *groupid* appended with an integer value indicating the subgroup of the row. + - *C1, C2 ..* + The input values of the row. + + >>> table1(''' + ... 1 session1 '2007-01-01 00:03:13' + ... 2 session1 '2007-01-01 00:03:27' + ... 3 session1 '2007-01-01 00:03:36' + ... 4 session2 '2007-01-01 00:04:39' + ... 5 session2 '2007-01-01 00:05:40' + ... 6 session3 '2007-01-01 00:04:49' + ... 7 session3 '2007-01-01 00:06:59' + ... 8 session3 '2007-01-01 00:06:59' + ... 9 session4 '2007-01-01 00:04:59' + ... ''') + >>> sql("select datediffnewsesid(10, c, b, a) from table1 group by b") + bgroupid | C1 + -------------- + session11 | 2 + session11 | 3 + session21 | 5 + session31 | 7 + session31 | 8 + +.. doctest:: + :hide: + + >>> sql("select datediffnewsesid(10, c, b, a) from (select 4 as a, 6 as b, 9 as c where c!=9)") + bgroupid | C1 + --------------- + None | None + + >>> table2(''' + ... 1 session1 '2007-05-01T21:10:51Z' + ... 9 session1 '2012-01-08T18:24:32Z' + ... ''') + >>> sql("select datediffnewsesid(1800, c, b, a) from table2 group by b") + bgroupid | C1 + -------------- + session11 | 9 + """ + + registered=True + + def __init__(self): + self.vals=[] + self.init=True + self.maxdiff=0 + + def initargs(self, args): + self.init=False + if not args: + raise functions.OperatorError("datediffnewsesid","No arguments") + if len(args)<4: + raise functions.OperatorError("datediffnewsesid","Wrong number of arguments") + self.maxdiff=args[0] + + def step(self, *args): + if self.init: + self.initargs(args) + + self.vals.append(list(args[1:])) + + def final(self): + lenofvals=len(self.vals) + if lenofvals<=0: + yield ("bgroupid", "C1") + yield [None, None, None] + return + + yield tuple(["bgroupid"]+["C"+str(i) for i in xrange(1,len(self.vals[0])-1)]) + + counter=0 + if lenofvals!=1: + for el in self.vals: + try: + el.insert(0,iso8601.parse_date(el[0])) + except Exception: + raise functions.OperatorError("datediffnewsesid","Wrong date format: %s" %(el[0])) + self.vals.sort(key=itemgetter(0)) + dt=self.vals[0][0] + for el in self.vals[1:]: + dtnew=el[0] + diff=dtnew-dt + dt=dtnew + if (diff.days*86400+diff.seconds)>self.maxdiff: + counter+=1 + if counter!=0: + bid=unistr(el[2])+str(counter) + yield [bid]+el[3:] + +class datedifffilter: + """ + + .. function:: datedifffilter(maxdiff, date, C1, C2 ....) -> [date,C1,C2....] + + Returns only a subset of the provided entries, performing a sort of entry clustering based on the entries date difference. Each cluster is + represented by the latest entry. + The first argument defines the time differnece threshold that is employed for entry clustering, and it is provided in seconds. + The second argument is assumed to contain the date column. Entries are assumed to be provided in an ascending order by the date column. + Input dates should be in :ref:`ISO 8601 format `. + All subsequent columns remain unchanged. + + + :Returned multiset schema: + - *date, C1, C2 ..* + The selected input values of the row. + + .. seealso:: + + * :ref:`tutmultiset` functions + + >>> table1(''' + ... 2010-01-01T01:32:03Z value1 + ... 2010-01-01T01:32:04Z value2 + ... 2010-01-01T01:32:06Z value3 + ... 2010-01-01T01:32:08Z value4 + ... 2010-01-01T01:32:29Z value5 + ... 2010-01-01T02:35:03Z value6 + ... 2010-01-01T02:35:04Z value7 + ... 2010-01-01T03:55:04Z value8 + ... ''') + >>> sql("select datedifffilter(20, a,b) from table1") + date | C1 + ----------------------------- + 2010-01-01T01:32:08Z | value4 + 2010-01-01T01:32:29Z | value5 + 2010-01-01T02:35:04Z | value7 + 2010-01-01T03:55:04Z | value8 + + >>> table1(''' + ... 2010-01-01T01:32:03Z value1 + ... ''') + >>> sql("select datedifffilter(20, a,b) from table1") + date | C1 + ----------------------------- + 2010-01-01T01:32:03Z | value1 + + >>> table1(''' + ... '2010-01-01 01:32:03' value1 + ... '2010-01-01 01:32:04' value2 + ... '2010-01-01 01:32:06' value3 + ... '2010-01-01 01:32:08' value4 + ... '2010-01-01 01:32:29' value5 + ... '2010-01-01 02:35:03' value6 + ... '2010-01-01 02:35:04' value7 + ... '2010-01-01 03:55:04' value8 + ... ''') + >>> sql("select datedifffilter(30, a,b) from table1") + date | C1 + ---------------------------- + 2010-01-01 01:32:29 | value5 + 2010-01-01 02:35:04 | value7 + 2010-01-01 03:55:04 | value8 + + """ + registered=True + + def __init__(self): + self.init=True + self.vals=[] + self.maxdiff=0 + + def initargs(self, args): + self.init=False + if not args: + raise functions.OperatorError("datedifffilter","No arguments") + if len(args)<2: + raise functions.OperatorError("datedifffilter","Wrong number of arguments") + self.maxdiff=args[0] + + def step(self, *args): + if self.init==True: + self.initargs(args) + + self.vals.append(list(args[1:])) + + def final(self): + lenofvals=len(self.vals) + if lenofvals==0: + yield ("date","C1") + yield [None,None] + return + + yield tuple(["date"]+["C"+str(i) for i in xrange(1, len(self.vals[0]))]) + + dt=None + dtpos=0 + diff=0 + if lenofvals==1: + yield(self.vals[dtpos]) + else: + for el in self.vals: + el.append(iso8601.parse_date(el[0])) + self.vals.sort(key=itemgetter(-1)) + for el in self.vals: + if dtposself.maxdiff: + yield(el[0:-1]) + if dtpos==lenofvals-1: + yield(self.vals[dtpos][0:-1]) + +class datediffgroup: + """ + + .. function:: datediffgroup(maxdiff, date, C1, C2 ....) -> [groupid, date,C1,C2....] + + Performing a sort of entry clustering based on the entries date difference. + The cluster id that is assigned to each entry is returned in the first column, and it is followed by the entry's original contents. + + The first argument defines the time differnece threshold that is employed for entry clustering, and it is provided in seconds. + The second argument is assumed to contain the date column. Entries are assumed to be provided in an ascending order by the date column. + Input dates should be in :ref:`ISO 8601 format `. + All subsequent columns remain unchanged. + + + :Returned multiset schema: + - *date, C1, C2 ..* + The selected input values of the row. + + .. seealso:: + + * :ref:`tutmultiset` functions + + >>> table1(''' + ... 2010-01-01T01:32:03Z value1 + ... 2010-01-01T01:32:04Z value2 + ... 2010-01-01T01:32:06Z value3 + ... 2010-01-01T01:32:08Z value4 + ... 2010-01-01T01:32:29Z value5 + ... 2010-01-01T02:35:03Z value6 + ... 2010-01-01T02:35:04Z value7 + ... 2010-01-01T03:55:04Z value8 + ... ''') + >>> sql("select datediffgroup(20,a,b) from table1") + groupid | date | C1 + --------------------------------------- + 1 | 2010-01-01T01:32:03Z | value1 + 1 | 2010-01-01T01:32:04Z | value2 + 1 | 2010-01-01T01:32:06Z | value3 + 1 | 2010-01-01T01:32:08Z | value4 + 2 | 2010-01-01T01:32:29Z | value5 + 3 | 2010-01-01T02:35:03Z | value6 + 3 | 2010-01-01T02:35:04Z | value7 + 4 | 2010-01-01T03:55:04Z | value8 + """ + registered=True + multiset=True + + + def __init__(self): + self.init=True + self.vals=[] + self.maxdiff=0 + self.counter=0 + self.tablesize=0 + self.groupIdCounter=1 + + + def initargs(self, args): + self.init=False + if not args: + raise functions.OperatorError("datediffgroup","No arguments") + if len(args)<2: + raise functions.OperatorError("datediffgroup","Wrong number of arguments") + self.tablesize=len(args)-1 + self.maxdiff=args[0] + + + + def step(self, *args): + if self.init==True: + self.initargs(args) + + self.vals.append(list(args[1:])) + self.counter+=1 + + def final(self): + if self.tablesize<=0: + yield ("groupid","date","C1") + else: + yield tuple(["groupid"]+["date"]+["C"+str(i+1) for i in xrange(self.tablesize-1)]) + + dt=None + dtpos=0 + diff=0 + + for el in self.vals: + + if dtposself.maxdiff: + self.groupIdCounter+=1 + + dtpos+=1 + if dtpos==self.counter-1: + yield [str(self.groupIdCounter)]+self.vals[dtpos] + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/text.py b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/text.py new file mode 100644 index 0000000..2a5277d --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/text.py @@ -0,0 +1,118 @@ +__docformat__ = 'reStructuredText en' + + +class concatgroup: + """ + .. function:: concatgroup(X) + + Concatenates strings in a group/dataset X. + + Example: + + >>> table1(''' + ... word1 1 + ... word2 1 + ... word3 2 + ... word4 2 + ... ''') + >>> sql("select concatgroup(a) from table1 group by b") + concatgroup(a) + -------------- + word1word2 + word3word4 + """ + + registered=True #Value to define db operator + + def __init__(self): + self.whole_string=[] + + def step(self, *args): + self.whole_string.append(args[0]) + + def final(self): + return ''.join(self.whole_string) + + +class concatlines: + """ + .. function:: concatlines(X) + + Concatenates strings in a group/dataset X. + + Example: + + >>> table1(''' + ... word1 + ... word2 + ... word3 + ... word4 + ... ''') + >>> sql("select concatlines(a) from table1") + concatlines(a) + ----------------------- + word1 + word2 + word3 + word4 + """ + + registered=True #Value to define db operator + + def __init__(self): + self.whole_string=[] + + def step(self, *args): + self.whole_string.append(args[0]) + + def final(self): + return '\n'.join(self.whole_string) + + +class concatterms: + """ + .. function:: concatterms(text1, text2,...) + + Concatenates strings in a group/dataset X, while keeping them disjoint, i.e. using the single space delimiter. + + Examples: + + >>> table1(''' + ... word1 1 + ... word2 1 + ... word3 2 + ... word4 2 + ... ''') + >>> sql("select concatterms(a) from table1 group by b") + concatterms(a) + -------------- + word1 word2 + word3 word4 + """ + + registered=True #Value to define db operator + + def __init__(self): + self.whole_string=[] + + def step(self, *args): + if len(args[0])!=0: + self.whole_string.append(args[0]) + + def final(self): + return ' '.join(self.whole_string) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/util.py b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/util.py new file mode 100644 index 0000000..e62afce --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/aggregate/util.py @@ -0,0 +1,130 @@ +__docformat__ = 'reStructuredText en' + +class expandgroups: + """ + .. function:: expandgroups(args) -> args + + Expands the contents of groups. Usefull for debugging group related queries. + + Examples: + + Directed graph: + + >>> table1(''' + ... 1 2 + ... 2 3 + ... 1 4 + ... 2 5 + ... 3 3 + ... ''') + + >>> sql("select expandgroups(a,b) from table1") + C1 | C2 + ------- + 1 | 2 + 2 | 3 + 1 | 4 + 2 | 5 + 3 | 3 + + >>> sql("select expandgroups(a,b) as gr from table1") + gr1 | gr2 + --------- + 1 | 2 + 2 | 3 + 1 | 4 + 2 | 5 + 3 | 3 + + >>> sql("select a,expandgroups(b) as gr from table1 group by a") + a | gr + ------ + 1 | 2 + 1 | 4 + 2 | 3 + 2 | 5 + 3 | 3 + + """ + + registered=True + + def __init__(self): + self.rows=[] + + def step(self, *args): + self.rows.append(args) + + def final(self): + yield tuple(('C'+str(x) for x in xrange(1,len(self.rows[0])+1))) + for r in self.rows: + yield r + +class showgroups: + """ + .. function:: showgroups(args) -> string + + Shows the contents of groups. Usefull for debugging group related queries. + + Examples: + + Directed graph: + + >>> table1(''' + ... 1 2 + ... 2 3 + ... 1 4 + ... 2 5 + ... 3 3 + ... ''') + + >>> sql("select showgroups(a,b) from table1") # doctest: +NORMALIZE_WHITESPACE + showgroups(a,b) + -------------------- + + 1 2 + 2 3 + 1 4 + 2 5 + 3 3 + + + >>> sql("select showgroups(b) as gr from table1 group by a") + gr + ---- + + 2 + 4 + + 3 + 5 + + 3 + + """ + + registered=True + + def __init__(self): + self.rows=[] + + def step(self, *args): + self.rows.append(args) + + def final(self): + return '\n'+'\n'.join(['\t'.join([unicode(x) for x in r]) for r in self.rows]) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/conf.py b/interactive-mining-3rdparty-madis/madis/src/functions/conf.py new file mode 100644 index 0000000..7c73ae6 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/conf.py @@ -0,0 +1,7 @@ +# setting for functions + +# To add headers for specific domain for file function +# add values at domainExtraHeaders dictionary +# e.g. domainExtraHeaders={'www.domain.gr':{'header':'value'}} + +domainExtraHeaders={"Accept-Encoding": "gzip"} \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/__init__.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/__init__.py new file mode 100755 index 0000000..2eb2788 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/__init__.py @@ -0,0 +1,3 @@ +""" + +""" \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/boolean.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/boolean.py new file mode 100644 index 0000000..cfca0ec --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/boolean.py @@ -0,0 +1,55 @@ +# coding: utf-8 + +import setpath +import functions + +def ifthenelse(*args): + """ + .. function:: ifthenelse(condition, x, y) + + Returns *x* if *condition* is true, else returns *y*. + + .. templateforparams Parameters: + :condition: exception type + :x: exception value + :y: traceback object + :returns: true or false + + .. note:: + + The difference with the *if* construct in most programming languages + is that *x* and *y* expressions will always be evaluated. + + Examples: + + >>> sql("select ifthenelse(1>0,'yes','no') as answer") + answer + ------ + yes + """ + if len(args)<2: + raise functions.OperatorError("ifthenelse","operator needs at least two inputs") + + if args[0]: + return args[1] + else: + if len(args)>2: + return args[2] + return None + +ifthenelse.registered=True + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/date.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/date.py new file mode 100644 index 0000000..7067d13 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/date.py @@ -0,0 +1,239 @@ +# coding: utf-8 +import functions +import datetime +from lib import iso8601 +from lib.dateutil import parser + +def cleantimezone(*args): + + """ + .. function:: cleantimezone(date) -> date + + Specialized function that removes timezone information from date string + + Examples: + + >>> table1(''' + ... '2009-01-01T01:03:13+0100' + ... '2009-01-01T01:03:13-0100' + ... '2009-01-01T01:03:13+01:00' + ... '2009-01-01T01:03:13-01:00' + ... '2009-01-01T01:03:13+01' + ... '2009-01-01T01:03:13-01' + ... ''') + >>> sql("select cleantimezone(a) from table1") + cleantimezone(a) + ------------------- + 2009-01-01 01:03:13 + 2009-01-01 01:03:13 + 2009-01-01 01:03:13 + 2009-01-01 01:03:13 + 2009-01-01 01:03:13 + 2009-01-01 01:03:13 + """ + + d = args[0].replace('T',' ') + tindex = d.find('+') + mindex = d.rfind('-') + if tindex<>-1: + return d[0:tindex] + elif mindex <>-1 and mindex>13: + return d[0:mindex] + else: + return d; + +cleantimezone.registered=True + + +def activityindex(*args): + + """ + .. function:: activityIndex(date, c1, c2) -> int + + Specialized function that classifies the provided date argument into a 6-point scale (0 to 5) + + Examples: + + >>> table1(''' + ... '2009-01-01T01:32:03Z' + ... '2010-01-01T00:03:13Z' + ... '2010-12-31T00:03:13Z' + ... '2011-04-01T00:03:13Z' + ... ''') + >>> sql("select activityIndex(a) from table1") + activityIndex(a) + ---------------- + 0 + 1 + 3 + 5 + """ + now = datetime.datetime.now() + now = iso8601.parse_date(now.strftime("%Y-%m-%d %H:%M:%S")) + d = args[0].replace('T',' ') + dt = iso8601.parse_date(args[0].replace('Z','')) + diff=now-dt + + if (diff.days)<30: + return 5 + elif (diff.days)<3*30: + return 4 + elif (diff.days)<6*30: + return 3 + elif (diff.days)<12*30: + return 2 + elif (diff.days)<24*30: + return 1 + elif (diff.days)>=24*30: + return 0 + else: + return -1; + +activityindex.registered=True + +def sectohuman(*args): + + """ + .. function:: sectohuman(sec) -> human readable format + + Converts a number of seconds to human readable format. + + Examples: + + >>> table1(''' + ... 3 + ... 63 + ... 10000 + ... 100000 + ... 1000000 + ... ''') + >>> sql("select sectohuman(a) from table1") + sectohuman(a) + ------------------------------ + 3 sec + 1 min 3 sec + 2 hours 46 min 40 sec + 1 day 3 hours 46 min 40 sec + 11 days 13 hours 46 min 40 sec + """ + + secs=int(args[0]) + h='' + days=secs/86400 + if days > 0: + h+=str(days)+' day' + if days > 1: + h+='s' + h+=' ' + secs=secs % 86400 + hours=secs/3600 + if hours > 0: + h+=str(hours)+' hour' + if hours > 1: + h+='s' + h+=' ' + secs=secs % 3600 + mins=secs/60 + if mins > 0: + h+=str(mins)+' min ' + secs=secs % 60 + if secs > 0: + h+=str(secs)+' sec' + + return h + +sectohuman.registered=True + +def datestrf2isoweek(*args): + + """ + .. function:: dateisoweek2week52(sec) -> isoweek + + Converts an ISOweek (having weeks in range [0,53]) to an ISOweek + format which has weeks in range [1,53]. This function is usefull for + producing week statistics which do not have incomplete weeks. + + Examples: + + >>> table1(''' + ... 2007-12-31 + ... 2010-01-01 + ... ''') + + >>> sql("select strftime('%YW%W',a) from table1") + strftime('%YW%W',a) + ------------------- + 2007W53 + 2010W00 + + >>> sql("select datestrf2isoweek(strftime('%YW%W',a)) from table1") + datestrf2isoweek(strftime('%YW%W',a)) + ------------------------------------- + 2007W53 + 2009W53 + """ + + year=int(args[0][0:4]) + week=args[0][-2:] + + if week=='00': + year-=1 + week='53' + + return str(year)+'W'+week + +datestrf2isoweek.registered=True + + +def date2iso(*args): + + """ + .. function:: date2iso(sec) -> ISO Datetime + + Converts an input date to ISO-8601 date format. It tries to autodetect, the + input date format. + + Examples: + + >>> table1(''' + ... 2007-12-31 + ... 2010-01-01 + ... 2010W06 + ... "18/Jan/2011:11:13:00 +0100" + ... ''') + + >>> sql("select date2iso(a) from table1") + date2iso(a) + ------------------------- + 2007-12-31T00:00:00+00:00 + 2010-01-01T00:00:00+00:00 + 2010-02-05T00:00:00+00:00 + 2011-01-18T11:13:00+01:00 + + """ + + date = args[0] + try: + date = iso8601.parse_date(date) + except iso8601.ParseError: + date = parser.parse(date, fuzzy=True) + + return date.isoformat() + +date2iso.registered=True + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/evals.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/evals.py new file mode 100644 index 0000000..8983188 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/evals.py @@ -0,0 +1,232 @@ +# coding: utf-8 + +import setpath +import functions +from string import Template + +class myTemplate(Template): + delimiter=r'%' + pattern = r""" + %(delim)s(?: + (?P%(delim)s) | # Escape sequence of two delimiters + (?P^) | # delimiter and a Python identifier + {(?P%(id)s)} | # delimiter and a braced identifier + (?P) # Other ill-formed delimiter exprs + ) + """%{'delim' : delimiter, 'id': Template.idpattern } + + +def query(*args): + return args[0] + ';' + +query.registered = True + + +def pyeval(*args): + + """ + .. function:: pyeval(expression) + + Evaluates with Python the expression/s given and returns the result + + >>> sql("pyeval '1+1'") + pyeval('1+1') + ------------- + 2 + >>> sql("select var('test')") # doctest: +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator VAR: Variable 'test' does not exist + >>> sql("select var('test', pyeval('1+1'))") + var('test', pyeval('1+1')) + -------------------------- + 2 + >>> sql("select var('test')") + var('test') + ----------- + 2 + >>> sql('''pyeval '1+1' '"-"' '3+1' ''') + pyeval('1+1','"-"','3+1') + ------------------------- + 2-4 + >>> sql("var 'testvar' of select 5") + var('testvar',(select 5)) + ------------------------- + 5 + >>> sql("pyeval 'testvar+5'") + pyeval('testvar+5') + ------------------- + 10 + >>> sql('''pyeval keywords('lala') ''') + pyeval('keywords(''lala'')') + ---------------------------- + lala + """ + + if len(args)==0: + return + + r='' + for i in args: + r=r+str(eval(i, functions.variables.__dict__, functions.rowfuncs.__dict__)) + + return r + +pyeval.registered=True + +def pyfun(*args): + """ + .. function:: pyfun(pyfunction, parameters) + + Calls a python function and returns the result. If an error occurs, it throws an + exception. + + >>> sql("select pyfun('math.sqrt', 25)") + pyfun('math.sqrt', 25) + ---------------------- + 5.0 + >>> sql("select pyfun('math.log10', 100)") + pyfun('math.log10', 100) + ------------------------ + 2.0 + >>> sql("select pyfun('math.log10', -1)") # doctest: +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator PYFUN: math.log10: math domain error + """ + + if len(args)==0: + return + + fsplit=args[0].split('.') + try: + f=__import__(fsplit[0]) + for i in fsplit[1:]: + f=f.__dict__[i] + except KeyboardInterrupt: + raise + except: + try: + f=__import__('libexternal'+'.'+fsplit[0]) + for i in fsplit: + f=f.__dict__[i] + except: + raise functions.OperatorError("pyfun","didn't find function: "+args[0]) + + try: + res=f(*args[1:]) + except Exception, e: + raise functions.OperatorError("pyfun",args[0]+": "+functions.mstr(e)) + + if res is None or type(res) in (int,float, str, unicode): + return res + else: + return repr(f(*args[1:])) + +pyfun.registered=True + +def pyfunerrtonul(*args): + """ + .. function:: pyfunerrtonul(pyfunction, parameters) + + Calls a python function and returns the result. If an error occurs it returns + *null*. + + >>> sql("select pyfunerrtonul('math.sqrt', -1)") + pyfunerrtonul('math.sqrt', -1) + ------------------------------ + None + >>> sql("select pyfunerrtonul('math.log10', -1)") + pyfunerrtonul('math.log10', -1) + ------------------------------- + None + """ + + if len(args)==0: + return + + fsplit=args[0].split('.') + try: + f=__import__(fsplit[0]) + for i in fsplit[1:]: + f=f.__dict__[i] + except: + try: + f=__import__('libexternal'+'.'+fsplit[0]) + for i in fsplit: + f=f.__dict__[i] + except: + raise functions.OperatorError("pyfunerrtonul","didn't find function: "+args[0]) + + try: + res=f(*args[1:]) + except Exception, e: + return None + + if res is None or type(res) in (int,float, str, unicode): + return res + else: + return repr(f(*args[1:])) + +pyfunerrtonul.registered=True + +def subst(*args): + """ + .. function:: subst(str, variables) + + Substitutes the special text markers with the variables values. + + >>> sql('''subst 'Variable %s has value %s' 'var1' '5' ''') + subst('Variable %s has value %s','var1','5') + -------------------------------------------- + Variable var1 has value 5 + + >>> sql('''select subst('Variable %s has value %d','var2',5) ''') + subst('Variable %s has value %d','var2',5) + ------------------------------------------ + Variable var2 has value 5 + + >>> sql('''var 'testvar' 'testvalue' ''') + var('testvar','testvalue') + -------------------------- + testvalue + + >>> sql('''select subst('Variable %{testvar}1 %{testvar1} has value %s', 5) ''') + subst('Variable testvalue1 %{testvar1} has value %s', 5) + -------------------------------------------------------- + Variable testvalue1 %{testvar1} has value %s + + """ + if len(args)==0: + return + + str=myTemplate(args[0]).safe_substitute(functions.variables.__dict__) + + if len(args)==1: + return str + + try: + str=str%args[1:] + except: + pass + + return str + +subst.registered=True + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/fileops.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/fileops.py new file mode 100644 index 0000000..4e35016 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/fileops.py @@ -0,0 +1,82 @@ +# coding: utf-8 +import os + +def fileextension(*args): + + """ + .. function:: fileextension(text) -> text + + Returns the extension of a given text argument. + + Examples: + + >>> table1(''' + ... "http://www.test.com/lalala.gif" + ... "http://www.test.com/lalala.GIF" + ... ''') + >>> sql("select fileextension(a) from table1") + fileextension(a) + ---------------- + .gif + .gif + + """ + + try: + ret=os.path.splitext(args[0]) + except ValueError: + return None + + return ret[1].lower() + +fileextension.registered = True + + +def filetext(*args): + """ + .. function:: filetext(filename) -> text + + Returns the contents of the file in a single value + + Examples: + + >>> sql("select filetext('testing/sales.tsv')") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + filetext('testing/sales.tsv') + ---------------------------------- + Cars 2010-01 Athens 200 + Cars 2010-02 Athens 130 + Bikes 2010-01 NY 10 + Bikes 2010-02 NY 30 + Cars 2010-01 NY 100 + Cars 2010-02 NY 160 + Cars 2010-01 Paris 70 + Cars 2010-02 Paris 20 + Bikes 2010-01 Paris 100 + Bikes 2010-02 Paris 20 + Boats 2010-01 Paris 200 + """ + + try: + with open(args[0], "rU") as f: + data = f.read() + except ValueError: + return None + return data + +filetext.registered = True + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/formating.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/formating.py new file mode 100644 index 0000000..2b1e602 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/formating.py @@ -0,0 +1,332 @@ +import setpath +import re +import datetime +import StringIO +from lib.dsv import writer, reader +from lib import argsparse +import functions +import lib.inoutparsing as csvargs + +def strsplit(*args): ###splits the first arguments + """ + + .. function:: strsplit(str[,formatting options]) -> [C1,C2,....] + + Splits *str* according to *formatting options*, default behavior is to split on space. + It is a multiset operator that returns one row. + + .. seealso:: + + * :ref:`tutmultiset` functions + + .. _formattingopts: + + Formatting options: + + :dialect: *tsv/csv* + + Formats field as tab/comma separated values with minimal quoting + + :delimiter: + + A string used to separate fields. It defaults to ' ' + + :doublequote: *t/f* + + Controls how instances of quotechar appearing inside a + field should be themselves be quoted. When True, the + character is doubled. When False, the escapechar is used as + a prefix to the quotechar. It defaults to True. + On output, if doublequote is False and no escapechar is set, + Error is raised if a quotechar is found in a field + + :escapechar: + + A one-character string used by the writer to escape the delimiter + if quoting is set to QUOTE_NONE and the quotechar if doublequote is False. + On reading, the escapechar removes any special meaning from the following + character. It defaults to None, which disables escaping. + + :quotechar: + + A one-character string used to quote fields containing special characters, + such as the delimiter or quotechar, or which contain new-line characters. + It defaults to '"'. + + :quoting: + + Controls when quotes should be generated by the writer and recognized by + the reader. It can take on any of the QUOTE_* constants and defaults to + QUOTE_MINIMAL. Possible values are QUOTE_ALL, QUOTE_NONE, QUOTE_MINIMAL, QUOTE_NONNUMERIC + + :skipinitialspace: *t/f* + + When True, whitespace immediately following the delimiter is ignored. The default is False + + :Returned multiset schema: + - *C1,C2...* + Text values produced from splitting. + + Examples: + + >>> sql("select strsplit('First,Second,Third', 'dialect:csv')") + C1 | C2 | C3 + ---------------------- + First | Second | Third + >>> sql("select strsplit('-First-%Second%-Third-','delimiter:%','quotechar:-')") + C1 | C2 | C3 + ---------------------- + First | Second | Third + +.. doctest:: + :hide: + + >>> sql("select strsplit('-First-%Second%-Third-','quotechar:-p')") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + MadisError: Madis SQLError: + "quotechar" must be an 1-character string + + """ + if len(args)<1: + raise functions.OperatorError("strsplit"," no input") + + arg=args[0] + args=args[1:] + try: + largs, kargs = argsparse.parse(args,csvargs.boolargs,csvargs.nonstringargs,csvargs.needsescape) + except Exception,e: + raise functions.MadisError(e) + if 'dialect' not in kargs: + kargs['dialect']=csvargs.defaultcsv() + if 'delimiter' not in kargs: + kargs['delimiter']=' ' + + if len(largs)>0: + raise functions.OperatorError("strsplit","strsplit operator: Unknown argument %s" %(''.join(largs))) + f=StringIO.StringIO() + + f.write(arg.encode('utf-8')) + f.seek(0) + try: + r=reader(f,**kargs) + except Exception,e: + raise functions.MadisError(e) + first=True + + for row in r: + if first: + first=False + yield tuple("C"+str(i) for i in xrange(1, len(row) + 1)) + yield row + if first: + first=False + yield ["C1"] + f.close() + + +strsplit.registered=True + +def strsplitv(*args): ###splits the first arguments + """ + .. function:: strsplitv(str[,formatting options]) -> [C1] + + Splits in rows *str* according to *formatting options*, default behavior is to split on space. + It is a multiset operator that returns one column but many rows. :ref:`Formatting options` are like in :func:`strsplit` function. + + .. seealso:: + + * :ref:`tutmultiset` functions + + + >>> sql("select strsplitv('First,Second,Third','dialect:csv')") + C1 + ------ + First + Second + Third + >>> sql("select strsplitv('First Second Third')") + C1 + ------ + First + Second + Third + """ + if len(args)<1: + raise functions.OperatorError("strsplitv","strsplit operator: no input") + + arg=args[0] + args=args[1:] + try: + largs, kargs = argsparse.parse(args,csvargs.boolargs,csvargs.nonstringargs,csvargs.needsescape) + except Exception,e: + raise functions.MadisError(e) + if 'dialect' not in kargs: + kargs['dialect']=csvargs.defaultcsv() + if 'delimiter' not in kargs: + kargs['delimiter']=' ' + + if len(largs)>0: + raise functions.OperatorError("strsplitv","strsplit operator: Unknown argument %s" %(''.join(largs))) + f=StringIO.StringIO() + + f.write(arg.encode('utf-8')) + f.seek(0) + + try: + r=reader(f,**kargs) + except Exception,e: + raise functions.MadisError(e) + first=True + + for row in r: + if first: + first=False + yield ("C1",) + for el in row: + yield [el] + if first: + first=False + yield ("C1",) + f.close() + +strsplitv.registered=True + +def strjoin(*args): + + """ + .. function:: strjoin(value1,value2,....[,'params',formatting options]) + + Returns a string with *value1,value2,....* formatted according to :ref:`formatting options`. + Literal parameter 'params' must precede *formating options*. Default formatting is comma separated values. + + Examples: + + >>> sql("select strjoin('First','Second','Third',100) as joinedvals") + joinedvals + ----------------------- + First,Second,Third,100 + >>> sql("select strjoin('First','Second','Third',100,'params','delimiter: ') as joinedvals") + joinedvals + ----------------------- + First Second Third 100 + >>> sql("select strjoin('lola',2,10,'llalallall','params','delimiter:%','quoting:QUOTE_ALL') as joinedvals") + joinedvals + ----------------------------- + "lola"%"2"%"10"%"llalallall" + >>> sql("select strjoin('value, with delimiter ',2,10,'new','params','dialect:csv') as joinedvals") + joinedvals + ---------------------------------- + "value, with delimiter ",2,10,new + """ + if None in args: + return None + sargs=[] + params=False + for i in xrange(len(args)): + if args[i]=='params': + args=args[(i+1):] + params=True + break + else: + sargs.append(args[i]) + try: + if params: + largs, kargs = argsparse.parse(args,csvargs.boolargs,csvargs.nonstringargs,csvargs.needsescape) + else: + largs=[] + kargs=dict() + except Exception,e: + raise functions.MadisError(e) + if len(largs)>0: + raise functions.OperatorError("strjoin","Unknown argument %s" %(''.join(largs))) + if 'dialect' not in kargs: + kargs['dialect']=csvargs.defaultcsv() + f=StringIO.StringIO() + try: + csvprinter=writer(f,**kargs) + except Exception,e: + raise functions.MadisError(e) + csvprinter.writerow(sargs) + f.seek(0) + s=f.read() + return s + + +strjoin.registered=True + + +def dateformat(*args): + + """ + .. function:: dateformat(date[,inpformat,outformat]) + + Returns *date* formatted with *outformat*. Default *inpformat* is %d-%m-%y and default + *outformat* is %Y-%m-%d. To change *inpformat* just provide as second parameter the input format. + To change *outformat*, both format parameters must be provided. If date is not formatted according + to *inpformat* null value is returned. + + Check `formatting pattern `_ details + + + Examples: + + >>> sql("select dateformat('28-01-09') as date") + date + ---------- + 2009-01-28 + + When date doesn't meet the format null is returned + + >>> sql("select dateformat('32-01-09') as date") + date + ---- + None + >>> sql("select dateformat('Thu, 28 Jun 2001 14:17:15 +0000','%a, %d %b %Y %H:%M:%S +0000') as date") + date + ---------- + 2001-06-28 + >>> sql("select dateformat('28-01-09','%d-%m-%y','%x') as date") + date + -------- + 01/28/09 + """ + fromf='%d-%m-%y' + tof='%Y-%m-%d' + if len(args)<1: + raise functions.OperatorError("dateformat","No input") + if None in args: + return None + if len(args)>1: + fromf=args[1] + if len(args)>2: + tof=args[2] + dt=args[0] + try: + dtobj=datetime.datetime.strptime(dt,fromf) + ret=datetime.datetime.strftime(dtobj,tof) + except ValueError,e: + return None + except Exception,e: + raise functions.OperatorError("dateformat",e) + return ret + + +dateformat.registered=True + + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/htmlops.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/htmlops.py new file mode 100644 index 0000000..2690176 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/htmlops.py @@ -0,0 +1,385 @@ +# coding: utf-8 +import urllib +import re +from htmlentitydefs import name2codepoint +import urlparse +import os +import mimetypes +import xml.sax.saxutils +import operator +import json + +def urlsplit(*args): + + """ + .. function:: urlsplit(text1, [text2,...]) -> multiset + + Breaks a given URL into multiple fields. The returned table schema is: + + :scheme: What type the URL is (e.g. http, ftp ...) + :netloc: Network location of URL (e.g. www.text.com) + :path: Path part of URL (e.g. /data/2010/). It always has a slash at the end + :filename: Filename part of URL + :type: Mime type of URL, or if not a mime type exists, the extension part of filename. + :subtype: Mime subtype of URL. + :params: All parameters following ';' in URL. + :query: All parameters following '?' in URL. + :fragment: All parameters following '#' in URL. + + Examples: + + >>> table1(''' + ... http://www.test.com/apath/bpath/fname.pdf + ... http://www.test.com/search.csv;p=5?q=test#hl=en + ... ''') + >>> sql("select urlsplit(a) from table1") + scheme | netloc | path | filename | type | subtype | params | query | fragment + ------------------------------------------------------------------------------------------------------- + http | www.test.com | /apath/bpath/ | fname.pdf | application | pdf | | | + http | www.test.com | / | search.csv | csv | | p=5 | q=test | hl=en + """ + + yield ('scheme', 'netloc', 'path', 'filename', 'type', 'subtype', 'params', 'query', 'fragment') + + url=''.join(args) + u=urlparse.urlparse(''.join(args)) + pf=os.path.split(u[2]) + + if len(pf)==2: + path, filename=pf + else: + path, filename=pf[0], '' + + if len(path)>0 and path[-1]!='/': + path+='/' + + m=mimetypes.guess_type(url) + if m[0]!=None: + m1, m2=m[0].split('/') + else: + m1, m2=(os.path.splitext(filename)[1], '') + if len(m1)>0 and m1[0]=='.': + m1=m1[1:] + + yield [u[0], u[1], path, filename, m1, m2, u[3], u[4], u[5]] + +urlsplit.registered=True +urlsplit.multiset=True + +def urllocation(*args): + + """ + .. function:: urllocation(str) -> str + + Returns the location part of provided URL. + + Examples: + + >>> table1(''' + ... http://www.test.com/apath/bpath/fname.pdf + ... http://www.test.com/search.csv;p=5?q=test#hl=en + ... ''') + >>> sql("select urllocation(a) from table1") + urllocation(a) + ----------------------------------------- + http://www.test.com/apath/bpath/fname.pdf + http://www.test.com/search.csv + """ + + u=urlparse.urlparse(''.join(args)) + + return u[0]+u'://'+''.join(u[1:3]) + +urllocation.registered=True + +def urlquery2jdict(*args): + """ + .. function:: urlquery2jdict(URL or URL_query_part) -> JDICT + + Converts the query part of a URL into a JSON associative array. + + Examples: + + >>> table1(''' + ... 'url_ver=ver1&url_tim=2011-01-01T00%3A02%3A40Z' + ... 'url_tim=2011-01-01T00%3A02%3A40Z&url_ver=ver1' + ... http://www.test.com/search.csv;p=5?lang=test&ver=en + ... ''') + >>> sql("select urlquery2jdict(a) from table1") + urlquery2jdict(a) + --------------------------------------------------- + {"url_tim":"2011-01-01T00:02:40Z","url_ver":"ver1"} + {"url_tim":"2011-01-01T00:02:40Z","url_ver":"ver1"} + {"lang":"test","ver":"en"} + """ + + url=args[0] + if url.startswith('http://') or url[0:1]=='/': + url=urlparse.urlparse(url)[4] + u=urlparse.parse_qs(url, True) + + for x,y in u.iteritems(): + if len(y)==1: + u[x]=y[0] + + return json.dumps(u, separators=(',',':'), ensure_ascii=False) + +urlquery2jdict.registered=True + +EntityPattern = re.compile('&(?:#(\d+)|(?:#x([\da-fA-F]+))|([a-zA-Z]+));') +def htmlunescape(s): + def unescape(match): + code = match.group(1) + if code: + return unichr(int(code, 10)) + else: + code = match.group(2) + if code: + return unichr(int(code, 16)) + else: + code = match.group(3) + if code in name2codepoint: + return unichr(name2codepoint[code]) + return match.group(0) + + return EntityPattern.sub(unescape, s) + +def htmldecode(*args): + """ + .. function:: htmldecode(str) + + Returns the html decoded *str*. + + Examples: + + >>> sql("select htmldecode('("die+wunderbaren+jahre")') as query") + query + ------------------------- + ("die+wunderbaren+jahre") + >>> sql("select htmldecode(null) as query") + query + ----- + None + """ + if len(args)>1: + raise functions.OperatorError("htmldecode","operator takes only one argument") + if args[0]==None: + return None + return htmlunescape(args[0]) + +htmldecode.registered=True + +def htmlencode(*args): + """ + .. function:: htmldecode(str) + + Returns the html decoded *str*. + + Examples: + + >>> sql("select htmldecode('("die+wunderbaren+jahre")') as query") + query + ------------------------- + ("die+wunderbaren+jahre") + >>> sql("select htmldecode(null) as query") + query + ----- + None + """ + if len(args)>1: + raise functions.OperatorError("htmldecode","operator takes only one argument") + if args[0]==None: + return None + + return xml.sax.saxutils.escape(u''.join(args[0]), {'"': """}) + +htmlencode.registered=True + +tags = re.compile(r'<([^>]*?)>', re.UNICODE) +tagNL = re.compile(r'(?:\s|^)(?:br|/p|/div|/head|/table|/tr|ul|/ul|/title|/tfoot|/thead|/span|/ol|/h1|/h2|/h3|/h4|/h5|/h6|/caption)(?:\s|$)', re.UNICODE) +tagSPACE = re.compile(r'(?:\s|^)(?:/\w+|wbr|p|div|head|table|tr|title|thead|tfoot|source|span|q|pre|ol|link|i|h1|h2|h3|h4|h5|h6|em|code|caption|a|figure|figcaption)(?:\s|$)', re.UNICODE) +tagUnderscore = re.compile(r'(?:\s|^)(?:sup|sub)(?:\s|$)', re.UNICODE) +def htmlstriptags(*args): + """ + .. function:: htmlstriptags(str, default_tag_conversion) + + Strips the html tags of input. It also converts "
" tags to new lines. If a default_tag_conversion is provided + then tags that would have been erased are converted to *default_tag_conversion*. + + Examples: + + >>> sql("select htmlstriptags('asdf<>as< br>df

spacedparagraph

anotherline w3') as query") + query + ------------------------------------------- + asdfas + df spaced paragraph + anotherline w_3 + + >>> sql("select htmlstriptags('asdf<>as< br>df

spacedparagraph

anotherline w3', '***') as query") + query + ---------------------------------------------------- + ***asdf***as + df spaced paragraph + anotherline*** w_3 + + >>> sql("select htmlstriptags(null) as query") + query + ----- + + """ + + default_tag_conversion = u'' + if len(args) > 1: + default_tag_conversion = unicode(args[1]) + + def tagdecode(tag): + t = tag.group(1).lower() + if tagNL.search(t): + return u'\n' + if tagSPACE.search(t): + return u' ' + if tagUnderscore.search(t): + return u'_' + else: + return default_tag_conversion + + if args[0] is not None: + text = unicode(args[0]) + else: + text = '' + + return tags.sub(tagdecode, text) + +htmlstriptags.registered=True + +def urldecode(*args): + """ + .. function:: urldecode(str) + + Returns the url decoded *str*. + + Examples: + + >>> sql("select urldecode('where%2Ccollid%3Dcolid+and+u%3D%27val%27') as query") + query + ------------------------------ + where,collid=colid and u='val' + + + >>> sql("select urldecode(null) as query") + query + ----- + None + """ + if len(args)>1: + raise functions.OperatorError("urldecode","operator takes only one argument") + if args[0]!=None: + return unicode(urllib.unquote_plus(args[0])) + return None + +urldecode.registered=True + +def urlencode(*args): + """ + .. function:: urlescape(str) + + Returns the escaped URL. + + Examples: + + >>> sql("select urlencode('where, collid=colid') as query") + query + ----------------------- + where%2C+collid%3Dcolid + + """ + if len(args)>1: + raise functions.OperatorError("urlencode","operator takes only one argument") + if args[0]!=None: + return urllib.quote_plus(unicode(args[0])) + return None + +urlencode.registered=True + + +addwbr=re.compile(r'([./-])([^./\-\d\s])', re.DOTALL| re.UNICODE) + +def htmladdbreaks(*args): + """ + .. function:: url(href, linktext) + + Returns the a url pointing to *href* and having the link text *linktext*. + + Examples: + + >>> sql("select htmladdbreaks('very-long/string') as brokenhtml") + brokenhtml + -------------------------- + very-long/string + """ + + if args[0]==None: + return None + + out=u''.join([unicode(x) for x in args]) + + return addwbr.sub(r'\1\2', out) + +htmladdbreaks.registered=True + +def htmllink(*args): + """ + .. function:: htmllink(href, linktext) + + Returns the an html link pointing to *href* and having the link text *linktext*. + + Examples: + + >>> sql("select htmllink('http://somewhere.org') as url") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + url + ----------------------------------------------------------------- + http://somewhere.org + + >>> sql("select htmllink('somewhere.org') as url") + url + ----------------------------------------------------- + somewhere.org + + >>> sql("select htmllink('somewhere.org', 'go somewhere') as url") + url + ----------------------------------------------- + go somewhere + + """ + def addhttp(u): + if u.find('://')==-1: + return u'http://'+unicode(u) + return unicode(u) + + if len(args)>2: + raise functions.OperatorError("url","operator a maximum of two arguments") + + if len(args)==2: + if args[1]!=None: + return ''+unicode(args[1])+'' + + if args[0]==None: + return None + return ''+htmladdbreaks(htmlencode(unicode(args[0])))+'' + +htmllink.registered=True + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/iptools.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/iptools.py new file mode 100644 index 0000000..3c3eea3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/iptools.py @@ -0,0 +1,110 @@ +# coding: utf-8 + +import setpath +import socket,struct +import re + + + +def ip2long(*args): + + """ + .. function:: ip2long(ip) -> int + + Converts a decimal dotted quad IP string to long integer IP format. + It can take either one column of IP strings or 4 columns each having one + part of the IP address. + + Examples: + + >>> sql("select ip2long('123.123.123.123')") + ip2long('123.123.123.123') + -------------------------- + 2071690107 + >>> sql("select ip2long(123,123,123,123)") + ip2long(123,123,123,123) + ------------------------ + 2071690107 + + """ + + if len(args)==1: + try: + return struct.unpack('!L',socket.inet_aton(args[0]))[0] + except: + return + elif len(args)==4: + return struct.unpack('!L',socket.inet_aton('.'.join([str(x) for x in args])))[0] +ip2long.registered=True + +def long2ip(*args): + """ + .. function:: long2ip(int) -> ip + + Convert longint IP to dotted quad string + + Examples: + + >>> sql("select long2ip('2071690107')") + long2ip('2071690107') + --------------------- + 123.123.123.123 + >>> sql("select long2ip(2071690107)") + long2ip(2071690107) + ------------------- + 123.123.123.123 + + """ + + return socket.inet_ntoa(struct.pack('!L',int(args[0]))) +long2ip.registered=True + + +def ip_prefix(*args): + """ + .. function:: ip_prefix(ip, class_number) -> ip + + Returns the subnetwork class of an IP address. + + Examples: + + >>> sql("ip_prefix '123.34.24.54' ") + ip_prefix('123.34.24.54') + ------------------------- + 4 + >>> sql("ip_prefix '123.34.24.54' '3'") + ip_prefix('123.34.24.54','3') + ----------------------------- + 123.34.24 + >>> sql("ip_prefix '123.34.24.54' '2'") + ip_prefix('123.34.24.54','2') + ----------------------------- + 123.34 + """ + + if args[0]=='': + return '' + + ipl=[int(x) for x in args[0].split('.')] + + if len(args)==1: + return len(ipl) + + return '.'.join( [str(x) for x in ipl[0:int(args[1])] ] ) + +ip_prefix.registered=True + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/jpacks.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/jpacks.py new file mode 100644 index 0000000..dcda4be --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/jpacks.py @@ -0,0 +1,1319 @@ +import setpath +from lib import jopts +from lib.jsonpath import jsonpath as libjsonpath +import json +import operator +import itertools +import re +import functions +import math +try: + from collections import OrderedDict +except ImportError: + # Python 2.6 + from lib.collections26 import OrderedDict + + +def jpack(*args): + + """ + .. function:: jpack(args...) -> jpack + + Converts multiple input arguments into a single string. Jpacks preserve the types + of their inputs and are based on JSON encoding. Single values are represented as + themselves where possible. + + Examples: + + >>> sql("select jpack('a')") + jpack('a') + ---------- + a + + >>> sql("select jpack('a','b',3)") + jpack('a','b',3) + ---------------- + ["a","b",3] + + >>> sql("select jpack('a', jpack('b',3))") + jpack('a', jpack('b',3)) + ------------------------ + ["a",["b",3]] + + """ + + return jopts.toj(jopts.elemfromj(*args)) + +jpack.registered=True + +def jngrams(*args): + + """ + .. function:: jngrams(n,text) -> jpack + + Converts multiple input arguments into a jpack of ngrams. + + Examples: + + >>> sql("select jngrams(1,'This is a test phrase')") + jngrams(1,'This is a test phrase') + ------------------------------------------- + [["This"],["is"],["a"],["test"],["phrase"]] + + >>> sql("select jngrams(2,'This is a test phrase')") + jngrams(2,'This is a test phrase') + --------------------------------------------------------- + [["This","is"],["is","a"],["a","test"],["test","phrase"]] + + + """ + if type(args[0]) == int: + n = args[0] + text = args[1] + else: + n = 1 + text = args[0] + g = text.split(' ') + listofngrams = [] + for i in xrange(len(g)-n+1): + listofngrams.append(g[i:i+n]) + return jopts.toj(listofngrams) + +jngrams.registered=True + +def jfrequentwords(*args): + + """ + .. function:: jfrequentwords(args...) -> jpack + + Returns the frequent words of a text in a jpack + + """ + wordslist = args[0].split(' ') + setwords = set(wordslist) + c = dict.fromkeys(setwords, 0) + for w in wordslist: + c[w]+=1 + lenwords = len(setwords) + extremevals = int(math.ceil(lenwords * 3 * 1.0/100)) + frequences = sorted(c.values())[extremevals:(lenwords-extremevals)] + avgfrequency = math.ceil(sum(frequences)*1.0/len(frequences)) + + return jopts.toj([k for k,v in c.iteritems() if v >= avgfrequency]) + +jfrequentwords.registered=True + +def jsonstrict(*args): + + """ + .. function:: jsonstrict(args...) -> json string + + Sometimes we wish to process json lists from another application. Jsonstrict function + tries to always create json compatible lists. So it always returns json lists. + + Examples: + + >>> sql("select jsonstrict('a')") + jsonstrict('a') + --------------- + ["a"] + + >>> sql("select jsonstrict('a','b',3)") + jsonstrict('a','b',3) + --------------------- + ["a","b",3] + + >>> sql("select jsonstrict('a', jpack('b',3))") + jsonstrict('a', jpack('b',3)) + ----------------------------- + ["a",["b",3]] + + """ + + return json.dumps(jopts.elemfromj(*args), separators=(',',':'), ensure_ascii=False) + +jsonstrict.registered=True + +def jzip(*args): + + """ + .. function:: jzip(args...) -> json string + + It combines the corresponding elements of input jpacks. + + Examples: + + >>> sql('''select jzip('["a", "b"]', '[1,2]','[4,5]')''') + jzip('["a", "b"]', '[1,2]','[4,5]') + ----------------------------------- + [["a",1,4],["b",2,5]] + + """ + return json.dumps([list(x) for x in zip(*jopts.elemfromj(*args))], separators=(',',':'), ensure_ascii=False) + +jzip.registered=True + +def jzipdict(*args): + + """ + .. function:: jzipdict(args...) -> json string + + It combines the correspinding elements of input jpacks into a jdict. + + Examples: + + >>> sql('''select jzipdict('["a", "b"]', '[1,2]','[4,5]')''') + jzipdict('["a", "b"]', '[1,2]','[4,5]') + --------------------------------------- + {"a":[1,4],"b":[2,5]} + + """ + return json.dumps(dict(tuple([x[0], x[1:]]) for x in zip(*jopts.elemfromj(*args))), separators=(',',':'), ensure_ascii=False) + +jzipdict.registered=True + +def jlen(*args): + + """ + .. function:: jlen(args...) -> int + + Returns the total length in elements of the input jpacks. + + Examples: + + >>> sql("select jlen('abc')") + jlen('abc') + ----------- + 1 + + >>> sql("select jlen('a','b',3)") + jlen('a','b',3) + --------------- + 3 + + >>> sql("select jlen('a', jpack('b',3))") + jlen('a', jpack('b',3)) + ----------------------- + 3 + + >>> sql("select jlen('[1,2,3]')") + jlen('[1,2,3]') + --------------- + 3 + + """ + return sum([len(x) if type(x) in (dict,list) else 1 for x in (jopts.elemfromj(*args))]) + +jlen.registered=True + +def jrange(num): + """ + .. function:: jrange(num) -> jrange + + Returns a jrange of integer numbers. + + Examples: + + >>> sql("select jrange(5)") + jrange('a') + ----------------- + ["0","1","2","3"] + + """ + jran = [None]*num + for i in xrange(num): + jran[i] = str(i) + return jopts.toj(jran) + +jrange.registered=True + +def jfilterempty(*args): + """ + .. function:: jfilterempty(jpacks.) -> jpack + + Removes from input jpacks all empty elements. + + Examples: + + >>> sql("select jfilterempty('a', '', '[]')") + jfilterempty('a', '', '[]') + --------------------------- + a + + >>> sql("select jfilterempty('a','[null]',3)") + jfilterempty('a','[null]',3) + ---------------------------- + ["a",3] + + >>> sql("select jfilterempty('[3]', jpack('b', ''))") + jfilterempty('[3]', jpack('b', '')) + ----------------------------------- + [3,"b"] + + """ + + return jopts.toj([x for x in jopts.fromj(*args) if x!='' and x!=[] and x!=None]) + +jfilterempty.registered=True + +def jlengthiest(*args): + """ + .. function:: jlengthiest(jpacks.) -> jpack + + Returns the string with the greatest length contained in the jpacks. + + Examples: + + >>> sql("select jlengthiest('a', '', '[]')") + jlengthiest('a', '', '[]') + -------------------------- + a + + >>> sql("select jlengthiest('a','longer',3)") + jlengthiest('a','longer',3) + --------------------------- + longer + + >>> sql("select jlengthiest('[3]', jpack('b', ''))") + jlengthiest('[3]', jpack('b', '')) + ---------------------------------- + 3 + + """ + + maxlen=-1 + res=None + + for i in (x for x in jopts.fromj(*args)): + if i == None: + l=-1 + else: + l = len(unicode(i)) + if l > maxlen: + maxlen = l + res = i + + return res + +jlengthiest.registered=True + +def jchars(*args): + """ + .. function:: jletters(text) -> character jpack + + Splits an input text into its composing characters. + + Examples: + + >>> sql("select jchars('this is a text')") + jchars('this is a text') + --------------------------------------------------------- + ["t","h","i","s"," ","i","s"," ","a"," ","t","e","x","t"] + + >>> sql("select jchars('another', 'text')") + jchars('another', 'text') + --------------------------------------------- + ["a","n","o","t","h","e","r","t","e","x","t"] + """ + + output = [] + + for i in args: + output+=list(i) + + return json.dumps(output, separators=(',',':'), ensure_ascii=False) + +jchars.registered=True + +def j2s(*args): + + """ + .. function:: j2s(jpack) -> space separated string + + Converts multiple input jpacks to a space separated string. Newlines are converted to spaces. + + Examples: + + >>> sql("select j2s('[1,2,3]')") # doctest: +NORMALIZE_WHITESPACE + j2s('[1,2,3]') + -------------- + 1 2 3 + + >>> sql("select j2s('[1,2,3]','a')") # doctest: +NORMALIZE_WHITESPACE + j2s('[1,2,3]','a') + ------------------ + 1 2 3 a + + >>> sql("select j2s('a', 'b')") # doctest: +NORMALIZE_WHITESPACE + j2s('a', 'b') + ------------- + a b + + """ + + return ' '.join([ unicode(x).replace('\n',' ') for x in jopts.fromj(*args) ]) + +j2s.registered=True + +def j2t(*args): + + """ + .. function:: j2t(jpack) -> tabpack + + Converts multiple input jpacks to a tab separated pack (tab separated values). If tab or newline characters are found in + the source jpack they are converted to spaces. + + Examples: + + >>> sql("select j2t('[1,2,3]')") # doctest: +NORMALIZE_WHITESPACE + j2t('[1,2,3]') + -------------- + 1 2 3 + + >>> sql("select j2t('[1,2,3]','a')") # doctest: +NORMALIZE_WHITESPACE + j2t('[1,2,3]','a') + ------------------ + 1 2 3 a + + >>> sql("select j2t('a', 'b')") # doctest: +NORMALIZE_WHITESPACE + j2t('a', 'b') + ------------- + a b + + """ + + return '\t'.join([ unicode(x).replace('\t', ' ').replace('\n',' ') for x in jopts.fromj(*args) ]) + +j2t.registered=True + +def t2j(*args): + + """ + .. function:: t2j(tabpack) -> jpack + + Converts a tab separated pack to a jpack. + + Examples: + + >>> sql("select t2j(j2t('[1,2,3]'))") # doctest: +NORMALIZE_WHITESPACE + t2j(j2t('[1,2,3]')) + ------------------- + ["1","2","3"] + + >>> sql("select t2j('asdfasdf')") # doctest: +NORMALIZE_WHITESPACE + t2j('asdfasdf') + --------------- + ["asdfasdf"] + + """ + + fj=[] + for t in args: + fj+=t.split('\t') + + return json.dumps(fj, separators=(',',':'), ensure_ascii=False) + +t2j.registered=True + +def s2j(*args): + + """ + .. function:: s2j(tabpack) -> jpack + + Converts a space separated pack to a jpack. + + Examples: + + >>> sql("select s2j('1 2 3 ')") # doctest: +NORMALIZE_WHITESPACE + s2j('1 2 3 ') + -------------- + ["1","2","3"] + """ + + fj=[] + for t in args: + fj+=[x for x in t.split(' ') if x!=''] + + return jopts.toj(fj) + +s2j.registered=True + +def nl2j(*args): + + """ + .. function:: nl2j(text) -> jpack + + Converts a text with newlines to a jpack. + """ + + fj=[] + for t in args: + fj+=[x for x in t.split('\n')] + + return jopts.toj(fj) + +nl2j.registered=True + +def j2nl(*args): + + """ + .. function:: j2nl(jpack) -> text + + Converts multiple input jpacks to a newline separated text. + + Examples: + + >>> sql("select j2nl('[1,2,3]')") # doctest: +NORMALIZE_WHITESPACE + j2nl('[1,2,3]') + --------------- + 1 + 2 + 3 + + >>> sql("select j2nl('[1,2,3]','a')") # doctest: +NORMALIZE_WHITESPACE + j2nl('[1,2,3]','a') + ------------------- + 1 + 2 + 3 + a + + >>> sql("select j2nl('a', 'b')") # doctest: +NORMALIZE_WHITESPACE + j2nl('a', 'b') + -------------- + a + b + + """ + + return '\n'.join([unicode(x) for x in jopts.fromj(*args)]) + +j2nl.registered = True + +def jmerge(*args): + + """ + .. function:: jmerge(jpacks) -> jpack + + Merges multiple jpacks into one jpack. + + Examples: + + >>> sql("select jmerge('[1,2,3]', '[1,2,3]', 'a', 3 )") # doctest: +NORMALIZE_WHITESPACE + jmerge('[1,2,3]', '[1,2,3]', 'a', 3 ) + ------------------------------------- + [1,2,3,1,2,3,"a",3] + + """ + + return jopts.toj( jopts.fromj(*args) ) + +jmerge.registered=True + + +def jset(*args): + """ + .. function:: jset(jpacks) -> jpack + + Returns a set representation of a jpack, unifying duplicate items. + + Examples: + + >>> sql("select jset('[1,2,3]', '[1,2,3]', 'b', 'a', 3 )") # doctest: +NORMALIZE_WHITESPACE + jset('[1,2,3]', '[1,2,3]', 'b', 'a', 3 ) + ---------------------------------------- + [1,2,3,"a","b"] + + """ + + return jopts.toj(sorted(set(jopts.fromj(*args)))) + +jset.registered = True + + +def jexcept(*args): + """ + .. function:: jexcept(jpackA, jpackB) -> jpack + + Returns the items of jpackA except the items that appear on jpackB. + + Examples: + + >>> sql("select jexcept('[1,2,3]', '[1,2,3]')") # doctest: +NORMALIZE_WHITESPACE + jexcept('[1,2,3]', '[1,2,3]') + ----------------------------- + [] + + >>> sql("select jexcept('[1,2,3]', '[1,3]')") # doctest: +NORMALIZE_WHITESPACE + jexcept('[1,2,3]', '[1,3]') + --------------------------- + 2 + + """ + + if len(args) < 2: + raise functions.OperatorError("jexcept","operator needs at least two inputs") + + b = set(jopts.fromj(args[1])) + return jopts.toj([x for x in jopts.fromj(args[0]) if x not in b]) + +jexcept.registered = True + + +def jintersection(*args): + """ + .. function:: jintersection(jpackA, jpackB) -> jpack + + Returns the items of jpackA except the items that appear on jpackB. + + Examples: + + >>> sql("select jintersection('[1,2,3]', '[1,2,3]')") # doctest: +NORMALIZE_WHITESPACE + jintersection('[1,2,3]', '[1,2,3]') + ----------------------------------- + [1,2,3] + + >>> sql("select jintersection('[1,2,3]', '[1,3]', 1)") # doctest: +NORMALIZE_WHITESPACE + jintersection('[1,2,3]', '[1,3]', 1) + ------------------------------------ + 1 + + """ + + if len(args) < 2: + raise functions.OperatorError("jintersection","operator needs at least two inputs") + + return jopts.toj(sorted(set.intersection(*[set(jopts.fromj(x)) for x in args]))) + +jintersection.registered = True + + +def jsort(*args): + + """ + .. function:: jsort(jpacks) -> jpack + + Sorts the input jpacks. + + Examples: + + >>> sql("select jsort('[1,2,3]', '[1,2,3]', 'b', 'a', 3 )") # doctest: +NORMALIZE_WHITESPACE + jsort('[1,2,3]', '[1,2,3]', 'b', 'a', 3 ) + ----------------------------------------- + [1,1,2,2,3,3,3,"a","b"] + + """ + + return jopts.toj(sorted( jopts.fromj(*args) )) + +jsort.registered=True + +def jsplitv(*args): + + """ + .. function:: jsplitv(jpacks) -> [C1] + + Splits vertically a jpack. + + Examples: + + >>> sql("select jsplitv(jmerge('[1,2,3]', '[1,2,3]', 'b', 'a', 3 ))") # doctest: +NORMALIZE_WHITESPACE + C1 + -- + 1 + 2 + 3 + 1 + 2 + 3 + b + a + 3 + + """ + + yield ('C1', ) + + for j1 in jopts.fromj(*args): + yield [jopts.toj(j1)] + +jsplitv.registered=True + +def jsplit(*args): + + """ + .. function:: jsplit(jpacks) -> [C1, C2, ...] + + Splits horizontally a jpack. + + Examples: + + >>> sql("select jsplit('[1,2,3]', '[3,4,5]')") # doctest: +NORMALIZE_WHITESPACE + C1 | C2 | C3 | C4 | C5 | C6 + --------------------------- + 1 | 2 | 3 | 3 | 4 | 5 + + """ + + fj=[jopts.toj(x) for x in jopts.fromj(*args)] + + if fj==[]: + yield ('C1',) + + yield tuple( ['C'+str(x) for x in xrange(1,len(fj)+1)] ) + yield fj + +jsplit.registered=True + +def jflatten(*args): + + """ + .. function:: jflattten(jpacks) -> jpack + + Flattens all nested sub-jpacks. + + Examples: + + >>> sql(''' select jflatten('1', '[2]') ''') # doctest: +NORMALIZE_WHITESPACE + jflatten('1', '[2]') + -------------------- + ["1",2] + + >>> sql(''' select jflatten('[["word1", 1], ["word2", 1], [["word3", 2], ["word4", 2]], 3]') ''') # doctest: +NORMALIZE_WHITESPACE + jflatten('[["word1", 1], ["word2", 1], [["word3", 2], ["word4", 2]], 3]') + ------------------------------------------------------------------------- + ["word1",1,"word2",1,"word3",2,"word4",2,3] + + """ + + return jopts.toj( jopts.flatten( jopts.elemfromj(*args) )) + +jflatten.registered=True + +def jmergeregexp(*args): + + """ + .. function:: jmergeregexp(jpacks) -> jpack + + Creates a regular expression that matches all of the jpack's contents. If the input + jpack contains keyword pairs, then jmergeregexp returns a regular expression + with named groups. + + Examples: + + >>> sql(''' select jmergeregexp('["abc", "def"]') ''') # doctest: +NORMALIZE_WHITESPACE + jmergeregexp('["abc", "def"]') + ------------------------------ + (?:abc)|(?:def) + + >>> sql(''' select jmergeregexp('[["pos", "p1"], ["neg", "n1"], ["pos", "p2"]]') ''') # doctest: +NORMALIZE_WHITESPACE + jmergeregexp('[["pos", "p1"], ["neg", "n1"], ["pos", "p2"]]') + ------------------------------------------------------------- + (?Pn1)|(?Pp1|p2) + + >>> sql(''' select jmergeregexp('[]') ''') # doctest: +NORMALIZE_WHITESPACE + jmergeregexp('[]') + ------------------ + _^ + + + >>> sql(''' select jmergeregexp('["ab",""]') ''') # doctest: +NORMALIZE_WHITESPACE + jmergeregexp('["ab",""]') + ------------------------- + (?:ab) + + """ + + inp = jopts.fromj(*args) + + if len(inp)>0 and type(inp[0]) == list: + out={} + for x,y in inp: + if x not in out: + out[x] = [y] + else: + out[x].append(y) + + res = '|'.join('(?P<'+ x + '>' + '|'.join(y)+')' for x, y in out.iteritems() if y!='') + if res == '': + res = '_^' + return res + + res = '|'.join('(?:'+x+')' for x in inp if x!='') + if res == '': + res = '_^' + return res + +jmergeregexp.registered=True + +def jmergeregexpnamed(*args): + + """ + .. function:: jmergeregexpnamed(jpacks) -> jpack + + Creates a regular expression that matches all of the jpack's contents with named groups. If the number of + named groups in a regular expression is greater than 99, then the output will be a jpack of regular expressions. + + Examples: + + >>> sql(''' select jmergeregexpnamed('["abc", "def"]') ''') # doctest: +NORMALIZE_WHITESPACE + jmergeregexpnamed('["abc", "def"]') + ----------------------------------- + (abc)|(def) + + """ + + inp = jopts.fromj(*args) + inp.sort() + + out = [] + for g in xrange(0, len(inp), 99): + out.append('|'.join('('+x+')' for x in inp[g:g+99])) + + return jopts.toj(out) + +jmergeregexpnamed.registered=True + +def jdict(*args): + + """ + .. function:: jdict(key, value, key1, value1) -> jdict + + Returns a jdict of the keys and value pairs. + + Examples: + + >>> sql(''' select jdict('key1', 'val1', 'key2', 'val2') ''') # doctest: +NORMALIZE_WHITESPACE + jdict('key1', 'val1', 'key2', 'val2') + ------------------------------------- + {"key1":"val1","key2":"val2"} + + >>> sql(''' select jdict('key', '{"k1":1,"k2":2}') ''') # doctest: +NORMALIZE_WHITESPACE + jdict('key', '{"k1":1,"k2":2}') + ------------------------------- + {"key":{"k1":1,"k2":2}} + + >>> sql(''' select jdict('key', '["val1", "val2"]') ''') # doctest: +NORMALIZE_WHITESPACE + jdict('key', '["val1", "val2"]') + -------------------------------- + {"key":["val1","val2"]} + + >>> sql(''' select jdict('1') ''') # doctest: +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator JDICT: At least two arguments required + + """ + + if len(args)==1: + raise functions.OperatorError('jdict',"At least two arguments required") + + result = OrderedDict() + + for i in xrange(0, len(args), 2): + result[args[i]] = jopts.fromjsingle(args[i+1]) + + return jopts.toj( result ) + +jdict.registered=True + +def jdictkeys(*args): + + """ + .. function:: jdictkeys(jdict) -> jpack + + Returns a jpack of the keys of input jdict + + Examples: + + >>> sql(''' select jdictkeys('{"k1":1,"k2":2}', '{"k1":1,"k3":2}') ''') # doctest: +NORMALIZE_WHITESPACE + jdictkeys('{"k1":1,"k2":2}', '{"k1":1,"k3":2}') + ----------------------------------------------- + ["k1","k2","k3"] + + >>> sql(''' select jdictkeys('{"k1":1,"k2":2}') ''') # doctest: +NORMALIZE_WHITESPACE + jdictkeys('{"k1":1,"k2":2}') + ---------------------------- + ["k1","k2"] + >>> sql(''' select jdictkeys('test') ''') # doctest: +NORMALIZE_WHITESPACE + jdictkeys('test') + ----------------- + [] + >>> sql(''' select jdictkeys(1) ''') # doctest: +NORMALIZE_WHITESPACE + jdictkeys(1) + ------------ + [] + + """ + + if len(args)==1: + keys=[] + i=args[0] + try: + if i[0]=='{' and i[-1]=='}': + keys=[x for x in json.loads(i, object_pairs_hook=OrderedDict).iterkeys()] + except TypeError,e: + pass + else: + keys=OrderedDict() + for i in args: + try: + if i[0]=='{' and i[-1]=='}': + keys.update([(x,None) for x in json.loads(i, object_pairs_hook=OrderedDict).iterkeys()]) + except TypeError,e: + pass + keys=list(keys) + return jopts.toj( keys ) + +jdictkeys.registered=True + +def jdictvals(*args): + + """ + .. function:: jdictvals(jdict, [key1, key2,..]) -> jpack + + If only the first argument (jdict) is provided, it returns a jpack of the values of input jdict (sorted by the jdict keys). + + If key values are also provided, it returns only the keys that have been provided. + + Examples: + + >>> sql(''' select jdictvals('{"k1":1,"k2":2}') ''') # doctest: +NORMALIZE_WHITESPACE + jdictvals('{"k1":1,"k2":2}') + ---------------------------- + [1,2] + + >>> sql(''' select jdictvals('{"k1":1,"k2":2, "k3":3}', 'k3', 'k1', 'k4') ''') # doctest: +NORMALIZE_WHITESPACE + jdictvals('{"k1":1,"k2":2, "k3":3}', 'k3', 'k1', 'k4') + ------------------------------------------------------ + [3,1,null] + >>> sql(''' select jdictvals('{"k1":1}') ''') # doctest: +NORMALIZE_WHITESPACE + jdictvals('{"k1":1}') + --------------------- + 1 + >>> sql(''' select jdictvals('{"k1":1}') ''') # doctest: +NORMALIZE_WHITESPACE + jdictvals('{"k1":1}') + --------------------- + 1 + >>> sql(''' select jdictvals(1) ''') # doctest: +NORMALIZE_WHITESPACE + jdictvals(1) + ------------ + 1 + + """ + + if type(args[0]) in (int,float) or args[0][0]!='{' or args[0][-1]!='}': + return args[0] + d=json.loads(args[0]) + if len(args)==1: + d=d.items() + d.sort(key=operator.itemgetter(1,0)) + vals=[x[1] for x in d] + else: + vals=[] + for i in args[1:]: + try: + vals.append(d[i]) + except KeyboardInterrupt: + raise + except: + vals.append(None) + + return jopts.toj( vals ) + +jdictvals.registered=True + +def jdictsplit(*args): + + """ + .. function:: jdictsplit(jdict, [key1, key2,..]) -> columns + + If only the first argument (jdict) is provided, it returns a row containing the values of input jdict (sorted by the jdict keys). + + If key values are also provided, it returns only the columns of which the keys have been provided. + + Examples: + + >>> sql(''' select jdictsplit('{"k1":1,"k2":2}') ''') # doctest: +NORMALIZE_WHITESPACE + k1 | k2 + ------- + 1 | 2 + + >>> sql(''' select jdictsplit('{"k1":1,"k2":2, "k3":3}', 'k3', 'k1', 'k4') ''') # doctest: +NORMALIZE_WHITESPACE + k3 | k1 | k4 + -------------- + 3 | 1 | None + + """ + + d=json.loads(args[0]) + if len(args)==1: + d=sorted(d.items()) + yield tuple([x[0] for x in d]) + yield [jopts.toj(x[1]) for x in d] + else: + vals=[] + yield tuple(args[1:]) + for i in args[1:]: + try: + vals.append(jopts.toj(d[i])) + except KeyboardInterrupt: + raise + except: + vals.append(None) + yield vals + +jdictsplit.registered=True + + +def jdictsplitv(*args): + + """ + .. function:: jdictsplitv(jdict, [key1, key2,..]) -> columns + + If only the first argument (jdict) is provided, it returns rows containing the values of input jdict. + + If key values are also provided, it returns only the columns of which the keys have been provided. + + Examples: + + >>> sql(''' select jdictsplitv('{"k1":1,"k2":2}') ''') # doctest: +NORMALIZE_WHITESPACE + key | val + --------- + k1 | 1 + k2 | 2 + + >>> sql(''' select jdictsplitv('{"k1":1,"k2":2, "k3":3}', 'k3', 'k1', 'k4') ''') # doctest: +NORMALIZE_WHITESPACE + key | val + --------- + k3 | 3 + k1 | 1 + + """ + + yield ('key', 'val') + if len(args) == 1: + dlist = json.loads(args[0], object_pairs_hook=OrderedDict) + for k, v in dlist.iteritems(): + yield [k, jopts.toj(v)] + else: + dlist = json.loads(args[0]) + for k in args[1:]: + try: + yield k, jopts.toj(dlist[k]) + except KeyError: + pass + +jdictsplitv.registered = True + +def jdictgroupkey(*args): + """ + .. function:: jdictgroupkey(list_of_jdicts, groupkey1, groupkey2, ...) + + It groups an array of jdicts into a hierarchical structure. The grouping is done + first by groupkey1 then by groupkey2 and so on. + + If no groupkeys are provided, then the first key of array's first jdict is used as a groupkey. + + Examples: + + >>> sql('''select jdictgroupkey('[{"gkey":"v1", "b":1},{"gkey":"v1","b":2},{"gkey":"v2","b":1, "c":2}]') as j''') + j + --------------------------------------------- + {"v1":[{"b":1},{"b":2}],"v2":[{"b":1,"c":2}]} + + >>> sql('''select jdictgroupkey('[{"gkey":"v1", "b":1},{"gkey":"v1","b":2},{"gkey":"v2","b":1, "c":2}]', "gkey") as j''') + j + --------------------------------------------- + {"v1":[{"b":1},{"b":2}],"v2":[{"b":1,"c":2}]} + + >>> sql('''select jdictgroupkey('[{"gkey":"v1", "gkey2":"f1", "b":1},{"gkey":"v1", "gkey2":"f2", "b":2},{"gkey":"v1", "gkey2":"f2", "b":1, "c":2}]', "gkey", "gkey2") as j''') + j + -------------------------------------------------------------- + {"v1":{"gkey2":{"f1":[{"b":1}],"f2":[{"b":2},{"b":1,"c":2}]}}} + + """ + + def recgroupkey(jdict, gkeys): + outdict=OrderedDict() + + for d in jdict: + if d[gkeys[0]] not in outdict: + outdict[d[gkeys[0]]] = [d] + else: + outdict[d[gkeys[0]]].append(d) + del(d[gkeys[0]]) + + if len(gkeys)>1: + outdict = OrderedDict([(x, recgroupkey(y, gkeys[1:])) for x,y in outdict.iteritems()]) + + return {gkeys[0]:outdict} + + outdict=OrderedDict() + dlist=json.loads(args[0], object_pairs_hook=OrderedDict) + + if len(args) == 1: + groupkeys = [iter(dlist[0]).next()] + else: + groupkeys = args[1:] + + outdict = recgroupkey(dlist, groupkeys) + + return jopts.toj(outdict[groupkeys[0]]) + +jdictgroupkey.registered=True + +def jsplice(*args): + + """ + .. function:: jsplice(jpack, range1_start, range1_end, ...) -> jpack + + Splices input jpack. If only a single range argument is provided, it returns input jpack's element in provided position. If defined position + index is positive, then it starts counting from the beginning of input jpack. If defined position is negative it starts counting from the + end of input jpack. + + If more than one range arguments are provided, then the arguments are assumed to be provided in pairs (start, end) that define ranges inside + the input jpack that should be joined together in output jpack. + + Examples: + + >>> sql(''' select jsplice('[1,2,3,4,5]',0) ''') # doctest: +NORMALIZE_WHITESPACE + jsplice('[1,2,3,4,5]',0) + ------------------------ + 1 + + >>> sql(''' select jsplice('[1,2,3,4,5]',-1) ''') # doctest: +NORMALIZE_WHITESPACE + jsplice('[1,2,3,4,5]',-1) + ------------------------- + 5 + + >>> sql(''' select jsplice('[1,2,3,4,5]',10) ''') # doctest: +NORMALIZE_WHITESPACE + jsplice('[1,2,3,4,5]',10) + ------------------------- + None + + >>> sql(''' select jsplice('[1,2,3,4,5]', 0, 3, 0, 2) ''') # doctest: +NORMALIZE_WHITESPACE + jsplice('[1,2,3,4,5]', 0, 3, 0, 2) + ---------------------------------- + [1,2,3,1,2] + + >>> sql(''' select jsplice('[1,2,3,4,5]', 2, -1) ''') # doctest: +NORMALIZE_WHITESPACE + jsplice('[1,2,3,4,5]', 2, -1) + ----------------------------- + [3,4] + + """ + + largs=len(args) + if largs==1: + return args[0] + + fj=jopts.fromj(args[0]) + + if largs==2: + try: + return jopts.toj(fj[args[1]]) + except KeyboardInterrupt: + raise + except: + return None + + outj=[] + for i in xrange(1,largs,2): + try: + outj+=fj[args[i]:args[i+1]] + except KeyboardInterrupt: + raise + except: + pass + + return jopts.toj(outj) + + +jsplice.registered=True + +def jcombinations(*args): + + """ + .. function:: jcombinations(jpack, r) -> multiset + + Returns all length r combinations of jpack. + + Examples: + + >>> sql('''select jcombinations('["t1","t2","t3"]',2)''') + C1 | C2 + ------- + t1 | t2 + t1 | t3 + t2 | t3 + + >>> sql('''select jcombinations('["t1","t2",["t3","t4"]]',2)''') + C1 | C2 + ---------------- + t1 | t2 + t1 | ["t3","t4"] + t2 | ["t3","t4"] + + >>> sql('''select jcombinations(null,2)''') + + + >>> sql('''select jcombinations('["t1","t2","t3","t4"]')''') + C1 + -- + t1 + t2 + t3 + t4 + """ + + r=1 + if len(args)==2: + r=args[1] + + yield tuple(('C'+str(x) for x in xrange(1,r+1))) + for p in itertools.combinations(jopts.fromj(args[0]), r): + yield [jopts.toj(x) for x in p] + +jcombinations.registered=True + +def jpermutations(*args): + + """ + .. function:: jpermutations(jpack, r) -> multiset + + Returns all length r permutations of jpack. + + Examples: + + >>> sql('''select jpermutations('["t1","t2","t3"]',2)''') + C1 | C2 + ------- + t1 | t2 + t1 | t3 + t2 | t1 + t2 | t3 + t3 | t1 + t3 | t2 + + >>> sql('''select jpermutations('["t1","t2",["t3","t4"]]',2)''') + C1 | C2 + ------------------------- + t1 | t2 + t1 | ["t3","t4"] + t2 | t1 + t2 | ["t3","t4"] + ["t3","t4"] | t1 + ["t3","t4"] | t2 + + >>> sql('''select jpermutations(null,2)''') + + >>> sql('''select jpermutations('["t1","t2","t3","t4"]')''') + C1 + -- + t1 + t2 + t3 + t4 + """ + + r=1 + if len(args)==2: + r=args[1] + + yield tuple(('C'+str(x) for x in xrange(1,r+1))) + for p in itertools.permutations(jopts.fromj(args[0]), r): + yield [jopts.toj(x) for x in p] + +jpermutations.registered=True + + +def jsonpath(*args): + + """ + .. function:: jsonpath(JSON, jsonpathexpr1, jsonpathexpr2) -> multiset + + Uses jsonpath expressions to pick values from inside a JSON input. If the outputs of all JSONpath expressions + have the same number of elements in them, it splits the output into multiple rows. + + .. note:: + + For more on JSONpath see: http://goessner.net/articles/JsonPath/ + + Examples: + + >>> sql('''select jsonpath('{"d1":[{"name":"n1", "value":"v1"}, {"name":"n2", "value":"v2"}]}', '$.d1') ''') + C1 + ------------------------------------------------------- + [{"name":"n1","value":"v1"},{"name":"n2","value":"v2"}] + + >>> sql('''select jsonpath('{"d1":[{"name":"n1", "value":"v1"}, {"name":"n2", "value":"v2"}]}', '$.d1[*].name') ''') + C1 + -- + n1 + n2 + + >>> sql('''select jsonpath('{"d1":[{"name":"n1", "value":"v1"}, {"name":"n2", "value":"v2"}]}', '$.d1[*].name', '$.d1[*].value') ''') + C1 | C2 + ------- + n1 | v1 + n2 | v2 + + >>> sql('''select jsonpath('{"d1":[{"name":"n1", "value":"v1"}, {"name":"n2", "value":"v2"}]}', '$.d1[*].name', '$.d1[*].nonexisting') ''') + C1 | C2 + --------- + n1 | None + n2 | None + + >>> sql('''select jsonpath('{"d1":[{"name":"n1", "value":"v1"}, {"name":"n2"}]}', '$.d1[*].name', '$.d1[*].value') ''') + C1 | C2 + ---------------- + ["n1","n2"] | v1 + + >>> sql('''select jsonpath('{"d1":[{"name":"n1", "value":"v1"}, {"name":"n2", "value":"v2"}]}', '$.nonexisting') ''') + + + """ + + j = json.loads(args[0]) + + yield tuple( ('C'+str(x)for x in xrange( 1,len(args) ) ) ) + output=[libjsonpath(j, jp, use_eval=False) for jp in args[1:]] + + l=0 + lchanges=0 + for i in output: + try: + if len(i)!=l: + l=len(i) + lchanges+=1 + except TypeError: + pass + + if l==0: + return + + if lchanges>1: + yield [jopts.toj(x) if type(x)!=bool else None for x in output] + else: + for i in xrange(l): + yield [jopts.toj(x[i]) if type(x)!=bool else None for x in output] + +jsonpath.registered=True + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/langtools.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/langtools.py new file mode 100644 index 0000000..d5149be --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/langtools.py @@ -0,0 +1,139 @@ +# coding: utf-8 + +import setpath +import datetime +from lib import porter2 as porter +from lib.textcat import * + +classifier=NGram() + +def detectlang(*args): + + """ + .. function:: detectlang(text1, text2,...) -> text + + Detects the language of a snippet of text by analysing its statistical properties. + + Examples: + + >>> sql("detectlang 'ελληνικά'") + detectlang('ελληνικά') + ------------------------------ + greek-utf + >>> sql("detectlang this is in english") + detectlang('this is in english') + -------------------------------- + english + >>> sql("detectlang ceci est en français") + detectlang('ceci est en français') + ----------------------------------- + french + >>> sql("detectlang este es el español") + detectlang('este es el español') + --------------------------------- + spanish + """ + + if len(args)==0: + return + + l=''.join(args).encode('utf-8') + + if l=='': + return + + return classifier.classify(l) + +detectlang.registered=True + +def stem(*args): + + """ + .. function:: stem(text1, text2,...) -> text + + Does stemming according to the porter algorithm. + + Examples: + + >>> sql("stem 'cutting and creating'") + stem('cutting and creating') + ---------------------------- + cut and creat + + >>> sql("stem ceci est en français cutting") + stem('ceci est en français cutting') + ------------------------------------- + ceci est en françai cut + + """ + + out=[] + for i in args: + o=i.lower() + o=o.strip() + o=o.split(' ') + + for k in o: + if len(k)>0: + out.append(porter.stem(k)) + + return ' '.join(out) + +stem.registered=True + +def stem_en(*args): + + """ + .. function:: stem_en(text1, text2,...) -> text + + Detects if the input is in english and only then does the porter stemming else + it returns the input arguments concatenated + + Examples: + + >>> sql("stem_en 'cutting and creating'") + stem_en('cutting and creating') + ------------------------------- + cut and creat + + >>> sql("stem_en ceci est en français cutting") + stem_en('ceci est en français cutting') + ---------------------------------------- + ceci est en français cutting + + """ + + jargs=''.join(args) + + if detectlang(*args)!='english': + return jargs + + out=[] + for i in args: + o=i.lower() + o=o.strip() + o=o.split(' ') + + for k in o: + if len(k)>0: + out.append(porter.stem(k)) + + return ' '.join(out) + +stem_en.registered=True + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/logparse.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/logparse.py new file mode 100644 index 0000000..a9936a6 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/logparse.py @@ -0,0 +1,80 @@ +# coding: utf-8 +import re +import functions + +apache_log_split=re.compile('^(\\S*) (\\S*) (\\S*) (\\[[^\\]]+\\]) \\"(\\w+) ([^"\\\\]*(?:\\\\.[^"\\\\]*)*) HTTP/([\\d.]+)\\" (\\S*) (\\S*) \\"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)\\" \\"([^\\"]*)\\"$', re.UNICODE) + +months = { + 'Jan':'01', + 'Feb':'02', + 'Mar':'03', + 'Apr':'04', + 'May':'05', + 'Jun':'06', + 'Jul':'07', + 'Aug':'08', + 'Sep':'09', + 'Oct':'10', + 'Nov':'11', + 'Dec':'12' + } + +def apachelogsplit(*args): + + """ + .. function:: apachelogsplit(apache_log_line) -> [ip, ident, authuser, date, request, status, bytes, referrer, useragent] + + Breaks a single apache log row into multiple fields. + + Examples: + + >>> table1(''' + ... '1.1.1.1 - - [01/Feb/2001:01:02:03 +0001] "HEAD /test.com HTTP/1.1" 200 - "-" "reftest"' + ... ''') + >>> sql("select apachelogsplit(a) from table1") + ip | ident | authuser | date | method | uri | httpver | status | bytes | referrer | useragent + ---------------------------------------------------------------------------------------------------------------------------- + 1.1.1.1 | None | None | 2001-02-01T01:02:03+0001 | HEAD | /test.com | 1.1 | 200 | None | None | reftest + + """ + + yield ('ip', 'ident', 'authuser', 'date', 'method', 'uri', 'httpver', 'status', 'bytes', 'referrer', 'useragent') + + f=apache_log_split.match(''.join(args).strip()) + + if f == None: + raise functions.OperatorError("APACHELOGSPLIT", "Row function didn't receive any input") + f=f.groups() + + f=[None if x=='-' else x for x in f] + + #parse date + if f[3]!=None: + if f[3][4:7] in months: + f[3]=f[3][1:-1] + date=f[3] + f[3]=date[7:11]+'-'+months[date[3:6]]+'-'+date[0:2]+'T'+date[12:14]+':'+date[15:17]+':'+date[18:20]+date[21:] + + if f[7]!=None: + f[7]=int(f[7]) + if f[8]!=None: + f[8]=int(f[8]) + + yield f + +apachelogsplit.registered=True + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/mathops.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/mathops.py new file mode 100644 index 0000000..52f3018 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/mathops.py @@ -0,0 +1,256 @@ +import setpath +import functions +import random +# coding: utf-8 +import math +import json +from fractions import Fraction + +def randomrange(*args): + + """ + .. function:: randomrange(start, end, step) -> int + + Returns a random number in the defined range + + Examples: + + >>> sql("select randomrange(0, 68, 1)") # doctest: +ELLIPSIS + randomrange(0, 68, 1) + --------------------- + ... + + >>> sql("select randomrange(0, 68)") # doctest: +ELLIPSIS + randomrange(0, 68) + ------------------ + ... + + """ + + try: + s = 1 + if len(args) >= 3: + s = args[2] + ret=random.randrange(args[0], args[1], s) + except ValueError: + return None + + return ret + +randomrange.registered=True + +def gaussdistribution(*args): + + """ + .. function:: gaussdistribution(mean, sigma) -> float + + Returns a gaussian distribution. Sigma is the standard deviation of the + distribution + + Examples: + + >>> sql("select gaussdistribution(10,5)") # doctest: +ELLIPSIS + gaussdistribution(10,5) + ----------------------- + ... + + """ + + try: + ret=random.gauss(args[0],args[1]) + except ValueError: + return None + + return ret + +gaussdistribution.registered=True + + +def sqroot(*args): + + """ + .. function:: sqroot(int) -> int + + Returns the square root of a given argument. + + Examples: + + >>> table1(''' + ... 25 + ... ''') + >>> sql("select sqroot(a) from table1") + sqroot(a) + --------- + 5.0 + + """ + + try: + ret=math.sqrt(args[0]) + except ValueError: + return None + + return ret + +sqroot.registered=True + + +def safediv(*args): + + """ + .. function:: safediv(int, int, int) -> int + + Returns the first argument, when the division of the two subsequent numbers + includes zero in denominator (i.e. in third argument) + + Examples: + + >>> sql("select safeDiv(1,5,0)") + safeDiv(1,5,0) + -------------- + 1 + + """ + + if args[2]==0: + return args[0] + else: + return (args[1]/args[2]) + +safediv.registered = True + + +def simplify_fraction(f): + """ + .. function:: simplify_fraction(Fraction) -> int or float or Fraction + + Takes as input a Fraction and returns the equivalent int or float. + In the case the int or float cannot be represented, the function returns the Fraction in json format + + Examples: + >>> simplify_fraction(Fraction(50,1)) + 50 + + >>> simplify_fraction(Fraction(50,2)) + 25 + + >>> simplify_fraction(Fraction(55555555294967297,2)) + '[55555555294967297, 2]' + """ + + if f.denominator == 1 and f.numerator < 9223372036854775808: + return f.numerator + elif float(f) < 4294967296.0: + return float(f) + else: + return json.dumps([f.numerator, f.denominator]) + + +def farith(*args): + """ + .. function:: farith(calc) -> float or Fraction + + Takes as input a mathematical expression in polish notation and computes the result using fractional computation + + Examples: + + >>> sql("select farith('+',5,7)" ) + farith('+',5,7) + --------------- + 12 + + >>> sql("select farith('-','*','/',15,'-',7,'+',1,1,3,'+',2,'+',1,1)" ) + farith('-','*','/',15,'-',7,'+',1,1,3,'+',2,'+',1,1) + ---------------------------------------------------- + 5 + """ + + s = [] + for i in reversed(args): + if i in ('*', '/', '-', '+'): + operand1 = s.pop() + operand2 = s.pop() + if i == '+': + operand = operand1 + operand2 + elif i == '-': + operand = operand1 - operand2 + elif i == '/': + operand = operand1 / operand2 + elif i == '*': + operand = operand1 * operand2 + s.append(operand) + else: + if type(i) in (int, float, long): + operand = Fraction(i) + s.append(operand) + else: + try: + s.append(Fraction(*json.loads(i))) + except ValueError, e: + raise functions.OperatorError('farith',"invalid expression found: '" + i +"'") + + return simplify_fraction(s.pop()) + +farith.registered = True + + +def tonumber(*args): + + """ + .. function:: tonumber(variable) -> int or float + + Convert variable, whose type is str or unicode, to int or float, if it is feasible + + Examples: + + >>> sql("select tonumber('12.3') as val") + val + ---- + 12.3 + + >>> sql("select tonumber(12.3) as val") + val + ---- + 12.3 + + >>> sql("select tonumber('not a number') as val") + val + ------------ + not a number + + >>> sql("select tonumber(null) as val") + val + ---- + None + + """ + + if type(args[0]) not in (str, unicode): + return args[0] + + try: + ret = int(args[0]) + except ValueError: + try: + ret = float(args[0]) + except ValueError: + return args[0] + + return ret + +tonumber.registered = True + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/setpath.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/setpath.py new file mode 100644 index 0000000..6c01b65 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/setpath.py @@ -0,0 +1,3 @@ +import sys, os +curmodulepath = os.path.dirname( os.path.abspath(__file__)) +sys.path.append(os.path.abspath(os.path.join(curmodulepath,'..','..'))) \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/settings.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/settings.py new file mode 100644 index 0000000..eaa73b1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/settings.py @@ -0,0 +1,117 @@ +# coding: utf-8 + +import setpath +import functions +import logging + +def toggle(*args): + + """ + .. function:: toggle(setting_name) + + Toggles a boolean global setting + + Examples: + + >>> sql("toggle lala") + toggle('lala') + -------------- + lala not found + + >>> sql("toggle tracing") + toggle('tracing') + -------------------- + tracing is now: True + """ + + if len(args)==0: + return + setting=args[0].lower() + if setting in functions.settings and type(functions.settings[setting])==bool: + functions.settings[setting]^=True + return setting+" is now: " + str(functions.settings[setting]) + else: + return setting+" not found" +toggle.registered=True + +def setting(*args): + + """ + .. function:: setting(setting_name, [value]) + + Sets and returns a setting's value + + Examples: + + >>> sql("setting 'tracing' 0") + setting('tracing','0') + ---------------------- + False + + >>> sql("setting 'tracing'") + setting('tracing') + ------------------ + False + """ + + if len(args)==0: + return str(functions.settings) + setting=args[0].lower() + if setting in functions.settings: + if len(args)==1: + return str(functions.settings[setting]) + elif len(args)==2: + if type(functions.settings[setting])==bool: + if args[1].lower() in ['true', '1']: + s=True + else: + s=False + functions.settings[setting]=s + elif type(functions.settings[setting])==int: + functions.settings[setting]=int(args[1]) + elif type(functions.settings[setting])==str: + functions.settings[setting]=str(args[1]) + return str(functions.settings[setting]) + else: + return setting+" not found" +setting.registered=True + +def setlog(*args): + + """ + .. function:: setlog(filename) + + Sets the log file path/filename for exec operator + + """ + + setting='logging' + if functions.settings[setting]: + return True + + functions.settings[setting]=True + if len(args)==0: + file=None + else: + file=args[0] + + logging.basicConfig(filename=file,level=logging.NOTSET,format="%(asctime)s - %(name)s - %(flowname)s - %(levelname)s - %(message)s") + return True + +setlog.registered=True + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/similarity.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/similarity.py new file mode 100644 index 0000000..c13a2cf --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/similarity.py @@ -0,0 +1,448 @@ +import setpath +import lib.jopts as jopts +import functions +import math + + +#def cosine(*args): +# """ +# +# .. function:: cosine(pack1,pack2) +# +# Returns cosine distance value of two packs ( vector-like object's created by :func:`~functions.aggregate.packing.pack` and :func:`~functions.aggregate.packing.vecpack` functions). +# +# Example: +# +# Calculate distance in user movies WITH preference score. +# +# >>> table2(''' +# ... user1 Jonny 10 +# ... user1 Movie 5 +# ... user1 Depp 8 +# ... user1 Russel 3 +# ... user2 Jonny 1 +# ... user2 Movie 1 +# ... user2 Depp 2 +# ... ''') +# +# +# Creating every user's pack over movies (column b) with dimension values (preference) column c. +# +# >>> sql(\"""create table tmpuserfullvecsInmovie as +# ... select a as userid, pack(b,c) as pk +# ... from table2 group by a\""") +# +# Use packs to calculate cosine distance over user packs. +# +# >>> sql(\"""select u1.userid,u2.userid, cosine(u1.pk,u2.pk) as distance +# ... from +# ... tmpuserfullvecsInmovie as u1, +# ... tmpuserfullvecsInmovie as u2 +# ... where u1.userid>> sql("drop table tmpuserfullvecsInmovie") +# +# """ +# if len(args)!=2: +# raise functions.OperatorError("cosine","operator takes exactly two arguments") +# try: +# r=memunpack(args[0]) +# s=memunpack(args[1]) +# except Exception,e: +# raise functions.OperatorError("cosine","Wrong format in operator arguments: %s" %(e)) +# rset=set(r) #set(r) +# sset=set(s) #set(s)# +# sumr=math.sqrt(sum([float(r[key])**2 for key in rset ])) +# sums=math.sqrt(sum([float(s[key])**2 for key in sset ])) +# return sum([float(r[key]*s[key]) for key in (rset & sset )])/(sumr*sums) +# +#cosine.registered=True + + +def jaccard(*args): + """ + .. function:: jaccard(jpack1,jpack2) + + Return jaccard similarity value of two jpacks. + + Example: + + >>> table1(''' + ... user1 movie1 20 + ... user1 movie2 30 + ... user2 movie1 40 + ... user2 movie3 90 + ... user2 movie4 90 + ... user3 movie1 40 + ... user3 movie3 80 + ... user4 movie1 70 + ... user4 movie2 10 + ... ''') + + NOTE that only column b is jgrouped because *jaccard* operates on packs as sets, not weighted values, So packing + also column c would not make any difference. + + >>> sql(\"""select u1.userid,u2.userid, jaccard(u1.pk, u2.pk) as similarity + ... from + ... (select a as userid, jgroup(b) as pk from table1 group by a) as u1, + ... (select a as userid, jgroup(b) as pk from table1 group by a) as u2 + ... where u1.userid>> table1(''' + ... user1 movie1 20 + ... user1 movie2 30 + ... user2 movie1 40 + ... user2 movie3 90 + ... user2 movie4 90 + ... user3 movie1 40 + ... user3 movie3 80 + ... user4 movie1 70 + ... user4 movie2 10 + ... ''') + + NOTE that only column b is jgrouped because *jaccard* operates on packs as sets, not weighted values, So packing + also column c would not make any difference. + + >>> sql(\"""select u1.userid,u2.userid, sorensendice(u1.pk, u2.pk) as similarity + ... from + ... (select a as userid, jgroup(b) as pk from table1 group by a) as u1, + ... (select a as userid, jgroup(b) as pk from table1 group by a) as u2 + ... where u1.userid>> table1(''' +# ... user1 movie1 20 +# ... user1 movie2 30 +# ... user2 movie1 40 +# ... user2 movie3 90 +# ... user2 movie4 90 +# ... user3 movie1 40 +# ... user3 movie3 80 +# ... user4 movie1 70 +# ... user4 movie2 10 +# ... ''') +# +# Creating in table tmpuservecsInmovie user packs over movies (column b) as sets (no preference score is packed - column c). +# +# >>> sql(\"""create table tmpuservecsInmovie as +# ... select a as userid, pack(b) as pk +# ... from table1 group by a\""") +# +# Creating vectorizing packs in table tmpuserfullvecsInmovie again as sets. +# Every user vector pack includes all distinct values of column b as dimension +# with weight 1 or 0 based on if the dimension exists in user group in the table2. +# +# >>> sql(\"""create table tmpuserfullvecsInmovie as +# ... select a as userid, vecpack(metrics,b) as pk +# ... from +# ... table1, +# ... (select pack(distinct b) as metrics from table1) +# ... group by a\""") +# +# Calculating euclean over non-vector packs that do not include preference score (column c) leads to zero distance for all user pairs, +# since in common dimension value 1 is included in the pack. +# +# >>> sql(\"""select u1.userid,u2.userid, euclean(u1.pk,u2.pk) as distance +# ... from +# ... tmpuservecsInmovie as u1, +# ... tmpuservecsInmovie as u2 +# ... where u1.userid>> sql(\"""select u1.userid,u2.userid, euclean(u1.pk,u2.pk) as distance +# ... from +# ... tmpuserfullvecsInmovie as u1, +# ... tmpuserfullvecsInmovie as u2 +# ... where u1.userid>> sql(\"""create table tmpuservecsInmoviePref as +# ... select a as userid, pack(b,c) as pk +# ... from table1 group by a\""") +# >>> sql(\"""create table tmpuserfullvecsInmoviePref as +# ... select a as userid, vecpack(metrics,b,c) as pk +# ... from +# ... table1, +# ... (select pack(distinct b) as metrics from table1) +# ... group by a\""") +# >>> sql(\"""select u1.userid,u2.userid, euclean(u1.pk,u2.pk) as distance +# ... from +# ... tmpuservecsInmoviePref as u1, +# ... tmpuservecsInmoviePref as u2 +# ... where u1.userid>> sql(\"""select u1.userid,u2.userid, euclean(u1.pk,u2.pk) as distance +# ... from +# ... tmpuserfullvecsInmoviePref as u1, +# ... tmpuserfullvecsInmoviePref as u2 +# ... where u1.userid>> sql("drop table tmpuservecsInmovie") +# >>> sql("drop table tmpuserfullvecsInmovie") +# >>> sql("drop table tmpuservecsInmoviePref") +# >>> sql("drop table tmpuserfullvecsInmoviePref") +# """ +# if len(args)!=2: +# raise functions.OperatorError("euclean","operator takes exactly two arguments") +# try: +# r=memunpack(args[0]) +# s=memunpack(args[1]) +# except Exception,e: +# raise functions.OperatorError("euclean","Wrong format operator arguments: %s" %(e)) +# rset=set(r) +# sset=set(s) +# return math.sqrt(sum([(float(r[key])-float(s[key]))**2 for key in (rset & sset )])) +#euclean.registered=True + + +#def eucleancommon(*args):###not working with lists +# """ +# +# .. function:: eucleancommon(pack1,pack2) +# +# Returns euclidean distance value of two packets ( vector-like object's created by :func:`~functions.aggregate.packing.pack` and :func:`~functions.aggregate.packing.vecpack` function). +# If packets are full vectors or include zero weights then then only common metrics (non-zero values) will be used in the calculation. +# This function behaves exactly like :func:`euclean` but exhibits the same behavior if packs are vectorized. +# +# Examples: +# +# The examples used are the same ones used in :func:`euclean`. Check them for a more detailed explanation of the followed steps. +# +# >>> table1(''' +# ... user1 movie1 20 +# ... user1 movie2 30 +# ... user2 movie1 40 +# ... user2 movie3 90 +# ... user2 movie4 90 +# ... user3 movie1 40 +# ... user3 movie3 80 +# ... user4 movie1 70 +# ... user4 movie2 10 +# ... ''') +# +# Calculate distance in user movies WITHOUT preference score. +# +# >>> sql(\"""create table tmpuservecsInmovie as +# ... select a as userid, pack(b) as pk +# ... from table1 group by a\""") +# >>> sql(\"""create table tmpuserfullvecsInmovie as +# ... select a as userid, vecpack(metrics,b) as pk +# ... from +# ... table1, +# ... (select pack(distinct b) as metrics from table1) +# ... group by a\""") +# >>> sql(\"""select u1.userid,u2.userid, eucleancommon(u1.pk,u2.pk) as distance +# ... from +# ... tmpuservecsInmovie as u1, +# ... tmpuservecsInmovie as u2 +# ... where u1.userid>> sql(\"""select u1.userid,u2.userid, eucleancommon(u1.pk,u2.pk) as distance +# ... from +# ... tmpuserfullvecsInmovie as u1, +# ... tmpuserfullvecsInmovie as u2 +# ... where u1.userid>> sql(\"""create table tmpuservecsInmoviePref as +# ... select a as userid, pack(b,c) as pk +# ... from table1 group by a\""") +# >>> sql(\"""create table tmpuserfullvecsInmoviePref as +# ... select a as userid, vecpack(metrics,b,c) as pk +# ... from +# ... table1, +# ... (select pack(distinct b) as metrics from table1) +# ... group by a\""") +# >>> sql(\"""select u1.userid,u2.userid, eucleancommon(u1.pk,u2.pk) as distance +# ... from +# ... tmpuservecsInmoviePref as u1, +# ... tmpuservecsInmoviePref as u2 +# ... where u1.userid>> sql(\"""select u1.userid,u2.userid, eucleancommon(u1.pk,u2.pk) as distance +# ... from +# ... tmpuserfullvecsInmoviePref as u1, +# ... tmpuserfullvecsInmoviePref as u2 +# ... where u1.userid>> sql("drop table tmpuservecsInmovie") +# >>> sql("drop table tmpuserfullvecsInmovie") +# >>> sql("drop table tmpuservecsInmoviePref") +# >>> sql("drop table tmpuserfullvecsInmoviePref") +# """ +# if len(args)!=2: +# raise functions.OperatorError("eucleancommon","operator takes exactly two arguments") +# try: +# r=memunpack(args[0]) +# s=memunpack(args[1]) +# except Exception,e: +# raise functions.OperatorError("eucleancommon","Wrong format in operator arguments: %s" %(e)) +# rset=set([key for key in r if r[key]!=0]) #set(r) +# sset=set([key for key in s if s[key]!=0]) #set(s)# +# +# return math.sqrt(sum([(float(r[key])-float(s[key]))**2 for key in (rset & sset )])) +# +#eucleancommon.registered=True + + + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/stopwords.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/stopwords.py new file mode 100644 index 0000000..54d466e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/stopwords.py @@ -0,0 +1,53 @@ +# coding: utf-8 + +import re +import setpath +from lib.stopwordlist import stopwords + + +def filterstopwords(*args): + + """ + .. function:: filterstopwords(str) -> str + + Returns the input text with the stopwords removed. The case of the first letter matters. + + Examples: + + >>> table1(''' + ... 'this and wood' 'NO more No words' + ... 'No more stop words' 'more free time' + ... ''') + >>> sql("select filterstopwords(a,b) from table1") + filterstopwords(a,b) + -------------------- + wood NO words + stop words free time + """ + + if len(args) == 1: + return ' '.join([k for k in args[0].split(' ') if k!='' and k[0].lower()+k[1:] not in stopwords]) + + out=[] + for i in args: + out.append(' '.join([k for k in i.split(' ') if k!='' and k[0].lower()+k[1:] not in stopwords])) + + return ' '.join(out) + +filterstopwords.registered=True + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/stringdist.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/stringdist.py new file mode 100644 index 0000000..e83a161 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/stringdist.py @@ -0,0 +1,80 @@ +# coding: utf-8 + +import setpath +import lib.stringdists as sd + +def levendist(*args): + """ + .. function:: levendist(str1, str2) + + Returns *int* which is the levenshtein distance between str1 and str2 + + Examples: + + >>> sql("select levendist('HURQBOHP','QKHOZ') ") + levendist('HURQBOHP','QKHOZ') + ----------------------------- + 7 + """ + if len(args)!=2: + raise functions.OperatorError("levendist","operator accepts two arguments") + + return sd.levenshtein_dist(args[0],args[1]) + +levendist.registered=True + +def damlevendist(*args): + """ + .. function:: damlevendist(str1, str2) + + Returns *int* which is the damerau-levenshtein distance between str1 and str2 + + Examples: + + >>> sql("select damlevendist('HURQBOHP','QKHOZ') ") + damlevendist('HURQBOHP','QKHOZ') + -------------------------------- + 6 + """ + if len(args)!=2: + raise functions.OperatorError("damlevendist","operator accepts two arguments") + + return sd.dameraulevenshtein_dist(args[0],args[1]) + +damlevendist.registered=True + +def quickstrdist(*args): + """ + .. function:: damlevendist(str1, str2) + + Returns *int* which is a string distance between str1 and str2, based on Python's + difflib library. It is a lot faster than levendist or damlevendist. + + Examples: + + >>> sql("select quickstrdist('HURQBOHP','QKHOZ') ") + quickstrdist('HURQBOHP','QKHOZ') + -------------------------------- + 8 + """ + if len(args)!=2: + raise functions.OperatorError("quickstrdist","operator accepts two arguments") + + return sd.quick_string_dist(args[0],args[1]) + +quickstrdist.registered=True + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/termsetops.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/termsetops.py new file mode 100644 index 0000000..6cbe6a0 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/termsetops.py @@ -0,0 +1,111 @@ +# coding: utf-8 + +import itertools + +def tset(*args): + + """ + .. function:: termsetdiff(termset1, termset2) -> termset + + Returns the termset that is the difference of sets of termset1 - termset2. + + Examples: + + >>> table1(''' + ... 't1 t2 t3' 't2 t3' + ... 't3 t2 t1' 't3 t4' + ... ''') + >>> sql("select tset(a,b) from table1") + tset(a,b) + ----------- + t1 t2 t3 + t1 t2 t3 t4 + """ + + return ' '.join(sorted(set(' '.join(args).split(' ')))) + +tset.registered=True + +def tsetdiff(*args): + + """ + .. function:: termsetdiff(termset1, termset2) -> termset + + Returns the termset that is the difference of sets of termset1 - termset2. + + Examples: + + >>> table1(''' + ... 't1 t2 t3' 't2 t3' + ... 't3 t2 t1' 't3 t4' + ... ''') + >>> sql("select tsetdiff(a,b) from table1") + tsetdiff(a,b) + ------------- + t1 + t1 t2 + """ + + if len(args)<2: + raise functions.OperatorError("tsetdiff","tsetdiff operator: at least two termsets should be provided") + + return ' '.join(sorted(set(args[0].split(' '))-set(args[1].split(' ')))) + +tsetdiff.registered=True + +def tsetcombinations(*args): + """ + .. function:: tsetcombinations(termset, r) -> termset + + Returns all the termset combinations of length r. + It is a multiset operator that returns one column but many rows. + + .. seealso:: + + * :ref:`tutmultiset` functions + + + >>> sql("select tsetcombinations('t1 t2 t3 t4',2)") + C1 + ----- + t1 t2 + t1 t3 + t1 t4 + t2 t3 + t2 t4 + t3 t4 + """ + if len(args)<1: + raise functions.OperatorError("tsetcombinations","tsetcombinations operator: no input") + + tset=args[0] + + if not isinstance(args[1], int): + raise functions.OperatorError("tsetcombinations","tsetcombinations operator: second argument should be integer") + + yield ("C1",) + + for p in itertools.combinations(sorted(tset.split(' ')), args[1]): + first=False + yield [' '.join(p)] + + if first: + yield [''] + +tsetcombinations.registered=True +tsetcombinations.multiset=True + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/testing/sales.tsv b/interactive-mining-3rdparty-madis/madis/src/functions/row/testing/sales.tsv new file mode 100644 index 0000000..7fe460a --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/testing/sales.tsv @@ -0,0 +1,12 @@ +Product Month Region Sales +Cars 2010-01 Athens 200 +Cars 2010-02 Athens 130 +Bikes 2010-01 NY 10 +Bikes 2010-02 NY 30 +Cars 2010-01 NY 100 +Cars 2010-02 NY 160 +Cars 2010-01 Paris 70 +Cars 2010-02 Paris 20 +Bikes 2010-01 Paris 100 +Bikes 2010-02 Paris 20 +Boats 2010-01 Paris 200 \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/text.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/text.py new file mode 100644 index 0000000..8840d0b --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/text.py @@ -0,0 +1,1314 @@ +# coding: utf-8 +import setpath +import re +import functions +import unicodedata +import hashlib +import zlib +import itertools +from collections import deque +from lib import jopts + +# Increase regular expression cache +try: + re._MAXCACHE = 1000 +except: + pass + +# Every regular expression containing \W \w \D \d \b \S \s needs to be compiled +# like below. If you want to embed the UNICODE directive inside the +# regular expression use: +# (?u) like re.sub(ur'(?u)[\W\d]', ' ', o) +delete_numbers_and_non_letters=re.compile(ur'[\W]',re.UNICODE) +delete_non_letters=re.compile(ur'[\W]',re.UNICODE) +delete_word_all=re.compile(ur'\w+\sall',re.UNICODE) +delete_word_all_and_or=re.compile(ur'\w+\sall\s(?:and|or)',re.UNICODE) +text_tokens = re.compile(ur'([\d.]+\b|\w+|\$[\d.]+)', re.UNICODE) +strip_remove_newlines=re.compile(u'(?:\\s+$|^\\s+|(?<=[^\\s\\d\\w.;,!?])\n+)', re.UNICODE) +reduce_spaces=re.compile(ur'\s+', re.UNICODE) +cqlterms=('title', 'subject', 'person', 'enter', 'creator', 'isbn') +replchars = re.compile(r'[\n\r]') + +def escapechars(*args): + def replchars_to_hex(match): + return r'\x{0:02x}'.format(ord(match.group())) + + return replchars.sub(replchars_to_hex, ''.join(args)) + +escapechars.registered = True + + +def keywords(*args): + + """ + .. function:: keywords(text1, [text2,...]) -> text + + Returns the keywords inside a single column (text1) or aggregated + multiple columns. + + Examples: + + >>> table1(''' + ... first(second) third+fourth + ... Ï€Ïωτο(δευτεÏο) Ï„Ïιτο+τέταÏτο + ... 'πέμπτο all' 'qwer.zxcv' + ... ''') + >>> sql("select keywords(a,b) from table1") + keywords(a,b) + --------------------------------------------------- + first second third fourth + Ï€Ïωτο δευτεÏο Ï„Ïιτο τέταÏτο + πέμπτο all qwer zxcv + """ + + out=text_tokens.findall(args[0]) + for i in args[1:]: + out+=text_tokens.findall(i) + + return ' '.join((x for x in out if x != '.')) + +keywords.registered=True + + +def cqlkeywords(*args): + + """ + .. function:: cqlkeywords(text1, [text2,...]) -> text + + Returns the keywords inside a single column (text1) or aggregated + from multiple columns. + + The difference of cqlkeywords to keywords is that cqlkeywords also + strips cql syntax like "title all" or "author all" and plain cql directives + like 'creator', 'title'... + + Examples: + + >>> table1(''' + ... first(second) third+fourth + ... Ï€Ïωτο(δευτεÏο) Ï„Ïιτο_τέταÏτο + ... 'πέμπτο all' 'έκτο title all τεστ' + ... 'title all and something' 'other' + ... 'title and something' 'other' + ... ''') + >>> sql("select cqlkeywords(a,b) from table1") + cqlkeywords(a,b) + --------------------------------------------------- + first second third fourth + Ï€Ïωτο δευτεÏο Ï„Ïιτο_τέταÏτο + έκτο τεστ + something other + and something other + """ + + out=[] + for i in args: + o=i.lower() + o=delete_non_letters.sub(' ',o) + o=delete_word_all_and_or.sub('',o) + o=delete_word_all.sub('',o) + o=reduce_spaces.sub(' ',o) + o=o.strip() + o=o.split(' ') + + for k in o: + if len(k)>0 and k not in cqlterms: + out.append(k) + + return ' '.join(out) + +cqlkeywords.registered=True + + +def kwnum(*args): + + """ + .. function:: kwnum(text1, [text2,...]) -> int + + Returns the number of simple keywords in a string. + Its input should be words separated by spaces, as returned by + cqlkeywords or keywords. + + Examples: + + >>> table1(''' + ... 'word1 word2 word3' + ... 'word1 word2' + ... 'word' + ... ''') + >>> sql("select kwnum(a) from table1") + kwnum(a) + -------- + 3 + 2 + 1 + """ + + o=0 + for i in args: + o+=len(i.split(' ')) + + return o + +kwnum.registered=True + +def uniqueterms(*args): + """ + .. function:: uniqueterms(text1, [text2,...]) -> text + + Returns the unique terms of an input string. + + Examples: + + >>> table1(''' + ... 'word1 word2 word2' + ... 'word1 word2 word1' + ... 'word' + ... ''') + >>> sql("select uniqueterms(a) from table1") + uniqueterms(a) + -------------- + word1 word2 + word1 word2 + word + """ + + o=set() + l=[] + for i in args: + for t in i.split(' '): + if t not in o and not t=='': + o.add(t) + l.append(t) + + return ' '.join(l) + +uniqueterms.registered=True + + +match_field_all=re.compile('(title|isbn|issn|subject|creator|language|type)\sall',re.UNICODE) + +def cqlfields(*args): + + """ + This functions returns the keywords inside a single column or aggregated + from multiple columns. It plays well with Unicode. + + The difference of cqlkeywords to keywords is that cqlkeywords also + strips cql syntax like "title all" or "author all". + + >>> table1(''' + ... '(title all "scrieri") and (creator all "arghezi") and (title all "other")' + ... '("maschinenschreiben") and (language all "ger")' + ... '("sauer") and ("übungsbuch")' + ... ''') + >>> sql("select cqlfields(a) from table1") + cqlfields(a) + ------------------- + title creator title + language + + """ + + out=[] + for i in args: + o=i.lower() + o=delete_numbers_and_non_letters.sub(' ',o) + fields=match_field_all.findall(o) + + for k in fields: + out.append(k) + return ' '.join(out) + + +cqlfields.registered=True + +def comprspaces(*args): + """ + .. function:: comprspaces(text1, [text2,...]) -> text + + This function strips (from the beginning and the end) and compresses + the spaces in its input. + + Examples: + + >>> table1(''' + ... ' an example with spaces ' 'another example with spaces ' + ... ''') + >>> sql("select comprspaces(a,b) from table1") + comprspaces(a,b) + -------------------------------------------------- + an example with spaces another example with spaces + """ + + if len(args) == 1: + return reduce_spaces.sub(' ', strip_remove_newlines.sub('', args[0])) + + out=[] + for i in args: + o=reduce_spaces.sub(' ', strip_remove_newlines.sub('', i)) + out+=[o] + + return ' '.join(out) + +comprspaces.registered=True + +reduce_special_characters=re.compile(ur'(?:[\s\n,.;]+|[^\w,.\s]+)',re.UNICODE) +reduce_underscore = re.compile(ur'(\b_+\b)',re.UNICODE) + +def normreplace(a): + if (a.group()[0] in ' \t\n.,;'): + return ' ' + + return '_'; + +def normalizetext(*args): + """ + .. function:: normalizetext(text1, [text2,...]) -> text + + Normalizes a text by replacing all the non-words except \s\n,.; with '_' + + Examples: + + >>> table1(''' + ... first(second) third+fourth + ... Ï€Ïωτο(δευτεÏο) Ï„Ïιτο+τέταÏτο + ... 'πέμπτο all' 'έκτο title all τεστ' + ... ''') + >>> sql("select normalizetext(a,b) from table1") + normalizetext(a,b) + ---------------------------------------------------- + first_second_ third_fourth + Ï€Ïωτο_δευτεÏο_ Ï„Ïιτο_τέταÏτο + πέμπτο all έκτο title all τεστ + """ + out=[] + for o in args: + o=reduce_special_characters.sub(normreplace,o) + o=reduce_underscore.sub(' ',o) + out.append(reduce_spaces.sub(' ', o).strip()) + + return ' '.join(out) + +normalizetext.registered=True + + +query_regular_characters=re.compile(ur"""^[·∆©(Ì−·¨¬…â€"•΄€„â€â€œâ€˜â€™Â´Â«Â»â€™Ê¹â€“\w\s\[!-~\]]*$""", re.UNICODE) + +def isvalidutf8(*args): + + """ + .. function:: isvalidutf8(text) -> 1/0 + + Returns 1 if the input text is in valid UTF-8 format, or 0 if not. + This function is used to find corrupted UTF-8 strings with a heuristic + based on non common characters. + + Examples: + + >>> table1(''' + ... test + ... δοκιμή! + ... sévignà + ... évezred + ... ''') + >>> sql("select isvalidutf8(a) from table1") + isvalidutf8(a) + -------------- + 1 + 1 + 1 + 1 + """ + + for i in args: + if i==None: + return 0 + if not query_regular_characters.match(i): + return 0 + + return 1 + +isvalidutf8.registered=True + + +characters_to_clean=re.compile(ur"""[^\w!-~]""", re.UNICODE) + +def utf8clean(*args): + + """ + .. function:: utf8clean(text) -> text + + Removes control characters from input utf-8 text. + + Examples: + + >>> table1(''' + ... test + ... δοκιμή! + ... sévignà + ... évezred + ... ''') + >>> sql("select utf8clean(a) from table1") + utf8clean(a) + ------------- + test + δοκιμή! + sévignà + évezred + """ + + def cleanchar(c): + c=c.group()[0] + if c != '\n' and unicodedata.category(c)[0] == 'C': + return u'' + else: + return c + + o='' + for i in args: + if type(i) in (str,unicode): + o+=characters_to_clean.sub(cleanchar, i) + else: + o+=unicode(i, errors='replace') + + return o + +utf8clean.registered=True + +def regexpr(*args): + + """ + .. function:: regexp(pattern,expression[,replacestr]) + + This function returns a match to the first parenthesis of *pattern* + or replaces the matches of *pattern* in *expression* with *replacestr*. + `Pattern Syntax `_ is + according to python's re module. + + Examples use `inversion`. + + Examples: + + >>> table1(''' + ... 25 + ... ''') + + >>> sql("regexpr 'start\s(\w+)\send' 'start otherword end' ") + regexpr('start\s(\w+)\send','start otherword end') + -------------------------------------------------- + otherword + + >>> sql("regexpr '\W+' '@#$%@$#% tobereplaced @#$%@#$%' 'nonword' ") + regexpr('\W+','@#$%@$#% tobereplaced @#$%@#$%','nonword') + --------------------------------------------------------- + nonwordtobereplacednonword + + >>> sql("select regexpr('(\w+).*?(\w+)', 'one two three')") + regexpr('(\w+).*?(\w+)', 'one two three') + ----------------------------------------- + ["one","two"] + """ + if len(args)<2: + return + + if len(args)==2: + a=re.search(args[0], unicode(args[1]),re.UNICODE) + if a!=None: + if len(a.groups())>0: + return jopts.toj(a.groups()) + else: + return True + else: + return None + + if len(args) == 3: + try: + return re.sub(args[0], args[2], args[1], flags=re.UNICODE) + except TypeError: + return re.sub(args[0], args[2], args[1]) + +regexpr.registered = True + +def regexprfindall(*args): + """ + .. function:: regexprfindall(pattern,text) + + This function returns *all* matches of *pattern* in text. + + Examples: + + >>> sql("select regexprfindall('\w+', 'one')") + regexprfindall('\w+', 'one') + ---------------------------- + ["one"] + + >>> sql("select regexprfindall('\w+', 'one two three')") + regexprfindall('\w+', 'one two three') + -------------------------------------- + ["one","two","three"] + """ + + if len(args)!=2: + raise functions.OperatorError('regexprfindall', 'Two parameters should be provided') + + return jopts.tojstrict(re.findall(args[0], unicode(args[1]),re.UNICODE)) + +regexprfindall.registered=True + +def regexprmatches(*args): + + """ + .. function:: regexprmatches(pattern, arg) + + This function returns true if the pattern matches arg or false otherwise. + + Examples use `inversion`. + + Examples: + + >>> sql("regexprmatches '(a)' 'qwer a qwer' ") + regexprmatches('(a)','qwer a qwer') + ----------------------------------- + 1 + + """ + if len(args)!=2: + raise functions.OperatorError('regexprmatches', 'Two parameters should be provided') + + a=re.search(args[0], unicode(args[1]),re.UNICODE) + if a!=None: + return True + else: + return False + +regexprmatches.registered=True + + +def regexpcountwithpositions(pattern,expression,start = 0,min = 0.5,multiply = 1): + """ + .. function:: regexpcountwithpositions(pattern, expression,start = 0,min = 0.5,multiply = 1,) + + Returns a score of positioned matches of pattern in expression. + + Examples: + + >>> sql("regexpcountwithpositions 'start' 'start end start' ") + regexpcountwithpositions('start','start end start') + --------------------------------------------------- + 1.75 + + >>> sql("regexpcountwithpositions 'start' 'start end start' ") + regexpcountwithpositions('start','start end start') + --------------------------------------------------- + 1.75 + + >>> sql("regexpcountwithpositions 'first' 'first second third fourth'") + regexpcountwithpositions('first','first second third fourth') + ------------------------------------------------------------- + 0.75 + + >>> sql("regexpcountwithpositions 'fourth' 'first second third fourth'") + regexpcountwithpositions('fourth','first second third fourth') + -------------------------------------------------------------- + 1.5 + + >>> sql("regexpcountwithpositions 'fourth' 'first second third fourth' 1") + regexpcountwithpositions('fourth','first second third fourth','1') + ------------------------------------------------------------------ + 0.5 + """ + + count = 0 + if start == 0: + total = 0 + for i in re.finditer(pattern+'|(\s)',expression,re.UNICODE): + count += 1 + if i.group()!=' ': + total += count * multiply + if total == 0: + return 0.0 + else: + if count == 0 : + return min + return min + total / float(count) + else: + matches = [] + total = 0 + for i in re.finditer(pattern+'|(\s)',expression,re.UNICODE): + count += 1 + if i.group()!=' ': + matches.append(count) + total += count * multiply + if total == 0: + return 0.0 + else: + if count == 0: + return min + return min + sum(count - i for i in matches) / float(count) + +regexpcountwithpositions.registered=True + + +def regexpcountuniquematches(*args): + """ + .. function:: regexpcountuniquematches(pattern, expression) + + Returns the number of matches of pattern in expression. + + Examples: + + + + >>> sql("regexpcountuniquematches 'start' 'start end start' ") + regexpcountuniquematches('start','start end start') + --------------------------------------------------- + 1 + + >>> sql("regexpcountuniquematches 'start end' 'start end start' ") + regexpcountuniquematches('start end','start end start') + ------------------------------------------------------- + 1 + + """ + + return len(set(re.findall(args[0], unicode(args[1]), re.UNICODE))) + +regexpcountuniquematches.registered=True + + +def regexpcountwords(*args): + """ + .. function:: regexpcountwords(pattern, expression) + + Returns the number of matches of pattern in expression. If a match includes more than one words then it returns the number of the words. + + Examples: + + >>> sql("regexpcountwords 'start' 'start end start' ") + regexpcountwords('start','start end start') + ------------------------------------------- + 2 + + >>> sql("regexpcountwords 'start end' 'start end start' ") + regexpcountwords('start end','start end start') + ----------------------------------------------- + 2 + """ + + return sum(((i.group().strip().count(' ')+1) for i in re.finditer(args[0],unicode(args[1]),re.UNICODE) )) + +regexpcountwords.registered=True + + +def contains(*args): + """ + .. function:: contains(str1,str2) -> bool + + Returns true if string *str1* contains *str2*. + + Examples: + + >>> sql("select contains('test string', 'str') as test ") + test + ---- + 1 + >>> sql("select contains('test string', 'nostr') as test ") + test + ---- + 0 + """ + if len(args)!=2: + raise functions.OperatorError("included","operator takes exactly two arguments") + if (args[1] in args[0]): + return True + return False + +contains.registered=True + + +def unitosuni(*args): + """ + .. function:: unitosuni(str) + + Returns *str* replacing non-ascii characters with their equivalent + unicode code point literal at the \\u00 format. + + Examples: + + >>> sql("select unitosuni('brûlé') as test ") + test + --------------- + br\\u00fbl\\u00e9 + >>> sql("select sunitouni(null)") + sunitouni(null) + --------------- + None + >>> sql("select unitosuni(9)") + unitosuni(9) + ------------ + 9 + """ + if len(args)!=1: + raise functions.OperatorError("unitosuni","operator takes only one arguments") + if args[0]==None: + return None + try: + return repr(unicode(args[0])).replace('\\x','\\u00')[2:-1] + except KeyboardInterrupt: + raise + except Exception: + return args[0] + +unitosuni.registered=True + + +def sunitouni(*args): + """ + .. function:: sunitouni(str) + + Returns *str* replacing literal unicode code points to their string representation. + + Examples: + + >>> sql("select sunitouni('br\\u00fbl\\u00e9') as test ") + test + ------- + brûlé + >>> sql("select sunitouni('\\u that is not a unicode code point') as test ") + test + ----------------------------------- + \u that is not a unicode code point + >>> sql("select sunitouni(null)") + sunitouni(null) + --------------- + None + >>> sql("select sunitouni(9)") + sunitouni(9) + ------------ + 9 + """ + if len(args)!=1: + raise functions.OperatorError("sunitouni","operator takes only one arguments") + if args[0]==None: + return None + kk="u'%s'" %(unicode(args[0]).replace("'","\\'")) + try: + return eval(kk) + except KeyboardInterrupt: + raise + except Exception: + return args[0] + +sunitouni.registered=True + + +def stripchars(*args): + """ + .. function:: stripchars(str[,stripchars]) + + Returns *str* removing leading and trailing whitespace characters + or *stripchars* characters if given. Works like python's + `strip function `_. + + + Examples: + + >>> sql("select stripchars(' initial and final spaces ') as test ") + test + ------------------------ + initial and final spaces + >>> sql("select stripchars(' ',' <>') as test ") + test + ------------------------ + initial and final spaces + >>> sql("select stripchars(null)") + stripchars(null) + ---------------- + None + """ + if len(args)<1: + raise functions.OperatorError("stripchars","operator takes at least one arguments") + if args[0]==None: + return None + if len(args)<2: + return unicode(args[0]).strip() + return unicode(args[0]).strip(args[1]) +stripchars.registered=True + + +def reencode(*args): + if len(args)!=1: + raise functions.OperatorError("reencode","operator takes only one arguments") + + us=args[0] + if us==None: + return None + us=unicode(us) + try: + a=unicode(us.encode('iso-8859-1'),'utf-8') + return a + except KeyboardInterrupt: + raise + except Exception: + try: + a=unicode(us.encode('windows-1252'),'utf-8') + return a + except Exception: + return us + +reencode.registered=False + + +def normuni(*args): + """ + .. function:: normuni(str) + + Returns *str* normalised in the composed unicode normal form without replacing + same look characters. For example this 'À' character can be encoded with one or two + different characters, :func:`normuni` returns an one-character encoded version. This + function is important to check true strings equality. + + Functions :func:`sunitouni` and :func:`unitosuni` are used in the examples to make it more comprehensive. + + Examples: + + .. note:: + Returned results in the next two examples should look the same, + if not that is a bug at the combined characters rendering of the shell + that the documentation was created. + + >>> sql("select sunitouni('C\u0327') as test ") + test + ---- + Ç + >>> sql("select normuni(sunitouni('C\u0327')) as test ") + test + ---- + Ç + >>> sql("select unitosuni(normuni(sunitouni('C\u0327'))) as test ") + test + ------ + \u00c7 + """ + if len(args)!=1: + raise functions.OperatorError("normuni","operator takes only one arguments") + if args[0]==None: + return None + return unicodedata.normalize('NFC', args[0]) + +normuni.registered=True + + +def hashmd5(*args): + """ + .. function:: hashmd5(args) + + Returns an MD5 hash of args. Numbers are converted to text before hashing is + performed. + + Examples: + + >>> sql("select hashmd5(65)") + hashmd5(65) + -------------------------------- + fc490ca45c00b1249bbe3554a4fdf6fb + >>> sql("select hashmd5(6,5)") + hashmd5(6,5) + -------------------------------- + f0d95c20cde50e3ca03cab53f986b6c3 + >>> sql("select hashmd5(5)") + hashmd5(5) + -------------------------------- + e4da3b7fbbce2345d7772b0674a318d5 + >>> sql("select hashmd5('5')") + hashmd5('5') + -------------------------------- + 7000aaf68ca7a93da0af3d03850571c2 + """ + + if len(args)==1: + return hashlib.md5(repr(args[0])).hexdigest() + else: + return hashlib.md5(chr(30).join([repr(x) for x in args])).hexdigest() + +hashmd5.registered=True + + +def hashmd5mod(*args): + """ + .. function:: hashmd5mod(args, divisor) -> int + + Returns the *modulo* with divisor number of the MD5 hash of args. + Numbers are converted to text before hashing is performed. + + Examples: + + >>> sql("select hashmd5mod(65, 3)") + hashmd5mod(65, 3) + ----------------- + 0 + + >>> sql("select hashmd5mod(6,5, 4)") + hashmd5mod(6,5, 4) + ------------------ + 2 + + >>> sql("select hashmd5mod(5, 5)") + hashmd5mod(5, 5) + ---------------- + 3 + + >>> sql("select hashmd5mod('5', 5)") + hashmd5mod('5', 5) + ------------------ + 4 + """ + + if len(args)==2: + return int(hashlib.md5(repr(args[0])).hexdigest(),16) % args[-1] + else: + return int(hashlib.md5(chr(30).join([repr(x) for x in args])).hexdigest(),16) % args[-1] + +hashmd5mod.registered=True + + +def crc32(*args): + """ + .. function:: crc32(args) -> int + + Returns the CRC32 of args. Numbers are converted to text before hashing is + performed. + + Examples: + + >>> sql("select crc32(65)") + crc32(65) + ---------- + 2658551721 + + >>> sql("select crc32(6,5)") + crc32(6,5) + ---------- + 1565899724 + + >>> sql("select crc32(5)") + crc32(5) + ---------- + 2226203566 + + >>> sql("select crc32('5')") + crc32('5') + ---------- + 1201448970 + """ + + if len(args)==1: + return zlib.crc32(repr(args[0])) & 0xffffffff + else: + return zlib.crc32(chr(30).join([repr(x) for x in args])) & 0xffffffff + +crc32.registered=True + +def hashmodarchdep(*args): + """ + .. function:: hashmodarchdep(args, divisor) -> int + + Returns a hash of the args. + + .. note:: + + This hash function is architecture dependent (32bit vs 64bit). + + Examples: + + >>> sql("select hashmodarchdep(65,5)") #doctest:+ELLIPSIS + hashmodarchdep(65,5) + -------------------- + ... + + >>> sql("select hashmodarchdep(6,5)") #doctest:+ELLIPSIS + hashmodarchdep(6,5) + ------------------- + ... + + >>> sql("select hashmodarchdep(5,5)") #doctest:+ELLIPSIS + hashmodarchdep(5,5) + ------------------- + ... + + >>> sql("select hashmodarchdep('5',5)") #doctest:+ELLIPSIS + hashmodarchdep('5',5) + --------------------- + ... + """ + + if len(args) == 2: + return hash(args[0]) % args[1] + else: + return hash(tuple(args[:-1])) % args[-1] + +hashmodarchdep.registered=True + + +def hashmodarchdep2(a, b): + """ + .. function:: hashmodarchdep2(arg, divisor) -> int + + Returns a hash of the args. + + .. note:: + + This hash function is architecture dependent (32bit vs 64bit). It is specialized for 2 parameters + + Examples: + + >>> sql("select hashmodarchdep2(65,5)") #doctest:+ELLIPSIS + hashmodarchdep2(65,5) + --------------------- + ... + + >>> sql("select hashmodarchdep2(6,5)") #doctest:+ELLIPSIS + hashmodarchdep2(6,5) + -------------------- + ... + + >>> sql("select hashmodarchdep2(5,5)") #doctest:+ELLIPSIS + hashmodarchdep2(5,5) + -------------------- + ... + + >>> sql("select hashmodarchdep2('5',5)") #doctest:+ELLIPSIS + hashmodarchdep2('5',5) + ---------------------- + ... + """ + return hash(a)%b + +hashmodarchdep2.registered=True + + +def textreferences(txt,maxlen = 5,pattern = r'(\b|_)((1[5-9]\d{2,2})|(20\d{2,2}))(\b|_)' ): + """ + .. function:: textreferences(text, maxlen = 5, pattern = (\b|_)(1|2)\d{3,3}(\b|_)) + + Returns the "Reference" section of documents. To find it, it searches for parts of the document that + have a high density of pattern matches. + + .. parameters:: txt,maxlen,pattern + txt: input text. + maxlen: the size of the scrolling window over the text in which the density is calculated. + pattern: regular expression that is matched against the lines of the text. By default the pattern matches + year occurences so as to extract sections that look like references. + + + Examples: + + >>> table1(''' + ... eeeeeeeeeeeeee + ... gggggggggggggg + ... aaaaaaaaaaaaaa + ... bbbbbbbbbbbbbb + ... aaa_1914_ccccc + ... bbb_2014_bbbbb + ... dddd_2008_ddddddd + ... cccc_2005_ccccc + ... ccccc_2014_ccccc + ... dddddd_2009_ddddd + ... gggggggggggggg + ... ''') + + >>> sql("select textreferences(group_concat(a,'\\n'),1,'(\b|_)(1|2)\d{3,3}(\b|_)') as a from table1") + a + -------------------------------------------------------------------------------------------------- + aaa_1914_ccccc + bbb_2014_bbbbb + dddd_2008_ddddddd + cccc_2005_ccccc + ccccc_2014_ccccc + dddddd_2009_ddddd + + + If an inadequate amount of newlines is found, it returns the text as is. + + >>> sql("select textreferences(group_concat(a,'.')) from table1") + textreferences(group_concat(a,'.')) + ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + eeeeeeeeeeeeee.gggggggggggggg.aaaaaaaaaaaaaa.bbbbbbbbbbbbbb.aaa_1914_ccccc.bbb_2014_bbbbb.dddd_2008_ddddddd.cccc_2005_ccccc.ccccc_2014_ccccc.dddddd_2009_ddddd.gggggggggggggg + + + >>> sql("select textreferences('')") + textreferences('') + ------------------ + + """ + + exp = re.sub('\r\n','\n',txt) + + if exp.count('\n')<10: + return exp + references = [] + reversedtext = iter(reversed(exp.split('\n')[10:])) + reversedtext2 = iter(reversed(exp.split('\n')[10:])) + results = [] + densities = [] + + for i in xrange(maxlen/2): + results.append(1) + for i in reversedtext: + if len(i)>10: + if re.search(pattern,i): + results.append(1) + else: + results.append(0) + + for i in xrange(maxlen/2): + results.append(0) + + out = 0 + temp = 0 + for i in xrange(maxlen/2,len(results)-maxlen/2): + if i==maxlen/2 : + temp = sum(results[0:maxlen])*1.0/maxlen + else: + if out == results[i+maxlen/2]: + pass + elif results[i+maxlen/2]: + temp = (temp*maxlen+1) *1.0 / maxlen + else: + temp = (temp*maxlen-1) *1.0 / maxlen + densities.append(temp) + out = results[i-maxlen/2] + + try: + threshold = sum(densities)/len(densities) + except: + threshold = 0 + + current = 0 + for i in reversedtext2: + if len(i)>10: + if densities[current] >= threshold: + references.append(i) + current+=1 + return '\n'.join(reversed(references)) + +textreferences.registered=True + + +def textwindow(*args): + """ + .. function:: textwindow(text, previous_word_count = 0, next_word_count = 0, middle_word_count = 1, pattern = None) + + Returns a rolling window over the text. The window includes *previous_word_count* words before the middle word + and next_word_count words after the middleword. Optionally you may choose more than one words to be in the middle, and filter your window with a regular expression pattern + + If the value of prev_word_count or next_word_count is negative, and a pattern exists then all matches of the pattern are + filtered out from prev and next output. + + Examples: + + >>> sql("select textwindow('This is a test phrase') ") + middle + ------ + This + is + a + test + phrase + + >>> sql("select textwindow('This is a test phrase',1,1) ") + prev1 | middle | next1 + ----------------------- + | This | is + This | is | a + is | a | test + a | test | phrase + test | phrase | + + >>> sql("select textwindow('This is a test phrase',1,1,2) ") + prev1 | middle | next1 + ---------------------------- + | This is | a + This | is a | test + is | a test | phrase + a | test phrase | + test | phrase | + + >>> sql("select textwindow('This is a test phrase with pdb codes: 1abc 2bcd 3cde 4bde ',-2,1,2,'\d\w{3}' ) ") + prev1 | prev2 | middle | next1 + ---------------------------------- + pdb | codes: | 1abc 2bcd | 3cde + pdb | codes: | 2bcd 3cde | 4bde + pdb | codes: | 3cde 4bde | + pdb | codes: | 4bde | + + >>> sql("select textwindow('This is a test phrase (123) for filtering middle with a number',1,1,'\d+') ") + prev1 | middle | next1 + ----------------------- + phrase | (123) | for + + """ + r = args[0] + try: + prev = args[1] + except IndexError: + prev = 0 + try: + nextlen = args[2] + except IndexError: + nextlen = 0 + + middle = 1 + pattern = None + try: + if type(args[3]) == int: + middle = args[3] + else: + pattern = args[3] + except IndexError: + pass + + try : + if type(args[4]) == int: + middle = args[4] + else: + pattern = args[4] + except IndexError: + pass + + if pattern == None: + prev = abs(prev) + + yield tuple(itertools.chain( ('prev'+str(x) for x in xrange(1,abs(prev)+1)),('middle',), ('next'+str(y) for y in xrange(1,nextlen + 1)) )) + g = [''] * prev + r.split(' ') + [''] * ((middle-1)+nextlen) + + if prev >= 0: + window = prev + nextlen + middle + pm = prev+middle + im = prev + if middle == 1: + if pattern == None: + for i in xrange(len(g)-window + 1): + yield (g[i:i+window]) + else: + patt = re.compile(pattern,re.UNICODE) + for i in xrange(len(g)-window + 1): + if patt.search(g[i+im]): + yield (g[i:i+window]) + + else : + if pattern == None: + for i in xrange(len(g)-window+1): + yield ( g[i:i+prev] + [' '.join(g[i+prev:i+pm])] + g[i+prev+middle:i+window] ) + else: + patt = re.compile(pattern,re.UNICODE) + for i in xrange(len(g)-window+1): + mid = ' '.join(g[i+prev:i+pm]) + if patt.search(mid): + yield ( g[i:i+prev] + [mid] + g[i+pm:i+window] ) + elif prev<0: + prev = abs(prev) + window = nextlen + middle + winprev = [''] * prev + winprev = deque(winprev, prev) + if middle == 1: + patt = re.compile(pattern,re.UNICODE) + for i in xrange(len(g)-window + 1): + if patt.search(g[i]): + yield tuple(itertools.chain(winprev,(g[i:i+window]))) + else: + winprev.append(g[i]) + else : + patt = re.compile(pattern,re.UNICODE) + for i in xrange(len(g)-window + 1): + mid = ' '.join(g[i:i+middle]) + if patt.search(g[i]): + yield tuple(itertools.chain(winprev, ([mid] + g[i+middle:i+window] ))) + else: + winprev.append(g[i]) + +textwindow.registered=True + + +def textwindow2s(*args): + """ + .. function:: textwindow2s(text, prev_word_count, middle_word_count, next_word_count, pattern) + + Returns a rolling window in the text. The window includes numberofprev words before the middle word and numberofnext words after the middleword. + You may filter your window using a pattern. + + Examples: + + + >>> sql("select textwindow2s('This is a test phrase',2,1,1) ") + prev | middle | next + ------------------------- + | This | is + This | is | a + This is | a | test + is a | test | phrase + a test | phrase | + + >>> sql("select textwindow2s('This is a test phrase',2,1,1, '\w{4}') ") + prev | middle | next + ------------------------ + | This | is + is a | test | phrase + a test | phrase | + + """ + g = args[0].split(' ') + yield tuple(('prev','middle','next')) + + try: + prev = args[1] + except IndexError: + prev = 0 + + try: + middle = args[2] + except IndexError: + middle = 1 + + try: + nextlen = args[3] + try: + nextlen = int(nextlen) + except: + raise functions.OperatorError('textwindow2s','Third argument should be an integer') + except IndexError: + nextlen = 0 + + if len(args) > 4: + try: + patt = re.compile(args[4]) + except: + raise functions.OperatorError('textwindow2s','Fourth argument must be string or compiled pattern') + for i in xrange(len(g)-middle+1): + im = i+middle + mid = ' '.join(g[i:im]) + if patt.search(mid): + yield (' '.join(g[max(i-prev,0):i]),mid,' '.join(g[im:im+nextlen])) + else: + for i in xrange(len(g)-middle+1): + im = i+middle + yield (' '.join(g[max(i-prev,0):i]),' '.join(g[i:im]),' '.join(g[im:im+nextlen])) + +textwindow2s.registered=True + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/tzconverter.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/tzconverter.py new file mode 100644 index 0000000..ac1bca9 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/tzconverter.py @@ -0,0 +1,104 @@ +from datetime import datetime, timedelta +import setpath +from lib import iso8601 + + +def tzconverter(*args): + + """ + .. function:: tzconverter(timestamp,offset) + + Returns timestamps converted from UTC to target timezone, indicated by the offset parameter. + + + Example:: + + >>> table1(''' + ... "2010-12-05T00:00:00+00:00" + ... "2010-12-05T00:01:00+00:00" + ... "2010-12-05T00:02:00+00:00" + ... ''') + + ... ''') + >>> sql("select a, tzconverter(a,'-01:00') from table1 ") + a | tzconverter(a,'-01:00') + ----------------------------------------------------- + 2010-12-05T00:00:00+00:00 | 2010-12-04T23:00:00-01:00 + 2010-12-05T00:01:00+00:00 | 2010-12-04T23:01:00-01:00 + 2010-12-05T00:02:00+00:00 | 2010-12-04T23:02:00-01:00 + + ... ''') + >>> sql("select a, tzconverter(a,'-01') from table1 ") + a | tzconverter(a,'-01') + -------------------------------------------------- + 2010-12-05T00:00:00+00:00 | 2010-12-04T23:00:00-01 + 2010-12-05T00:01:00+00:00 | 2010-12-04T23:01:00-01 + 2010-12-05T00:02:00+00:00 | 2010-12-04T23:02:00-01 + + >>> sql("select a, tzconverter(a,'-0100') from table1 ") + a | tzconverter(a,'-0100') + ---------------------------------------------------- + 2010-12-05T00:00:00+00:00 | 2010-12-04T23:00:00-0100 + 2010-12-05T00:01:00+00:00 | 2010-12-04T23:01:00-0100 + 2010-12-05T00:02:00+00:00 | 2010-12-04T23:02:00-0100 + + >>> sql("select a, tzconverter(a,'+00:30') from table1 ") + a | tzconverter(a,'+00:30') + ----------------------------------------------------- + 2010-12-05T00:00:00+00:00 | 2010-12-05T00:30:00+00:30 + 2010-12-05T00:01:00+00:00 | 2010-12-05T00:31:00+00:30 + 2010-12-05T00:02:00+00:00 | 2010-12-05T00:32:00+00:30 + + + """ + + date = iso8601.parse_date(args[0]) + mins = 0 + sign = '' + result = '' + c = 0 + + for i in args[1]: + if c == 0: + sign = args[1][0] + elif c == 1: + mins += int(args[1][1])*600 + elif c == 2: + mins += int (args[1][2])*60 + elif c == 3 and args[1][3] == ':': #in this case i know what's next + mins += int(args[1][4])*10 + int(args[1][5]) + break; + elif c == 3: + mins += int(args[1][3])*10 + elif c == 4: + mins += int (args[1][4]) + c+=1 + + if sign == '+': + result = date + timedelta(minutes = mins) + + elif sign == '-': + result = date - timedelta(minutes = mins) + + result = str(result).replace(" ","T").replace("+00:00", args[1]) + + return result + +tzconverter.registered = True + + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/util.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/util.py new file mode 100644 index 0000000..a0cdeca --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/util.py @@ -0,0 +1,375 @@ +# coding: utf-8 +import setpath +from gzip import zlib +import subprocess +import functions +import time +import urllib2 +import urllib +from lib import jopts +from functions.conf import domainExtraHeaders +import lib.gzip32 as gzip +try: + from collections import OrderedDict +except ImportError: + # Python 2.6 + from lib.collections26 import OrderedDict + +def gz(*args): + + """ + .. function:: gz(text) -> gzip compressed blob + + Function *gz* compresses its input with gzip's maximum compression level. + + Examples: + + >>> table1(''' + ... "qwerqewrqwerqwerqwerqwerqwer" + ... "asdfasdfasdfasdfasdfasdfsadf" + ... ''') + >>> sql("select length(a), length(gz(a)) from table1") + length(a) | length(gz(a)) + ------------------------- + 28 | 20 + 28 | 18 + + """ + + return buffer(zlib.compress(args[0], 9)) + +gz.registered=True + +def ungz(*args): + + """ + .. function:: ungz(blob) -> text + + Function *ungz* decompresses gzip blobs. If the input blobs aren't gzip + compressed, then it just returns them as they are. + + Examples: + + >>> table1(''' + ... "qwerqwerqwer" + ... "asdfasdfasdf" + ... ''') + >>> sql("select ungz(gz(a)) from table1") + ungz(gz(a)) + ------------ + qwerqwerqwer + asdfasdfasdf + + >>> sql("select ungz('string'), ungz(123)") + ungz('string') | ungz(123) + -------------------------- + string | 123 + + """ + + try: + return zlib.decompress(args[0]) + except KeyboardInterrupt: + raise + except: + return args[0] + +ungz.registered=True + +def urlrequest(*args): + + """ + .. function:: urlrequest([null], url) -> response + + This functions connects to the *url* (via GET HTTP method) and returns the request's result. If first + parameter is *null*, then in case of errors *null* will be returned. + + Examples: + + >>> sql("select urlrequest('http://www.google.com/not_existing')") + Traceback (most recent call last): + ... + HTTPError: HTTP Error 404: Not Found + + >>> sql("select urlrequest(null, 'http://www.google.com/not_existing') as result") + result + ------ + None + + """ + try: + req = urllib2.Request(''.join((x.encode('utf-8') for x in args if x != None)), None, domainExtraHeaders) + hreq = urllib2.urlopen(req) + + if [1 for x,y in hreq.headers.items() if x.lower() in ('content-encoding', 'content-type') and y.lower().find('gzip')!=-1]: + hreq = gzip.GzipFile(fileobj=hreq) + + return unicode(hreq.read(), 'utf-8', errors = 'replace') + + except urllib2.HTTPError,e: + if args[0] == None: + return None + else: + raise e + +urlrequest.registered=True + +def urlrequestpost(*args): + + """ + .. function:: urlrequestpost(data_jdict, [null], url) -> response + + This functions connects to the *url* (via POST HTTP method), submits the *data_jdict*, and returns the request's result. If second + parameter is *null*, then in case of errors *null* will be returned. + + Examples: + + >>> sql('''select urlrequestpost('{"POST_param_name":"data"}', 'http://www.google.com/not_existing')''') + Traceback (most recent call last): + ... + HTTPError: HTTP Error 404: Not Found + + >>> sql('''select urlrequestpost('["POST_param_name","data"]', null, 'http://www.google.com/not_existing') as result''') + result + ------ + None + + >>> sql("select urlrequestpost(jdict('param1','value1'), null, 'http://www.google.com/not_existing') as result") + result + ------ + None + + >>> sql("select urlrequestpost(jpack('param1','value1'), null, 'http://www.google.com/not_existing') as result") + result + ------ + None + + """ + try: + req = urllib2.Request(''.join((x for x in args[1:] if x != None)), None, domainExtraHeaders) + + datain = jopts.fromjsingle(args[0]) + + dataout = [] + if type(datain) == list: + for i in xrange(0, len(datain), 2): + dataout.append((datain[i].encode('utf_8'), datain[i+1].encode('utf_8'))) + else: + dataout = [( x.encode('utf_8'), y.encode('utf_8') ) for x,y in datain.items()] + + if dataout == []: + raise functions.OperatorError('urlrequestpost',"A list or dict should be provided") + + hreq = urllib2.urlopen(req, urllib.urlencode(dataout)) + + if [1 for x,y in hreq.headers.items() if x.lower() in ('content-encoding', 'content-type') and y.lower().find('gzip')!=-1]: + hreq = gzip.GzipFile(fileobj=hreq) + + return unicode(hreq.read(), 'utf-8', errors = 'replace') + + except urllib2.HTTPError,e: + if args[1] == None: + return None + else: + raise e + +urlrequestpost.registered=True + +def failif(*args): + """ + .. function:: failif(condition [, messsage]) + + If condition is true, raises an error. If message is provided, the message is included in + raised error. + + Examples: + + >>> sql("select failif(1=1,'exception') as answer") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator FAILIF: exception + + >>> sql("select failif(1=0,'exception') as answer") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + answer + ------ + 0 + + >>> sql("select failif(1=1) as answer") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator FAILIF: an error was found + + """ + + if len(args)>3: + raise functions.OperatorError('failif','operator needs one or two input') + + if args[0]: + if len(args)==2: + raise functions.OperatorError('failif', args[1]) + else: + raise functions.OperatorError('failif', 'an error was found') + + return args[0] + +failif.registered=True + +def execprogram(*args): + """ + .. function:: execprogram(stdin=null, program_name, parameters, [raise_error]) -> text or blob + + Function *execprogram* executes a shell command and returns its output. If the + value of the first argument is not *null*, the arguments value will be pushed in program's Standard Input. + + If the program doesn't return a *0* return code, then a madIS error will be raised, containing + the contents of the program's error stream. + + If the last argument of *execprogram* is set to *null*, then all program errors will be returned as *null* + (see "cat non_existent_file" examples below). + + Every one of the program's parameters must be provided as different arguments of the *execprogram* call + (see "cat -n" example below). + + .. note:: + Function *execprogram* tries by default to convert the program's output to UTF-8. If the conversion + isn't succesfull, then it returns the output as a binary blob. + + Examples: + + >>> table1(''' + ... echo test + ... echo 1 + ... ''') + >>> sql("select execprogram(null, a, b) from table1") + execprogram(null, a, b) + ----------------------- + test + 1 + + >>> sql("select execprogram(null, null, '-l')") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator EXECPROGRAM: Second parameter should be the name of the program to run + + >>> sql("select execprogram(null, null, '-l', null)") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + execprogram(null, null, '-l', null) + ----------------------------------- + None + + >>> sql("select execprogram('test', 'cat')") + execprogram('test', 'cat') + -------------------------- + test + + >>> sql('''select execprogram('test', 'cat', '-n')''') #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + execprogram('test', 'cat', '-n') + -------------------------------- + 1 test + + >>> sql("select execprogram(null, 'NON_EXISTENT_PROGRAM')") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator EXECPROGRAM: [Errno 2] No such file or directory + + >>> sql("select execprogram(null, 'cat', 'non_existent_file')") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator EXECPROGRAM: cat: non_existent_file: No such file or directory + + >>> sql("select execprogram(null, 'cat', 'non_existent_file', null)") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + execprogram(null, 'cat', 'non_existent_file', null) + --------------------------------------------------- + None + """ + + if len(args)<2: + raise functions.OperatorError('execprogram', "First parameter should be data to provide to program's STDIN, or null") + + raise_error=False + if len(args)>2 and args[-1]==None: + raise_error=True + + if args[1]==None: + if raise_error: + return None + else: + raise functions.OperatorError('execprogram', "Second parameter should be the name of the program to run") + + outtext=errtext='' + try: + p=subprocess.Popen([unicode(x) for x in args[1:] if x!=None], stdin=subprocess.PIPE if args[0]!=None else None, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + if args[0]==None: + outtext, errtext=p.communicate() + else: + val = args[0] + valtype = type(val) + if valtype == unicode: + val = val.encode('utf-8') + if valtype in (int,float): + val = str(val) + outtext, errtext=p.communicate( val ) + except Exception,e: + raise functions.OperatorError('execprogram', functions.mstr(e)) + + if p.returncode!=0: + if raise_error: + return None + else: + raise functions.OperatorError('execprogram', functions.mstr(errtext).strip()) + + try: + outtext=unicode(outtext, 'utf-8') + except KeyboardInterrupt: + raise + except: + return buffer(outtext) + + return outtext + +execprogram.registered=True + + +def sleep(*args): + """ + .. function:: sleep(seconds) + + This function waits for the given number of seconds before returning. The *seconds* parameters can + be fractional (e.g. *0.1* will sleep for 100 milliseconds). + + Examples: + + >>> sql("select sleep(0.1)") + sleep(0.1) + ---------- + 0.1 + + """ + t = args[0] + if t<0: + t=0 + time.sleep(t) + + return t + +sleep.registered=True + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/row/variables.py b/interactive-mining-3rdparty-madis/madis/src/functions/row/variables.py new file mode 100644 index 0000000..1b69e56 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/row/variables.py @@ -0,0 +1,190 @@ +# coding: utf-8 + +import setpath +import functions +import os + +def var(*args): + + """ + .. function:: var(varname[, value]) -> value + + Sets (if both varname and value are given) or returns (if only varname is given) the contents of a variable. + + Examples: + + >>> sql("var 'v'") # doctest: +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator VAR: Variable 'v' does not exist + >>> sql("var 'v' 5") + var('v','5') + ------------ + 5 + >>> sql("var 'v'") + var('v') + -------- + 5 + >>> sql("select var('v')") + var('v') + -------- + 5 + """ + + if len(args)==0: + return str(functions.variables.__dict__) + + var=args[0] + + if len(args)==1: + if hasattr(functions.variables,var): + return functions.variables.__dict__[var] + else: + raise functions.OperatorError('var', "Variable '" +var+"' does not exist") + elif len(args)==2: + functions.variables.__dict__[var]=args[1] + return functions.variables.__dict__[var] + else: + return None + +var.registered=True + +def getvar(*args): + + """ + .. function:: getvar(varname) -> value + + Returns the value of varname. This function exists so as to be able to force + SQLite's engine to always evaluate the *getvar* function. This can be achieved + by givine to the function an always changing second parameter. + + Examples: + + >>> sql("var 't' 5") + var('t','5') + ------------ + 5 + >>> sql("getvar 't'") + getvar('t') + ----------- + 5 + >>> sql("select getvar('t', random())") + getvar('t', random()) + --------------------- + 5 + """ + + try: + return functions.variables.__dict__[args[0]] + except KeyError: + raise functions.OperatorError('var', "Variable '" +var+"' does not exist") + +getvar.registered=True + +def requirevars(*args): + """ + .. function:: requirevars(varname1, [varname2,...]) + + Checks if all variables (varname1,...) exist. If not it throws an exception. + + Examples: + + >>> sql("var 'cv1' 5") + var('cv1','5') + -------------- + 5 + >>> sql("var 'cv2' 10") + var('cv2','10') + --------------- + 10 + >>> sql("requirevars 'cv1' 'cv2'") + requirevars('cv1','cv2') + ------------------------ + 1 + >>> sql("requirevars cv1 cv2") + requirevars('cv1 cv2') + ---------------------- + 1 + >>> sql("requirevars 'cv1' 'testvar'") # doctest: +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator REQUIREVARS: Variable testvar isn't initialized + """ + + for v in (' '.join(args).strip()).split(): + if not hasattr(functions.variables, v): + raise functions.OperatorError("requirevars","Variable %s isn't initialized"%v) + return 1 + +requirevars.registered=True + +def flowname(*args): + """ + .. function:: flowname([str]) + + Sets and retrieves, 'flowname' variable + + Examples: + + >>> sql("flowname test flow ") + flowname('test flow') + --------------------- + test flow + >>> sql("flowname") + flowname() + ---------- + test flow + >>> sql("flowname 'arg1' arg2") # doctest: +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator FLOWNAME: Flowname accepts only 1 argument + """ + + var='flowname' + if len(args)>1: + raise functions.OperatorError('flowname','Flowname accepts only 1 argument') + + if len(args)==0 and hasattr(functions.variables,var): + return str(functions.variables.__dict__[var]) + elif len(args)==1: + functions.variables.__dict__[var]=' '.join( [str(x) for x in args[0:] ] ) + return str(functions.variables.__dict__[var]) + else: + return None +flowname.registered=True + +def setexecdb(*args): + + """ + .. function:: setexecdb(str) + + Sets the database path/filename for exec operator. + + """ + + var='execdb' + if len(args)==0 and hasattr(functions.variables,var): + return str(functions.variables.__dict__[var]) + else: + functions.variables.__dict__[var]=str(os.path.abspath(os.path.expandvars(os.path.expanduser(os.path.normcase(args[0]))))) + return str(functions.variables.__dict__[var]) + +setexecdb.registered=True + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/setpath.py b/interactive-mining-3rdparty-madis/madis/src/functions/setpath.py new file mode 100644 index 0000000..2c5a314 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/setpath.py @@ -0,0 +1,8 @@ +import sys, os +curmodulepath = os.path.dirname(os.path.abspath(__file__)) + +if hasattr(sys, 'pypy_version_info'): + sys.path.insert(0, os.path.abspath(os.path.join(curmodulepath, '..', 'pypylib'))) + +sys.path.insert(0, os.path.abspath(os.path.join(curmodulepath, '..'))) +sys.path.insert(0, os.path.abspath(os.path.join(curmodulepath, '..', 'lib'))) diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/sqltransform.py b/interactive-mining-3rdparty-madis/madis/src/functions/sqltransform.py new file mode 100644 index 0000000..d6ccdd4 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/sqltransform.py @@ -0,0 +1,517 @@ +# coding: utf-8 + +import setpath +import sqlparse.sql +import sqlparse +import re +from sqlparse.tokens import * +import zlib +import functions + +try: + from collections import OrderedDict +except ImportError: + # Python 2.6 + from lib.collections26 import OrderedDict + +break_inversion_subquery = re.compile(r"""\s*((?:(?:(?:'[^']*?'|\w+:[^\s]+)\s*)*))((?i)of\s|from\s|)(.*?)\s*$""", + re.DOTALL | re.UNICODE) +find_parenthesis = re.compile(r"""\s*\((.*)\)\s*$""", re.DOTALL | re.UNICODE) +viewdetector = re.compile(r'(?i)\s*create\s+(?:temp|temporary)\s+view\s+', re.DOTALL | re.UNICODE) +inlineop = re.compile(r'\s*/\*\*+[\s\n]*((?:def\s+|class\s+).+)[^*]\*\*+/', re.DOTALL | re.UNICODE) + +_statement_cache = OrderedDict() +_statement_cache_size = 1000 + +# delete reserved SQL keywords that collide with our vtables +if __name__ != "__main__": + for i in ['EXECUTE', 'NAMES', 'CACHE', 'EXEC', 'OUTPUT']: + if i in sqlparse.keywords.KEYWORDS: + del sqlparse.keywords.KEYWORDS[i] + + +#Parse comments for inline ops +def opcomments(s): + if r'/**' not in unicode(s): + return [] + + out = [] + constr_comm = None + for i in s.tokens: + ui = unicode(i) + if type(i) == sqlparse.sql.Comment: + op = inlineop.match(ui) + if op != None: + out.append(op.groups()[0]) + + # Construct comment to work around sqlparse bug + if constr_comm is not None: + constr_comm += ui + + if type(i) == sqlparse.sql.Token: + if ui == u'/*': + if constr_comm is not None: + constr_comm = None + else: + constr_comm = u'/*' + elif ui == u'*/': + if constr_comm is not None: + op = inlineop.match(constr_comm) + if op != None: + out.append(op.groups()[0]) + constr_comm = None + return out + + +#Top level transform (runs once) +def transform(query, multiset_functions=None, vtables=[], row_functions=[], substitute=lambda x: x): + if type(query) not in (str, unicode): + return (query, [], []) + + s = query + subsquery = substitute(s) + + # Check cache + if subsquery in _statement_cache: + return _statement_cache[subsquery] + + enableInlineops = False + if r'/**' in subsquery: + enableInlineops = True + + out_vtables = [] + + st = sqlparse.parse(subsquery) + + trans = Transclass(multiset_functions, vtables, row_functions) + s_out = '' + sqp = ('', [], []) + inlineops = [] + + for s in st: + # delete question mark + strs = re.match(r"(.*?);*\s*$", unicode(s), re.DOTALL | re.UNICODE).groups()[0] + st1 = sqlparse.parse(strs) + if len(st1) > 0: + if enableInlineops: + inlineops.append(opcomments(st1[0])) + sqp = trans.rectransform(st1[0]) + strs = unicode(sqp[0]) + s_out += strs + s_out += ';' + + # Detect create temp view and mark its vtables as permanent + if viewdetector.match(strs): + out_vtables += [x + (False,) for x in sqp[1]] + else: + out_vtables += sqp[1] + + result = (s_out, vt_distinct(out_vtables), sqp[2], inlineops) + + if len(_statement_cache) < _statement_cache_size: + _statement_cache[subsquery] = result + else: + _statement_cache.popitem(last=False) + _statement_cache[subsquery] = result + return result + + +class Transclass: + direct_exec = [] + multiset_functions = None + vtables = [] + row_functions = [] + + def __init__(self, multiset_functions=None, vtables=[], row_functions=[]): + self.direct_exec = [] + self.multiset_functions = multiset_functions + self.vtables = vtables + self.row_functions = row_functions + + #recursive transform + def rectransform(self, s, s_orig=None): + if not (re.search(ur'(?i)(select|' + '|'.join([x for x in self.vtables]) + '|' + '|'.join( + self.multiset_functions) + '|' + '|'.join(self.row_functions) + ')', unicode(s), re.UNICODE)): + return unicode(s), [], self.direct_exec + + out_vtables = [] + + if s_orig is None: + s_orig = s + + query = None + + # Expand functions with spaces between them and their parenthesis + for t in s_orig.tokens: + tfm = re.match('(\w+)\s\(', unicode(t), re.UNICODE) + if isinstance(t, sqlparse.sql.Function) and tfm and ( + tfm.groups()[0] in self.vtables or tfm.groups()[0] in self.row_functions): + tidx = s_orig.token_index(t) + s_orig.tokens[tidx:tidx + 1] = t.tokens + + fs = [x for x in expand_tokens(s)] + + # Process external_query VTs + tmatch = re.match(r'\s*(\w+)\s+(.*|$)', unicode(s), re.DOTALL | re.UNICODE) + if tmatch is not None and tmatch.groups()[0].lower() in self.vtables: + op_for_inv = tmatch.groups()[0].lower() + if hasattr(self.vtables[op_for_inv], 'external_query'): + rest = tmatch.groups()[1] + op_for_inv = unicode(op_for_inv) + params, preposition, subq = break_inversion_subquery.match(rest).groups() + if subq != '': + paramslist = [format_query(subq)] + else: + paramslist = [] + paramslist += [format_param(''.join(x)) for x in + re.findall(r"'([^']*?)'|(\w+:[^\s]+)", params, re.UNICODE)] + inv_s = ','.join(paramslist) + vname = vt_name(op_for_inv) + self.direct_exec += [(op_for_inv, paramslist, subq)] + s_orig.tokens[s_orig.token_index(s.tokens[0]):s_orig.token_index(s.tokens[-1]) + 1] = [sqlparse.sql.Token(Token.Keyword, 'select * from ' + vname + ' ')] + return unicode(s), vt_distinct([(vname, op_for_inv, inv_s)]), self.direct_exec + + # Process internal parenthesis + for t in fs: + if type(t) is sqlparse.sql.Parenthesis: + subq = find_parenthesis.match(unicode(t)) + if subq != None: + subq = subq.groups()[0] + t.tokens = sqlparse.parse(subq)[0].tokens + out_vtables += self.rectransform(t)[1] + t.tokens[0:0] = [sqlparse.sql.Token(Token.Punctuation, '(')] + t.tokens.append(sqlparse.sql.Token(Token.Punctuation, ')')) + + # Process Inversions + + #Process direct row inversion + t = re.match(r'\s*(\w+)(\s+.*|$)', unicode(s), re.DOTALL | re.UNICODE) + if t != None and t.groups()[0].lower() in self.row_functions: + op_for_inv = t.groups()[0] + rest = t.groups()[1] + params, preposition, subq = break_inversion_subquery.match(rest).groups() + paramslist = [format_param(''.join(x)) for x in re.findall(r"'([^']*?)'|(\w+:[^\s]+)", params, re.UNICODE)] + if subq != '': + if len(preposition) > 0: + subq, v, dv = self.rectransform(sqlparse.parse(subq)[0]) + out_vtables += v + paramslist += ['(' + subq + ')'] + else: + paramslist += [format_param(subq)] + inv_s = 'SELECT ' + op_for_inv + '(' + ','.join(paramslist) + ')' + subs = sqlparse.parse(inv_s)[0] + s_orig.tokens[s_orig.token_index(s.tokens[0]):s_orig.token_index(s.tokens[-1]) + 1] = subs.tokens + s = subs + + fs = [x for x in expand_tokens(s)] + + # Process vtable inversion + for t in fs: + if t.ttype == Token.Keyword.DML: + break + strt = unicode(t).lower() + if strt in self.vtables: + #print "FOUND INVERSION:", strt, fs + tindex = fs.index(t) + # Break if '.' exists before vtable + if tindex > 0 and unicode(fs[tindex - 1]) == '.': + break + op_for_inv = strt + try: + rest = ''.join([unicode(x) for x in fs[tindex + 1:]]) + except KeyboardInterrupt: + raise + except: + rest = '' + params, preposition, subq = break_inversion_subquery.match(rest).groups() + orig_subq = subq + if subq != '': + subq, v, dv = self.rectransform(sqlparse.parse(subq)[0]) + out_vtables += v + if not hasattr(self.vtables[strt], 'external_stream'): + if subq != '': + paramslist = [format_query(subq)] + else: + paramslist = [] + paramslist += [format_param(''.join(x)) for x in + re.findall(r"'([^']*?)'|(\w+:[^\s]+)", params, re.UNICODE)] + inv_s = ''.join( + [unicode(x) for x in fs[:fs.index(t)]]) + 'SELECT * FROM ' + op_for_inv + '(' + ','.join( + paramslist) + ')' + else: + paramslist = [format_param(''.join(x)) for x in + re.findall(r"'([^']*?)'|(\w+:[^\s]+)", params, re.UNICODE)] + inv_s = ''.join( + [unicode(x) for x in fs[:fs.index(t)]]) + 'SELECT * FROM ' + op_for_inv + '(' + ','.join( + paramslist) + ') ' + subq + subs = sqlparse.parse(inv_s)[0] + self.direct_exec += [(op_for_inv, paramslist, orig_subq)] + s_orig.tokens[s_orig.token_index(s.tokens[0]):s_orig.token_index(s.tokens[-1]) + 1] = subs.tokens + s = subs + break + + # find first select + s_start = s.token_next_match(0, Token.Keyword.DML, r'(?i)select', True) + if s_start is not None: + # find keyword that ends substatement + s_end = s.token_next_match(s.token_index(s_start), Token.Keyword, ( + r'(?i)union', r'(?i)order', r'(?i)limit', r'(?i)intersect', r'(?i)except', r'(?i)having'), True) + if len(s.tokens) < 3: + return unicode(s), vt_distinct(out_vtables), self.direct_exec + if s_end is None: + if s.tokens[-1].value == ')': + s_end = s.tokens[-2] + else: + s_end = s.tokens[-1] + else: + if s.token_index(s_end) + 1 >= len(s.tokens): + raise functions.MadisError("'" + unicode(s_end).upper() + "' should be followed by something") + out_vtables += self.rectransform( + sqlparse.sql.Statement(s.tokens_between(s.tokens[s.token_index(s_end) + 1], s.tokens[-1])), s)[1] + s_end = s.tokens[s.token_index(s_end) - 1] + query = sqlparse.sql.Statement(s.tokens_between(s_start, s_end)) + else: + return unicode(s), vt_distinct(out_vtables), self.direct_exec + + # find from and select_parameters range + from_range = None + from_start = query.token_next_match(0, Token.Keyword, r'(?i)from', True) + + # process virtual tables in from range + if from_start is not None: + from_end = query.token_next_by_instance(query.token_index(from_start), sqlparse.sql.Where) + if from_start == query.tokens[-1]: + raise functions.MadisError("Error in FROM range of: '" + str(query) + "'") + if from_end is None: + from_end = query.tokens[-1] + from_range = sqlparse.sql.Statement( + query.tokens_between(query.tokens[query.token_index(from_start) + 1], from_end)) + else: + from_range = sqlparse.sql.Statement( + query.tokens_between(query.tokens[query.token_index(from_start) + 1], from_end, exclude_end=True)) + for t in [x for x in expand_type(from_range, (sqlparse.sql.Identifier, sqlparse.sql.IdentifierList))]: + if unicode(t).lower() in ('group', 'order'): + break + if type(t) is sqlparse.sql.Function: + vname = vt_name(unicode(t)) + fname = t.tokens[0].get_real_name().lower() + if fname in self.vtables: + out_vtables += [(vname, fname, unicode(t.tokens[1])[1:-1])] + t.tokens = [sqlparse.sql.Token(Token.Keyword, vname)] + else: + raise functions.MadisError("Virtual table '" + fname + "' does not exist") + + if from_start is not None: + select_range = sqlparse.sql.Statement(query.tokens_between(query.tokens[1], from_start, exclude_end=True)) + else: + select_range = sqlparse.sql.Statement(query.tokens_between(query.tokens[1], query.tokens[-1])) + + # Process EXPAND functions + for t in flatten_with_type(select_range, sqlparse.sql.Function): + if hasattr(t.tokens[0], 'get_real_name'): + fname = t.tokens[0].get_real_name() + else: + fname = unicode(t.tokens[0]) + fname = fname.lower().strip() + if fname in self.multiset_functions: + t = s_orig.group_tokens(sqlparse.sql.Parenthesis, s_orig.tokens_between(s_start, s_end)) + vname = vt_name(unicode(t)) + out_vtables += [(vname, 'expand', format_query(t))] + s_orig.tokens[s_orig.token_index(t)] = sqlparse.sql.Token(Token.Keyword, 'select * from ' + vname + ' ') + break + + return unicode(s), vt_distinct(out_vtables), self.direct_exec + + +def vt_name(s): + tmp = re.sub(r'([^\w])', '_', 'vt_' + unicode(zlib.crc32(s.encode('utf-8'))), re.UNICODE) + return re.sub(r'_+', '_', tmp, re.UNICODE) + + +def format_query(s): + q = "'query:" + unicode(s).replace("'", "''") + "'" + q = q.replace('\n', ' ') + return q + + +def format_param(s): + return "'" + unicode(s).replace("'", "''") + "'" + + +def format_identifiers(s): + return unicode(s).replace(' ', '').replace('\t', '') + + +def flatten_with_type(inpt, clss): + """Generator yielding ungrouped tokens. + + This method is recursively called for all child tokens. + """ + for token in inpt.tokens: + if isinstance(token, clss): + yield token + else: + if token.is_group() or type(token) is sqlparse.sql.Parenthesis: + for i in flatten_with_type(token, clss): + yield i + + +def expand_type(inpt, clss): + """Generator yielding ungrouped tokens. + + This method is recursively called for all child tokens. + """ + for token in inpt.tokens: + if token.is_group() and isinstance(token, clss): + for i in expand_type(token, clss): + yield i + else: + yield token + + +def expand_tokens(inpt): + """Generator yielding ungrouped tokens. + + This method is recursively called for all child tokens. + """ + for token in inpt.tokens: + if (token.is_group() and isinstance(token, ( + sqlparse.sql.Identifier, sqlparse.sql.IdentifierList, sqlparse.sql.Where))): + for i in expand_tokens(token): + yield i + else: + yield token + + +def vt_distinct(vt): + vtout = OrderedDict() + for i in vt: + if i[0] not in vtout: + vtout[i[0]] = i + else: + if not vtout[i[0]][-1] == False: + vtout[i[0]] = i + + return vtout.values() + + +if __name__ == "__main__": + + sql = [] + multiset_functions = ['nnfunc1', 'nnfunc2', 'apriori', 'ontop', 'strsplit'] + + def file(): + pass + + file.external_stream = True + + def execv(): + pass + + execv.no_results = True + + vtables = {'file': file, 'lnf': True, 'funlalakis': True, 'filela': True, 'sendto': True, 'helpvt': True, + 'output': True, 'names': True, 'cache': True, 'testvt': True, 'exec': execv, 'flow': True} + row_functions = ['help', 'set', 'execute', 'var', 'toggle', 'strsplit', 'min', 'ifthenelse', 'keywords'] + + sql += ["select a,b,(apriori(a,b,c,'fala:a')) from lalatable"] + sql += ["create table a from select a,b,(apriori(a,b,c,'fala:a')) from lalatable, lala14, lala15"] + sql += ["create table a from select a,b,(apriori(a,b,c,'fala:a')) from lalatable, lala14, lala15"] + sql += ["select a,b,(apriori(a,b,c,'fala:a')) from lalatable where a=15 and b=23 and c=(1234)"] + sql += ["select a,b,(apriori(a,b,c,'fala:a')) from lalatable where a=15 and b=23 and c=(1234) group by a order by"] + sql += [ + "select a,b,(apriori(a,b,c,'fala:a')) from ('asdfadsf') where a=15 and b=23 and c=(1234) group by a order by"] + sql += [ + "select a,b,(apriori(a,b,c,'fala:a')) from ('asdfadsf') where a=15 and b=23 and c=(1234) group by a order by b union select a,b from funlalakis('1234'), (select a from lnf('1234') )"] + sql += ["select c1,c2 from file('test.tsv', 'param1');select a from filela('test.tsv') group by la"] + sql += ['insert into la values(1,2,3,4)'] + sql += ["select apriori(a) from (select apriori('b') from table2)"] + sql += [ + "select userid, top1, top2 from (select userid,ontop(3,preference,collid,preference) from colpreferences group by userid)order by top2 ; "] + sql += ["select ontop(a), apriori(b) from lala"] + sql += ["select ontop(a) from (select apriori(b) from table) order by a"] + sql += [ + "select userid,ontop(3,preference,collid,preference),ontop(1,preference,collid) from colpreferences group by userid;"] + sql += ["create table lala as select apriori(a) from table;"] + sql += [ + "create table lila as select userid,ontop(3,preference,collid,preference),ontop(1,preference,collid) from colpreferences group by userid; "] + sql += ["select * from file(test.txt)"] + sql += ["select sum(b) from test_table group by a pivot b,c"] + sql += ["select * from (helpvt lala)"] + sql += ["output 'list'"] + sql += ["(help lala)"] + sql += [r"select * from tab1 union help 'lala'"] + sql += [r"select * from file('list'),(select * from file('list'))"] + sql += [r"create table ta as help list"] + sql += [r"select * from (help lala)"] + sql += [r"output 'lala' select apriori(a,b) from extable"] + sql += [r"select apriori(a,b) from extable"] + sql += [r"select * from file('/lala','param1:t')"] + sql += [r"output '/lala' 'param1' select * from tab"] + sql += [r"select apriori(a,b) from file(/lala/lalakis)"] + sql += ["(select a from (sendto 'fileout.lala' 'tsv' select * from file('file.lala')))"] + sql += ["sendto 'lala1' sendto 'fileout.lala' 'tsv' select * from file('file.lala'))"] + sql += ["help 'lala'"] + sql += ["names file 'lala'; helpvt lala"] + sql += [r"select * from file() as a, file() as b;"] + sql += [r"select file from (file 'alla) as lala"] + sql += [r" .help select * from file('lsls')"] + sql += [r" .execute select * from file('lsls')"] + sql += [r"limit 1"] + sql += [r"file 'lala'"] + sql += [r"select * from lala union file 'lala' union file 'lala'"] + sql += [r"file 'lala' limit 1"] + sql += [r"create table lala file 'lala'"] + sql += [r"SELECT * FROM (file 'lala')"] + sql += [r"(file 'lala') union (file 'lala1')"] + sql += [r"select (5+5) from (file 'lala1')"] + sql += [ + r"select * from ( output 'bla' select * from file('collection-general.csv','dialect:line') where rowid!=1 ) "] + sql += [r"select * from testtable where x not in (file 'lalakis')"] + #sql+=[r".help ασδαδδ"] + sql += [r"names (file 'testfile')"] + #sql+=[r"select * from (select lala from table limit)"] + sql += [r"""create table session_to_country( + sesid text NOT NULL primary key, + geoip_ccode text +); """] + sql += [r"""create table ip_country as select iplong,CC from (cache select cast(C3 as integer) as ipfrom,cast(C4 as +integer) as ipto, C5 as CC from file('file:GeoIPCountryCSV_09_2007.zip','compression:t','dialect:csv') ),tmpdistlong +where iplong>=ipfrom and iplong <=ipto; +"""] + sql += [r"cache select * from lala;"] + sql += [r"var 'lala' from var 'lala1'"] + sql += [r"toggle tracing"] + sql += [r"select strsplit('8,9','dialect:csv')"] + sql += [r"testvt"] + sql += [r"select date('now')"] + sql += [r"exec select * from lala"] + sql += [r"var 'usercc' from select min(grade) from (testvt) where grade>5;"] + sql += [r"var 'usercc' from select 5;"] + sql += [r"(exec flow file 'lala' 'lala1' asdfasdf:asdfdsaf);"] + sql += [ + r"UPDATE merged_similarity SET merged_similarity = ((ifthenelse(colsim,colsim,0)*0.3)+(ifthenelse(colsim,colsim,0)*0.3))"] + sql += [r"toggle tracing ;"] + sql += [r"select sesid, query from tac group by sesid having keywords('query')='lala'"] + sql += [ + r"select sesid, query from tac group by sesid having keywords('query')='lala' union select * from file('lala')"] + sql += [r"select * from (select 5 as a) where a=4 or (a=5 and a not in (select 3));"] + sql += [r"select * from a where ((a.r in (select c1 from f)));"] + sql += [r"select upper(a.output) from a"] + sql += [r"select upper(execute) from a"] + sql += [r"exec select a.5 from (flow file 'lala')"] + sql += [r"select max( (select 5))"] + sql += [r"cache select 5; create temp view as cache select 7; cache select 7"] + sql += [r"select * from /** def lala(x): pass **/ tab"] + sql += [r"select * from /* def lala(x): pass **/ tab"] + sql += [r"/** def lala():return 6 **/ \n"] + sql += [r"/** def lala():return 6 **/ "] + + for s in sql: + print "====== " + unicode(s) + " ===========" + a = transform(s, multiset_functions, vtables, row_functions) + print "Query In:", s + print "Query Out:", a[0].encode('utf-8') + print "Vtables:", a[1] + print "Direct exec:", a[2] + print "Inline Ops:", a[3] \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/__init__.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/cache.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/cache.py new file mode 100644 index 0000000..f1e574e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/cache.py @@ -0,0 +1,335 @@ +""" +.. function:: cache(query:None) -> [the same schema as input query] + +Caches and indexes in memory the input query. Its output has exactly the same schema as +the input query. + +Examples: + +.. doctest:: + >>> table1(''' + ... 1 2 + ... 3 4 + ... 5 6 + ... 7 8 + ... 10 1 + ... ''') + + >>> sql("select * from (cache select * from table1) order by a desc,b asc") + a | b + ------ + 10 | 1 + 7 | 8 + 5 | 6 + 3 | 4 + 1 | 2 + + >>> sql("select * from (cache select * from table1) where a=b") + + >>> table2(''' + ... 5 1 + ... 5 2 + ... 5 3 + ... 2 3 + ... 2 2 + ... 2 1 + ... ''') + + >>> sql("select * from (cache select * from table2) where b>=2 order by a desc,b desc") + a | b + ----- + 5 | 3 + 5 | 2 + 2 | 3 + 2 | 2 + + >>> sql("select * from (cache select * from table2) where 3>=a and 3<=b") + a | b + ----- + 2 | 3 + + +.. seealso:: + + * :ref:`tutcache` + +""" + +registered=True + +import setpath +import functions +import apsw +import itertools +import operator +from lib import argsparse +from lib import kdtree +from lib import schemaUtils +import json + +constraints={ +2:'SQLITE_INDEX_CONSTRAINT_EQ', +32:'SQLITE_INDEX_CONSTRAINT_GE', +4:'SQLITE_INDEX_CONSTRAINT_GT', +8:'SQLITE_INDEX_CONSTRAINT_LE', +16:'SQLITE_INDEX_CONSTRAINT_LT', +64:'SQLITE_INDEX_CONSTRAINT_MATCH' +} + + +# Decorator to extended a function by calling first another function with no arguments + +def echocall(func): + def wrapper(*args, **kw): + obj=args[0] + Extra="" + if 'tablename' in obj.__dict__: + Extra=obj.tablename + if functions.settings['vtdebug']: + print "Table %s:Before Calling %s.%s(%s)" %(Extra+str(obj),obj.__class__.__name__,func.__name__,','.join([repr(l) for l in args[1:]]+["%s=%s" %(k,repr(v)) for k,v in kw.items()])) + aftermsg="Table %s:After Calling %s.%s(%s)" %(Extra,obj.__class__.__name__,func.__name__,','.join([repr(l) for l in args[1:]]+["%s=%s" %(k,repr(v)) for k,v in kw.items()])) + a=func(*args, **kw) + if functions.settings['vtdebug']: + pass + #print aftermsg + return a + #return func(*args, **kw) + return wrapper + + +class Source: + def __init__(self,boolargs=[],nonstringargs=dict(),needsescape=[]): + self.tableObjs=dict() + self.boolargs=boolargs + self.nonstringargs=nonstringargs + self.needsescape=needsescape + @echocall + def Create(self, db, modulename, dbname, tablename,*args): + + dictargs={'tablename':tablename,'db':db,'dbname':dbname,'modulename':modulename} + self.tableObjs[tablename]=LTable(self.tableObjs,self.boolargs,self.nonstringargs,self.needsescape,*args,**dictargs) + return [self.tableObjs[tablename].getschema(),self.tableObjs[tablename]] + @echocall + def Connect(self, db, modulename, dbname, tablename,*args): + if tablename not in self.tableObjs: + return Create(self, db, modulename, dbname, tablename,*args) + return [self.tableObjs[tablename].getschema(),self.tableObjs[tablename]] + +class LTable: ####Init means setschema and execstatus + autostring='automatic_vtable' + @echocall + def __init__(self,tblist,boolargs,nonstringargs,needsescape,*args,**envars): # envars tablename, auto , OPTIONAL [] + self.delayedexception=None + self.tblist=tblist + self.auto=False + self.first=True + self.schema="create table %s('Error')" % (envars['tablename']) + self.tablename=envars['tablename'] + self.description=None + self.consdict={} + self.coldata=[] + self.rowids=[] + self.kdindex=None + self.lastcalculatedidx=None + self.ordered=False + + largs, kargs = [] ,dict() + try: + largs, kargs = argsparse.parse(args,boolargs,nonstringargs,needsescape) + except Exception,e: + raise functions.MadisError(e) + try: + q=envars['db'].cursor().execute(kargs['query']) + self.description=q.getdescription() + except apsw.ExecutionCompleteError: + raise functions.DynamicSchemaWithEmptyResultError(__name__.rsplit('.')[-1]) + + self._setschema() + + self.data = [] + ro = [] + dedupl = {} + for r in q: + ro = [] + for i in r: + if i not in dedupl: + dedupl[i] = i + ro.append(i) + else: + ro.append(dedupl[i]) + + self.data.append(tuple(ro)) + + del(dedupl) + + + @echocall + def _setschema(self): + descr=self.description ### get list of tuples columnname, type + self.schema=schemaUtils.CreateStatement(descr, self.tablename) + + @echocall + def getschema(self): + if functions.settings['tracing']: + print "VT schema:%s" %(self.schema) + return self.schema + + @echocall + def BestIndex(self, constraint_param, orderbys): + indexes = [] + newcons = [] + i = 0 + + for c in constraint_param: + if c[1] == apsw.SQLITE_INDEX_CONSTRAINT_MATCH: + indexes.append(None) + else: + indexes.append((i, True)) + i += 1 + newcons.append(c) + + consname = json.dumps(newcons, separators=(',', ':')) + json.dumps(orderbys, separators=(',', ':')) + self.consdict[consname] = (newcons, orderbys) + cost = 0 + + # Cost of scan + if newcons == []: + cost = len(self.data) + + return indexes, 0, consname, True, cost + + @echocall + def Open(self): + return Cursor(self) + + @echocall + def Disconnect(self): + pass + + @echocall + def Destroy(self): + """ + This method is called when the table is no longer used + """ + del(self.data) + del(self.kdindex) + del(self.tblist[self.tablename]) + +# Represents a cursor +class Cursor: + def __init__(self, table): + self.table=table + self.eof=True + self.pos=0 + self.row=[] + + # @echocall #-- Commented out for speed reasons + def Filter(self, indexnum, indexname, constraintargs): + self.eof=False + constraints, orderbys = self.table.consdict[indexname] + + if self.table.lastcalculatedidx!=(constraints,orderbys): + self.calculate_indexes(constraints,orderbys) + self.table.lastcalculatedidx=(constraints,orderbys) + + if len(constraints)==0: + self.resultrows=iter(self.table.data) + else: + self.resultrows=kdtree.query(self.table.kdindex, constraints, constraintargs) + if self.table.ordered: + self.resultrows=iter(sorted(list(self.resultrows),key=operator.itemgetter(self.table.orderindex) )) + + try: + self.row=self.resultrows.next() + except KeyboardInterrupt: + raise + except: + self.eof=True + +# @echocall #-- Commented out for speed reasons + def Eof(self): + return self.eof + +# @echocall #-- Commented out for speed reasons + def Rowid(self): + return self.pos + +# @echocall #-- Commented out for speed reasons + def Column(self, col): + return self.row[col] + +# @echocall #-- Commented out for speed reasons + def Next(self): + try: + self.row=self.resultrows.next() + except KeyboardInterrupt: + raise + except: + self.eof=True + + @echocall + def Close(self): + del(self.resultrows) + + def calculate_indexes(self,cons,orderbys): + self.table.ordered=False + if len(orderbys)!=0 and len(self.table.data)!=0: + self.table.ordered=True + self.table.orderindex=len(self.table.data[0]) + for o in reversed(orderbys): + self.table.data.sort(key=operator.itemgetter(o[0]),reverse=o[1]) + self.table.data=[x+(y,) for x,y in itertools.izip(self.table.data,itertools.count())] + + idxs=[x[0] for x in cons] + self.table.kdindex=kdtree.kdtree(self.table.data, idxs) + +import re +onlyalphnum=re.compile(ur'[a-zA-Z]\w*$') + +def schemastr(tablename,colnames,typenames=None): + stripedcolnames=[el if onlyalphnum.match(el) else '"'+el.replace('"','""')+'"' for el in colnames] + if not typenames: + return "create table %s(%s)" %(tablename,','.join(['"'+str(c)+'"' for c in unify(stripedcolnames)])) + else: + stripedtypenames=['' if el=="None" else el if onlyalphnum.match(el) else '"'+el.replace('"','""')+'"' for el in typenames] + return "create table %s(%s)" %(tablename,','.join([str(c)+' '+str(t) for c,t in zip(unify(stripedcolnames),stripedtypenames)])) + +def unify(slist): + if len(set(slist))==len(slist): + return slist + eldict={} + for s in slist: + if s in eldict: + eldict[s]+=1 + else: + eldict[s]=1 + for val,fr in eldict.items(): + if fr==1: + del eldict[val] + for val in eldict: + eldict[val]=1 + uniquelist=[] + for s in slist: + if s in eldict: + uniquelist+=[s+str(eldict[s])] + eldict[s]+=1 + else: + uniquelist+=[s] + + return uniquelist + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/clipboard.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/clipboard.py new file mode 100644 index 0000000..fbb0ab8 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/clipboard.py @@ -0,0 +1,133 @@ +""" +.. function:: clipboard() + +Returns the contents of the system's clipboard. If the clipboard's contents are guessed to be a table, then it automatically splits the contents in its output. + +:h: + if the 'h' option is provided to *clipboard()* function, the first row of the clipboard's data is regarded as the schema of the data. + +:Returned table schema: + Column names start from C1... , all column types are text + +Examples: + + >>> sql("select * from clipboard()") + C1 | C2 | C3 | C4 + ------------------------------------------------------ + 1 | Zimbabwe | 304.30 | 2009 est. + 2 | Japan | 192.10 | 2009 est. + 3 | Saint Kitts and Nevis | 185.00 | 2009 est. + +""" +import vtbase + +registered=True +external_stream=True + +class clipboard(vtbase.VT): + def __init__(self): + self.schema=[('C1', 'text')] + self.count = None + + def checkfordelimiter(self, delim = '\t'): + #check for regular schema + hasschema=True + self.count=0 + if len(self.data)>0: + self.count = self.data[0].count(delim) + if self.count==0: + hasschema=False + else: + for i in self.data[1:]: + if i.count(delim) != self.count: + hasschema=False + break + return hasschema + + def VTiter(self, *parsedArgs, **envars): + largs, dictargs = self.full_parse(parsedArgs) + import lib.pyperclip as clip + data=unicode(clip.getcb(), 'utf_8') + + if data.count('\n')>=data.count('\r'): + data=data.split('\n') + else: + data=data.split('\r') + + #delete empty lines from the end + for i in xrange(len(data)-1,-1,-1): + if len(data[i])==0: + del data[i] + else: + break + + self.data = data + delim = None + + if 'delimiter' in dictargs: + delim = dictargs['delimiter'] + + if delim == r'\t': + delim = '\t' + + if delim == '': + delim = None + + else: + if self.checkfordelimiter('\t'): + delim = '\t' + elif self.checkfordelimiter(','): + delim = ',' + elif self.checkfordelimiter(';'): + delim = ';' + elif self.checkfordelimiter(':'): + delim = ':' + elif self.checkfordelimiter(' ') and len(data)>1: + delim = ' ' + + if delim != None: + data=[[x.strip() for x in i.split(delim)] for i in data] + self.schema = None + header = False + + # Check for header directive + for i in parsedArgs: + if i.startswith('h'): + header = True + + if header and len(data)>0: + self.schema = [(c,'text') for c in data[0]] + data = data[1:] + else: + if self.count == None: + count = len(data[0]) + 1 + else: + count = self.count + 2 + + self.schema=[('C'+str(i),'text') for i in xrange(1, count)] + else: + data = [[r.strip()] for r in data] + + yield self.schema + + for r in data: + yield r + +def Source(): + return vtbase.VTGenerator(clipboard) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/clipout.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/clipout.py new file mode 100644 index 0000000..20a6114 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/clipout.py @@ -0,0 +1,71 @@ +""" +.. function:: clipout([h:0], query:None) + +Writes to clipboard the output of *query*. The clipboard contents will be tab delimited. + +:header option: + + if an 'h' or h:1 option is found then it also exports the schema of the query. + +:Returned table schema: + - *return_value* int + Boolean value 1 indicating success. On failure an exception is thrown. + +Examples: + + >>> sql("clipout select 5,6") + return_value + ------------ + 1 +""" + +import setpath +from vtout import SourceNtoOne +import os +import functions + +registered=True + +def Clipout(diter, schema, *args, **kargs): + import lib.pyperclip as clip + a=[] + + exportheader=False + + for i in args: + if i.startswith('h'): + exportheader=True + + for i in kargs: + if i.startswith('h'): + exportheader=True + + if exportheader==True: + a.append(u'\t'.join([unicode(i[0]).replace('\t',' ').replace('\n',' ') for i in schema]).encode('utf_8', 'replace')) + exportheader=False + + for row in diter: + a.append(u'\t'.join([unicode(i).replace('\t',' ').replace('\n',' ') for i in row]).encode('utf_8', 'replace')) + + if os.name == 'nt': + clip.setcb(functions.mstr('\n'.join(a))) + else: + clip.setcb('\n'.join(a)) + +def Source(): + return SourceNtoOne(Clipout) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/coltypes.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/coltypes.py new file mode 100644 index 0000000..f08ff63 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/coltypes.py @@ -0,0 +1,83 @@ +""" +.. function:: coltypes(query:None) + +Returns the input query results column names and types. + +:Returned table schema: + - *column* text + Column name of input query *schema* + - *type* text + Type of column + +Examples: + + >>> sql("coltypes select 5 as vt") + column | type + ------------- + vt | None + +Applying coltypes in the result of virtual table func:`typing` function in the same query + + >>> sql("coltypes typing 'vt:int' select 5 as vt") + column | type + ------------- + vt | int + +.. doctest:: + :hide: + + >>> sql("select * from (coltypes typing 'text' select '10' ) as a, (coltypes typing 'int' select '10' ) as b where a.column=b.column") + column | type | column | type + ----------------------------- + '10' | text | '10' | int +""" + +import setpath +import vtbase +import functions + +registered=True + +class ColTypes(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + largs, dictargs = self.full_parse(parsedArgs) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No query argument ") + + query=dictargs['query'] + connection=envars['db'] + + yield (('column', 'text'), ('type', 'text')) + + cur=connection.cursor() + execit=cur.execute(query, parse = False) + try: + samplerow=execit.next() + except StopIteration: + pass + + vals=cur.getdescriptionsafe() + cur.close() + + for i in vals: + yield i + +def Source(): + return vtbase.VTGenerator(ColTypes) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/continue.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/continue.py new file mode 100644 index 0000000..591b77a --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/continue.py @@ -0,0 +1,48 @@ +""" +One to N operator continue +This functions executes a query that is given as a parameter and returns 1 +if the execution succeds or 0 if the execution fails + + >>> #sql("continue select 5") + return_value + ------------ + 1 + >>> #sql("continue lalakis") + return_value + ------------ + 0 +""" + +import setpath #for importing from project root directory KEEP IT IN FIRST LINE +from vtout import SourceNtoOne +import functions + + #UNCOMMENT TO REGISTER THE N to 1 OPERATOR +registered=False + +def execontinue(diter, schema, *args,**kargs): + if args or kargs: + raise functions.OperatorError(__name__.rsplit('.')[-1],"operator takes no arguments") + + for el in diter: + pass + pass + +def Source(): + + return SourceNtoOne(execontinue,retalways=True) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/coutput.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/coutput.py new file mode 100644 index 0000000..07267da --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/coutput.py @@ -0,0 +1,576 @@ +""" +Examples: + + >>> table1(''' + ... James 10 2 + ... Mark 7 3 + ... Lila 74 1 + ... ''') + >>> sql("select * from table1") + a | b | c + -------------- + James | 10 | 2 + Mark | 7 | 3 + Lila | 74 | 1 + + >>> sql("coutput '../../tests/output' split:2 mode:rcfile select hashmodarchdep(rank,2),* from (select a as name , b as age, c as rank from table1)") + return_value + ------------ + 1 + >>> sql("unionallrcfiles file:../../tests/output") + name | age | rank + ------------------ + Mark | 7 | 3 + Lila | 74 | 1 + James | 10 | 2 + + >>> sql("coutput '../../tests/emptyoutput' split:2 mode:rcfile select hashmodarchdep(rank,2),* from (select a as name , b as age, c as rank from table1 limit 0)") + return_value + ------------ + 1 + >>> sql("unionallrcfiles file:../../tests/emptyoutput") + + + >>> sql("coutput '../../tests/outputsp8' split:8 mode:rcfile select hashmodarchdep(rank,8),* from (select a as name , b as age, c as rank from table1)") + return_value + ------------ + 1 + >>> sql("unionallrcfiles file:../../tests/outputsp8") + name | age | rank + ------------------ + James | 10 | 2 + Mark | 7 | 3 + Lila | 74 | 1 +""" + + +import os.path +import sys +from vtout import SourceNtoOne +import functions +import lib.inoutparsing +import os +from itertools import izip , imap +import itertools +import cPickle as cPickle +import struct +import gc +import StringIO as StringIO +import cStringIO as cStringIO +import marshal +import zlib +from array import array + + + + +BLOCK_SIZE = 65536000 +ZLIB = "zlib" +BZ2 = "bzip" +RCFILE=1 +SDC=2 +SPAC=3 +registered=True + +def getSize(v): + t = type(v) + + if t == unicode: + return 52 + 4*len(v) + + if t in (int, float, None): + return 24 + + return 37 + len(v) + +def outputData(diter, schema, connection, *args, **formatArgs): + import bz2 + import msgpack + serializer = msgpack + ### Parameter handling ### + where=None + mode = 'sdc' + compression = 'zlib' + level = 2 + split = 0 + if 'split' in formatArgs: + split = 1 + if len(args)>0: + where=args[0] + elif 'file' in formatArgs: + where=formatArgs['file'] + else: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No destination provided") + if 'file' in formatArgs: + del formatArgs['file'] + if 'mode' in formatArgs: + mode = formatArgs['mode'] + if 'compr' in formatArgs: + if formatArgs['compr'] == "zlib": + compression = ZLIB + elif formatArgs['compr'] == "bz2": + compression = BZ2 + else: + raise functions.OperatorError(__name__.rsplit('.')[-1],"Wrong compression algorithm provided. Choose between zlib or bz2") + + if 'level' in formatArgs: + l = formatArgs['level'] + try: + if int(l)>=0 and int(l) <=9 : + level = int(l) + else : + raise functions.OperatorError(__name__.rsplit('.')[-1],"Compression level should range from 0 to 9") + except: + raise functions.OperatorError(__name__.rsplit('.')[-1],"Compression level should range from 0 to 9") + filename, ext=os.path.splitext(os.path.basename(where)) + fullpath=os.path.split(where)[0] + if split == 0: + fileIter=open(where, "w+b") + fastPickler = cPickle.Pickler(fileIter, 1) + fastPickler.fast = 1 + else: + fileIter = 1 + + + + def spac(fileObject,lencols): + colnum = len(schema)-1 + serializer.dump(schema[1:],fileObject) + setcol = [set([]) for _ in xrange(colnum)] + dictsize = 65536 + paxcols = [] + indextype = 'H' + index_init = [0 for _ in xrange(3)] + coldicts = [{} for _ in xrange(colnum)] + prevsets = [[] for _ in xrange(colnum)] + count = 0 + blocknum = 0 + compress = bz2.compress + + + while True: + maxlen = 0 + exitGen = False + rows = [] + try: + for i in xrange(lencols): + rows.append((yield)) + except GeneratorExit: + exitGen = True + listofvals = zip(*rows) + + if listofvals!=[]: + + for i,col in enumerate(listofvals): + if i not in paxcols: + setcol[i].update(col) + + prev = fileObject.tell() + 8*(colnum+2) + output = cStringIO.StringIO() + headindex = [0 for _ in xrange(colnum+2)] + + if blocknum == 0: + for i in xrange(colnum): + headindex[i] = output.tell() + prev + if (len(setcol[i])*1.0/lencols>0.67): + paxcols.append(i) + l = index_init[:] + t = output.tell() + output.write(struct.pack('L'*len(l), *l)) + output.write(compress(serializer.dumps(listofvals[i]),2)) + l[0] = output.tell() + output.seek(t) + output.write(struct.pack('L'*len(l), *l)) + output.seek(l[0]) + else: + prevsets[i] = list(set(setcol[i]).copy()) + coldicts[i] = dict(((x,y) for y,x in enumerate(prevsets[i]))) + coldict = coldicts[i] + if len(prevsets[i])<256: + indextype='B' + else: + indextype='H' + l = index_init[:] + t = output.tell() + output.write(struct.pack('L'*len(l), *l)) + output.write(compress(serializer.dumps(prevsets[i]),2)) + l[0] = output.tell() + output.write(compress(array(indextype,[coldict[val] for val in listofvals[i]] ).tostring())) + l[1] = output.tell() + output.seek(t) + output.write(struct.pack('L'*len(l), *l)) + output.seek(l[1]) + else: + for i in xrange(colnum): + headindex[i] = output.tell() + prev + if i in paxcols: + l = index_init[:] + t = output.tell() + output.write(struct.pack('L'*len(l), *l)) + output.write(compress(serializer.dumps(listofvals[i]),2)) + l[0] = output.tell() + output.seek(t) + output.write(struct.pack('L'*len(l), *l)) + output.seek(l[0]) + + else: + pset = set(prevsets[i]) + difnew = list(setcol[i] - pset) + s = prevsets[i] + difnew + d = 0 + if len(s) > dictsize: + difold = list(pset - setcol[i]) + while len(s)>dictsize: + s.remove(difold[d]) + d+=1 + + prevsets[i] = s + coldicts[i] = dict(((x,y) for y,x in enumerate(s))) + coldict = coldicts[i] + towritevalues = (x for x in xrange(len(coldict)-d, len(coldict))) + + + l = index_init[:] + t = output.tell() + output.write(struct.pack('L'*len(l), *l)) + if len(prevsets[i]) != 0 : + if len(prevsets[i])<256: + indextype='B' + else: + indextype='H' + output.write(compress(serializer.dumps(difnew),2)) + l[0] = output.tell() + output.write(compress(array(indextype,towritevalues).tostring())) + l[1] = output.tell() + + output.write(compress(array(indextype,[coldict[val] for val in listofvals[i]] ).tostring())) + l[2] = output.tell() + output.seek(t) + output.write(struct.pack('L'*len(l), *l)) + output.seek(l[2]) + + headindex[i+1] = output.tell()+ prev + headindex[i+2] = count + count=0 + fileObject.write(struct.pack('L'*len(headindex), *headindex)) + fileObject.write(output.getvalue()) + for s in setcol: + s.clear() + gc.collect() + blocknum+=1 + + if exitGen: + fileObject.close() + break + + + def sorteddictpercol(fileIter,lencols,compression,level): + output = StringIO.StringIO() + if split: + output.write(struct.pack('!B', 0)) + cPickle.dump(schema[1:],output,1) + colnum = len(schema)-1 + cz = output.getvalue() + fileIter.write(struct.pack('!i', len(cz))) + fileIter.write(cz) + + else: + colnum = len(schema) + fileIter.write(struct.pack('!B', 0)) + cPickle.dump(schema,fileIter,1) + if hasattr(sys, 'pypy_version_info'): + from __pypy__ import newlist_hint + + else: + newlist_hint = lambda size: [] + paxcols = [] + blocknum = 0 + +# tempio = cStringIO.StringIO() +# fastPickler = cPickle.Pickler(tempio, 2) +# fastPickler.fast = 1 + exitGen=False + compress = zlib.compress + if compression == BZ2: + compress = bz2.compress + if lencols == 0: + (yield) + + + while not exitGen: + output.truncate(0) + mrows = newlist_hint(lencols) + try: + for i in xrange(lencols): + mrows.append((yield)) + except GeneratorExit: + exitGen = True + + count = len(mrows) + output.write(struct.pack('!B', 1)) + if compression == BZ2: + output.write(struct.pack('!B', 0)) + else: + output.write(struct.pack('!B', 1)) + + headindex = [0 for _ in xrange((colnum*2)+1)] + type = '!'+'i'*len(headindex) + output.write(struct.pack(type, *headindex)) + + if mrows != []: + + for i, col in enumerate(([x[c] for x in mrows] for c in xrange(colnum))): + + if blocknum==0: + s = sorted(set(col)) + lens = len(s) + if lens>50*1.0*count/100: + paxcols.append(i) + l = output.tell() +# tempio.truncate(0) +# fastPickler.dump(col) + output.write(compress(serializer.dumps(col),level)) + headindex[i*2] = output.tell() - l + else: + coldict = dict(((x,y) for y,x in enumerate(s))) + l = output.tell() +# tempio.truncate(0) +# fastPickler.dump(s) + output.write(compress(serializer.dumps(s),level)) + headindex[i*2] = output.tell()-l + if lens>1: + if lens<256: + output.write(compress(array('B',[coldict[y] for y in col]).tostring(),level)) + else: + output.write(compress(array('H',[coldict[y] for y in col]).tostring(),level)) + headindex[i*2+1] = output.tell()-l-headindex[i*2] + else: + if i in paxcols: + l = output.tell() +# tempio.truncate(0) +# fastPickler.dump(col) + output.write(compress(serializer.dumps(col),level)) + headindex[i*2] = output.tell() - l + else: + s = sorted(set(col)) + lens = len(s) + coldict = dict(((x,y) for y,x in enumerate(s))) + l = output.tell() +# tempio.truncate(0) +# fastPickler.dump(s) + output.write(compress(serializer.dumps(s),level)) + headindex[i*2] = output.tell()-l + if lens>1: + if lens<256: + output.write(compress(array('B',[coldict[y] for y in col]).tostring(),level)) + else: + output.write(compress(array('H',[coldict[y] for y in col]).tostring(),level)) + headindex[i*2+1] = output.tell()-l-headindex[i*2] + + blocknum=1 + headindex[colnum*2] = count + output.seek(0) + type = '!'+'i'*len(headindex) + output.write(struct.pack('!B', 1)) + if compression == BZ2: + output.write(struct.pack('!B', 0)) + else: + output.write(struct.pack('!B', 1)) + output.write(struct.pack(type, *headindex)) + cz = output.getvalue() + fileIter.write(struct.pack('!i',len(cz))) + fileIter.write(cz) + fileIter.close() + + + + + def rcfile(fileObject,lencols,compression,level): + colnum = len(schema) - 1 + structHeader = '!'+'i' * colnum + indexinit = [0 for _ in xrange(colnum)] + fileObject.write(struct.pack('!B', 0)) + cPickle.dump(schema[1:],fileObject,1) +# l = cStringIO.StringIO() +# fastPickler = cPickle.Pickler(l, 2) +# fastPickler.fast = 1 + exitGen = False + compress = zlib.compress + if compression == BZ2: + compress = bz2.compress + if lencols == 0: + (yield) + + while not exitGen: + rows = [] + try: + for i in xrange(lencols): + rows.append((yield)) + except GeneratorExit: + exitGen = True + + index = indexinit[:] + output = cStringIO.StringIO() + + output.write(struct.pack('!B', 1)) + output.write(struct.pack(structHeader, *index)) + if rows != []: + for i, col in enumerate(([x[c] for x in rows] for c in xrange(colnum))): +# l.truncate(0) +# fastPickler.dump(col) + cz = zlib.compress(serializer.dumps(col), 5) + output.write(cz) + index[i] = len(cz) + output.seek(1) + output.write(struct.pack(structHeader, *index)) + fileObject.write(output.getvalue()) + fileObject.close() + + + + def calclencols(mode): + if mode==RCFILE: + count = 0 + bsize = 0 + rows = [] + try: + while bsize path_filename, filename + +Returns the files name in a given directory. With the option 'rec:1' it returns +the files under the provided directory and all its subdirectories. + +This function is very usefull when used with the *execprogram* function to execute +an external command for every filename. + +.. note:: + *Dirfiles* does not follow links. + +:Returned table schema: + Column C1 is the full filename (path/filename) + Column C2 is filename + +Examples: + + >>> sql("select c2 from dirfiles('.') where c2 like 'f%.py'") # doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + c2 + ------- + file.py + flow.py + + >>> sql("select c2 from dirfiles('rec:1','.') where c2 like 'c%.py'") # doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + c2 + ------------ + coltypes.py + clipout.py + cache.py + continue.py + clipboard.py + +""" +import vtbase +import os.path +import functions +import os + +registered=True + +class dirfiles(vtbase.VT): + def VTiter(self, *parsedArgs, **envars): + def expandedpath(p): + return os.path.realpath(os.path.abspath(os.path.expanduser(os.path.expandvars(os.path.normcase(os.path.normpath(p)))))) + + yield [('c1', 'text'), ('c2', 'text')] + + opts = self.full_parse(parsedArgs) + + dirname='.' + recursive=False + + if 'rec' in opts[1]: + del opts[1]['rec'] + recursive=True + + if 'r' in opts[1]: + del opts[1]['r'] + recursive=True + + if not recursive and len(opts[0])+len(opts[1])>1: + if opts[0][0]=='rec' or opts[0][0]=='recursive': + recursive=True + del opts[0][0] + + if 'query' in opts[1]: + dirname=query + elif len(opts[0])>0: + dirname=opts[0][-1] + elif len(opts[0])==len(opts[1])==0: + dirname='.' + else: + functions.OperatorError(__name__.rsplit('.')[-1], 'A directory name should be provided') + + dirname=expandedpath(dirname) + + if not recursive: + for f in os.listdir(dirname): + fullpathf=expandedpath(os.path.join(dirname,f)) + if os.path.isfile(fullpathf): + yield (fullpathf, f) + else: + for root, dirs, files in os.walk(dirname): + for f in files: + fullpathf=expandedpath(os.path.join(root, f)) + if os.path.isfile(fullpathf): + yield (fullpathf, f) + +def Source(): + return vtbase.VTGenerator(dirfiles) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/examplevt.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/examplevt.py new file mode 100644 index 0000000..8067db4 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/examplevt.py @@ -0,0 +1,68 @@ +""" +.. function:: examplevt(arguments) + +A minimal example of a virtual table. Returns all the arguments passed to it. + +:Returned table schema: + Column names start from C1... , all column types are text + +Examples: + + >>> sql("select * from examplevt(1, '2', 'var3')") # doctest:+ELLIPSIS + varname | value + ------------------------------------------------------------- + parsedargs | (u'1', u'2', u'var3') + envar:tablename | vt_773987998 + envar:modulename | examplevt + ... + envar:dbname | temp + + >>> sql("select * from (examplevt 'var1' 'var2' v1:test select 5)") # doctest:+ELLIPSIS + varname | value + -------------------------------------------------------------------- + parsedargs | (u'query:select 5', u'var1', u'var2', u'v1:test') + envar:tablename | vt_1975870853 + envar:modulename | examplevt + ... + envar:dbname | temp + +""" +import vtbase + +registered=True +external_query = True + +class examplevt(vtbase.VT): + def VTiter(self, *parsedArgs, **envars): + yield [('varname', ), ('value', 'text')] + + largs, dictargs = self.full_parse(parsedArgs) + + li = 0 + for i in largs: + yield [li, unicode(i)] + li += 1 + + for k, v in dictargs.iteritems(): + yield [unicode(k), unicode(v)] + + for x,y in envars.iteritems(): + yield ["envar:"+x, str(y)] + +def Source(): + return vtbase.VTGenerator(examplevt) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/exec.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/exec.py new file mode 100644 index 0000000..62e83f1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/exec.py @@ -0,0 +1,290 @@ +""" +.. function:: exec(query:None,[path:None,variables]) + +Executes the input query. Gets the first column of the returned result and executes its rows content supposing it is an sql statement. + +*Path* parameter sets the current working directory while executing the statements. + +*Variables* are named parameters that set variables in execution environment. For example *c:v* named parameter +sets the variable *c* in the new environment, initialized with current variable's *v* value. + +:Returned table schema: + - *return_value* int + Boolean value 1 indicating success of the SQL statements flow execution. On failure an exception is thrown. + +.. toadd See also variables.. LINK , file??? + +Examples: + +.. doctest:: + :hide: + + >>> settestdb('../../tests/temp.db3') + +This query executes the statements in quotes and returns successfully + +.. doctest:: + + >>> sql("exec select 'select 5'") + return_value + ------------ + 1 + +Typical usage. + +.. doctest:: + + >>> sql("file 'testing/testtable.sql'") + C1 + ---------------------------------------- + create table table1 (a,b,c); + insert into table1 values('James',10,2); + insert into table1 values('Mark',7,3); + insert into table1 values('Lila',74,1); + + >>> sql("exec file 'testing/testtable.sql'") + return_value + ------------ + 1 + + >>> sql("select * from table1") + a | b | c + -------------- + James | 10 | 2 + Mark | 7 | 3 + Lila | 74 | 1 + +Nesting flows. Usage of *path* and variables parameters. + +.. doctest:: + + >>> sql("file 'testing/topflow.sql'") + C1 + ----------------------------------------------------------------------------- + var 'v' 5; + var 'tablename' 'internaltable'; + var 'lastdate' from select '2008-01-01'; + create table topflowvars as select * from getvars() where variable!='execdb'; + exec 'tablename' 'c:v' file 'internalflow.sql'; + + >>> sql("file 'testing/internalflow.sql'") + C1 + ------------------------------------------------------------------------------ + create table %{tablename} as select * from getvars() where variable!='execdb'; + + >>> sql("select * from variables() where variable!='execdb'") + variable | value + ---------------- + flowname | + + >>> sql("exec 'path:testing' file 'testing/topflow.sql'") + return_value + ------------ + 1 + >>> sql("select * from topflowvars") + variable | value + ------------------------- + flowname | notset + lastdate | 2008-01-01 + tablename | internaltable + v | 5 + + >>> sql("select * from internaltable") + variable | value + ------------------------- + flowname | notset + c | 5 + tablename | internaltable + + >>> sql("select * from variables() where variable!='execdb'") + variable | value + ---------------- + flowname | + +.. doctest:: + :hide: + + >>> import os + >>> os.remove('../../tests/temp.db3') + +Test files: + +- :download:`testtable.sql <../../functions/vtable/testing/testtable.sql>` +- :download:`topflow.sql <../../functions/vtable/testing/topflow.sql>` +- :download:`internalflow.sql <../../functions/vtable/testing/internalflow.sql>` + +""" + +import copy +import os.path + +import setpath #for importing from project root directory KEEP IT IN FIRST LINE +from vtout import SourceNtoOne +import apsw +import functions +import logging +import datetime +import os +import copy +import re +import time +import types + +comment_line = re.compile(r'/\*.*?\*/(.*)$') +registered = True + +def filterlinecomment(s): + if re.match(r'\s*--', s, re.DOTALL|re.UNICODE): + return '' + else: + return s + +def breakquery(q): + if len(q) > 1: + raise functions.OperatorError(__name__.rsplit('.')[-1], "Ambiguous query column, result has more than one columns") + st = '' + for row in q[0].splitlines(): + strow = filterlinecomment(row) + if strow == '': + continue + if st != '': + st += '\n'+strow + else: + st += strow + if apsw.complete(st): + yield st + st = '' + + if len(st) > 0 and not re.match(r'\s+$', st, re.DOTALL| re.UNICODE): + if len(st) > 35: + raise functions.OperatorError(__name__.rsplit('.')[-1], "Incomplete statement found : %s ... %s" % (st[:15], st[-15:])) + else: + raise functions.OperatorError(__name__.rsplit('.')[-1], "Incomplete statement found : %s" % (st,)) + +def execflow(diter, schema, connection, *args, **kargs): + ignoreflag = 'ignorefail' + + if functions.variables.execdb is None: + functions.variables.execdb = connection.filename + con = functions.Connection(functions.variables.execdb) + + functions.register(con) + oldvars = functions.variables + newvars = lambda x: x + newpath = None + path = os.getcwd() + + if 'path' in kargs: + newpath = os.path.abspath(kargs['path']) + del kargs['path'] + os.chdir(newpath) + + newvars.execdb = functions.variables.execdb + newvars.flowname = 'notset' + for v in args: + if hasattr(functions.variables, v): + newvars.__dict__[v] = functions.variables.__dict__[v] + else: + raise functions.OperatorError(__name__.rsplit('.')[-1], "Variable %s doesn't exist" % (v,)) + for newv, oldv in kargs.items(): + if hasattr(functions.variables,oldv): + newvars.__dict__[newv]=functions.variables.__dict__[oldv] + else: + raise functions.OperatorError(__name__.rsplit('.')[-1], "Variable %s doen't exist" % (oldv,)) + functions.variables = newvars + + if functions.settings['logging']: + lg = logging.LoggerAdapter(logging.getLogger(__name__),{ "flowname" : functions.variables.flowname }) + lg.info("############FLOW START###################") + before = datetime.datetime.now() + + query = '' + try: + line = 0 + for t in diter: + for query in breakquery(t): + line += 1 + if type(query) not in types.StringTypes: + raise functions.OperatorError(__name__.rsplit('.')[-1], "Content is not sql query") + #Skip empty queries or comment lines + query = query.strip() + if query.startswith("--"): + continue + cmatch = comment_line.match(query) + if query == '' or (cmatch is not None and cmatch.groups()[0] == ''): + continue + + if functions.settings['logging']: + lg = logging.LoggerAdapter(logging.getLogger(__name__),{ "flowname" : functions.variables.flowname }) + lg.info("STARTING: %s" %(query)) + before = datetime.datetime.now() + c = con.cursor() + # check ignore flag + catchexception = False + if query.startswith(ignoreflag): + catchexception=True + query = query[len(ignoreflag):] + try: + for i in c.execute(query): + pass + except Exception,e: #Cathing IGNORE FAIL EXCEPTION + if catchexception: + if functions.settings['logging']: + lg = logging.LoggerAdapter(logging.getLogger(__name__),{ "flowname" : functions.variables.flowname }) + lg.exception("Ignoring Exception: "+str(e)) + continue + else: + try: + c.close() + c = con.cursor() + c.execute('rollback') + except: + pass + raise e + + if functions.settings['logging']: + lg = logging.LoggerAdapter(logging.getLogger(__name__),{ "flowname" : functions.variables.flowname }) + after = datetime.datetime.now() + tmdiff = after-before + duration = "%s min. %s sec %s msec" % ((int(tmdiff.days)*24*60+(int(tmdiff.seconds)/60), (int(tmdiff.seconds)%60),(int(tmdiff.microseconds)/1000))) + lg.info("FINISHED in %s: %s" % (duration, query)) + c.close() + except Exception, e: + if functions.settings['logging']: + lg = logging.LoggerAdapter(logging.getLogger(__name__),{ "flowname" : functions.variables.flowname }) + lg.exception(e) + raise functions.OperatorError(__name__.rsplit('.')[-1], "Error in statement no. %s query '%s':\n%s" % (line, query, str(e))) + finally: + try: + con.close() + except: + pass + after = datetime.datetime.now() + tmdiff = after-before + fltm = "Flow executed in %s min. %s sec %s msec" %((int(tmdiff.days)*24*60+(int(tmdiff.seconds)/60),(int(tmdiff.seconds)%60),(int(tmdiff.microseconds)/1000))) + if functions.settings['logging']: + lg = logging.LoggerAdapter(logging.getLogger(__name__),{ "flowname" : functions.variables.flowname }) + lg.info(fltm) + lg.info("#############FLOW END####################") + functions.variables = oldvars + if newpath: + os.chdir(path) + +def Source(): + return SourceNtoOne(execflow,connectionhandler=True) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/expand.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/expand.py new file mode 100644 index 0000000..c54c627 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/expand.py @@ -0,0 +1,269 @@ +""" +.. function:: expand(query:None) + +Executes the input query and returns the result expanding any multiset values returned. The returned result is produced iteratively. + +:Returned table schema: + Same as input query schema expanded with multiset functions column naming. When *as* renaming function is used at a multiset function, + if the multiset function returns only one column it is named according to the *as* value, + else a positive integer (1,2...n) is appended to the column name indicating column index in the multiset function result. + +Examples:: + + >>> table1(''' + ... James 10 2 + ... Mark 7 3 + ... Lila 74 1 + ... ''') + >>> sql("select ontop(1,c,a,b) from table1") + top1 | top2 + ----------- + Mark | 7 + >>> sql("select ontop(1,c,b,c) as prefs from table1") + prefs1 | prefs2 + --------------- + 7 | 3 + >>> sql("select ontop(1,c,a) as nameontop from table1") + nameontop + --------- + Mark + + The explicit invocation of expand function won't affect the output since it is already automatically invoked because of the multiset function ontop. + + >>> sql("expand expand select ontop(2,b,a) from table1") + top1 + ----- + Lila + James + +.. doctest:: + :hide: + + >>> table2(''' + ... Fibi 40 + ... Monika 5 + ... Soula 17 + ... ''') + >>> sql("select * from (select ontop(1,c,a,b) from table1) as a,(select ontop(1,c,a,b) from table1) as b,(select ontop(2,b,a,b) from table2) as c where a.top2=b.top2 and a.top2>> sql("select * from (select ontop(3,c,a,b) from table1) as a,(select ontop(3,c,a,b) from table1) as b,(select ontop(2,b,a,b) from table2) as c") + top1 | top2 | top1 | top2 | top1 | top2 + ------------------------------------------ + Mark | 7 | Mark | 7 | Fibi | 40 + Mark | 7 | Mark | 7 | Soula | 17 + Mark | 7 | James | 10 | Fibi | 40 + Mark | 7 | James | 10 | Soula | 17 + Mark | 7 | Lila | 74 | Fibi | 40 + Mark | 7 | Lila | 74 | Soula | 17 + James | 10 | Mark | 7 | Fibi | 40 + James | 10 | Mark | 7 | Soula | 17 + James | 10 | James | 10 | Fibi | 40 + James | 10 | James | 10 | Soula | 17 + James | 10 | Lila | 74 | Fibi | 40 + James | 10 | Lila | 74 | Soula | 17 + Lila | 74 | Mark | 7 | Fibi | 40 + Lila | 74 | Mark | 7 | Soula | 17 + Lila | 74 | James | 10 | Fibi | 40 + Lila | 74 | James | 10 | Soula | 17 + Lila | 74 | Lila | 74 | Fibi | 40 + Lila | 74 | Lila | 74 | Soula | 17 +""" + +import setpath +import vtbase +import functions +import re +from lib.sqlitetypes import getElementSqliteType + +### Classic stream iterator +registered = True + +noas = re.compile('.*\(.*\).*') + +def izip2(*args): + # izip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D- + counter = sum((1 if type(x) is generator else 0 for x in args)) + iterators = [chain(it, sentinel(), fillers) for it in args] + try: + while iterators: + yield tuple(map(next, iterators)) + except ZipExhausted: + pass + +class Expand(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + + def exprown(row): + for i in xrange(len(row)): + iobj = row[i] + if type(iobj) is tuple: + for el in iobj[1]: + for l in exprown(row[(i+1):]): + yield row[:i] + list(el) + l + try: + del(self.connection.openiters[iobj[0]]) + except KeyboardInterrupt: + raise + except: + pass + return + + yield row + + largs, dictargs = self.full_parse(parsedArgs) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No query argument ") + query=dictargs['query'] + + self.connection = envars['db'] + oiters = self.connection.openiters + iterheader = functions.iterheader + lenIH = len(iterheader) + + cur = self.connection.cursor() + c= cur.execute(query, parse = False) + + schema = cur.getdescriptionsafe() + self.nonames = True + types = [] + orignames = [x[0] for x in schema] + origtypes = [x[1] if len(x)>1 else 'None' for x in schema] + + nrow = [] + nnames = [] + ttypes=[] + + try: + row = c.next() + except StopIteration: + yield schema + return + + rowlen = len(row) + + for i in xrange(rowlen): + obj = row[i] + if type(obj) is buffer and obj[:lenIH] == iterheader: + strobj = str(obj) + oiter=oiters[strobj] + try: + first = oiter.next() + except StopIteration: + first = [None] + + ttypes += ['GUESS']*len(first) + if noas.match(orignames[i]): + badschema = False + if type(first) != tuple: + badschema = True + + for i in first: + if type(first) != tuple or type(i) not in (unicode, str) or i is None: + badschema = True + break + + if badschema: + raise functions.OperatorError(__name__.rsplit('.')[-1], + "First yielded row of multirow functions, should contain the schema inside a Python tuple.\nExample:\n yield ('C1', 'C2')") + + nnames += list(first) + else: + if len(first) == 1: + nnames += [orignames[i]] + else: + nnames += [orignames[i]+str(j) for j in xrange(1, len(first)+1)] + nrow += [(strobj, oiter)] + else: + ttypes += [origtypes[i]] + nnames += [orignames[i]] + nrow += [obj] + + firstbatch = exprown(nrow) + try: + firstrow = firstbatch.next() + except StopIteration: + firstrow = None + + for i, v in enumerate(ttypes): + if v == 'GUESS': + try: + v = getElementSqliteType(firstrow[i]) + except Exception, e: + v = 'text' + types.append(v) + + yield [(nnames[i], types[i]) for i in xrange(len(types))] + + if firstrow is not None: + yield firstrow + + for exp in firstbatch: + yield exp + +# lastvals = [None] * len(nrow) + for row in c: + nrow = list(row) +# itercount = 0 + + for i in xrange(rowlen): + if type(nrow[i]) is buffer and nrow[i][:lenIH] == iterheader: + striter = str(nrow[i]) + oiter = oiters[striter] + oiter.next() + nrow[i] = (striter, oiter) +# itercount += 1 + + for exp in exprown(nrow): + yield exp + +# if itercount > 0: +# while True: +# n = 0 +# irow = [] +# for i in xrange(len(row)): +# val = nrow[i] +# if type(val) == tuple: +# try: +# ival = val[1].next() +# lastvals[i] = ival +# except StopIteration: +# ival = lastvals[i] +# itercount -= 1 +# irow += nrow[n:i] +# n = i+1 +# irow += ival +# +# irow += nrow[n:] +# if itercount == 0: +# break +# else: +# yield irow +# else: +# yield row + + + +def Source(): + return vtbase.VTGenerator(Expand) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/file.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/file.py new file mode 100644 index 0000000..af3e277 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/file.py @@ -0,0 +1,544 @@ +""" +.. function:: file(location, [formatting options]) + +Opens and returns a file or url as a table. The file's format is defined through +named options. *location* is defined through a URL, or a regular filename, can be given also as +the named parameter *url* or *file*. If no named parameters are given the returned table has one column +with each line of resource as a row or it assumes the dialect from the file ending (Files ending in .tsv, .csv, .json are +assumed to be in the corresponding dialect). + +:Returned table schema: + Columns are automatically named as *C1, C2...* or if header is set, columns are named by the resource first line value, and have the type *text* + +Formatting options: + +:fast: + + Default is 0 (false). Fast option speeds up the parsing of lines into values, exchanging accuracy for speed. It uses the delimiter option to split lines. + +:strict: + + - strict:1 (default), if a failure occurs, the current transaction will be cancelled and an error will be returned. + - strict:0 , returns all data that succesfully parses. + - strict:-1 , returns all input lines in which the parser finds a problem. In essence this works as a negative parser. + + If no strict option is defined in fast:1 mode, then no strictness checking is applied at all, and an "Unknown error" will be returned if a problem occurs. + +:encoding: + + A standar encoding name. (`List of encodings `_) + +:compression: *t/f* + + Default is *f* (False) + +:compressiontype: *zip/gzip* + + Default is *zip* + +Formatting options for CSV file types: + +:dialect: *tsv/csv/json* + + Formats field as tab/comma separated values with minimal quoting. *JSON* dialect uses a line oriented *JSON* based format. + + File extensions that are recognised as a dialect (.tsv, .csv, .json) take precedence over a specified dialect parameter. + +:header: *t/f* + + Set the column names of the returned table + +:delimiter: + + A string used to separate fields. It defaults to ',' + +:doublequote: *t/f* + + Controls how instances of quotechar appearing inside a field should be themselves be quoted. When True, the character is doubled. When False, the escapechar is used as a prefix to the quotechar. It defaults to True. + On output, if doublequote is False and no escapechar is set, Error is raised if a quotechar is found in a field + +:escapechar: + + A one-character string used by the writer to escape the delimiter if quoting is set to QUOTE_NONE and the quotechar if doublequote is False. On reading, the escapechar removes any special meaning from the following character. It defaults to None, which disables escaping + +:lineterminator: + + The string used to terminate lines produced by the writer. It defaults to '\\\\r\\\\n' + +:quotechar: + + A one-character string used to quote fields containing special characters, such as the delimiter or quotechar, or which contain new-line characters. It defaults to '"'. + +:quoting: + + Controls when quotes should be generated by the writer and recognised by the reader. It can take on any of the QUOTE_* constants and defaults to QUOTE_MINIMAL. + Possible values are QUOTE_ALL, QUOTE_NONE, QUOTE_MINIMAL, QUOTE_NONNUMERIC + +:skipinitialspace: *t/f* + + When True, whitespace immediately following the delimiter is ignored. The default is False + +:toj: *Num* + + When toj is defined, columns 0-Num are returned as normal, and all columns >Num are returned as a JSON list or JSON + dict, depending on if the *header* is enabled. + +Examples:: + + >>> sql("select * from (file file:testing/colpref.csv dialect:csv) limit 3;") + C1 | C2 | C3 | C4 + -------------------------------------- + userid | colid | preference | usertype + agr | | 6617580.0 | agr + agr | a0037 | 2659050.0 | agr + >>> sql("select * from (file file:testing/colpref.csv dialect:csv header:t) limit 3") + userid | colid | preference | usertype + -------------------------------------- + agr | | 6617580.0 | agr + agr | a0037 | 2659050.0 | agr + agr | a0086 | 634130.0 | agr + >>> sql("select * from (file file:testing/colpref.zip header:t dialect:csv compression:t) limit 3;") + userid | colid | preference | usertype + -------------------------------------- + agr | | 6617580.0 | agr + agr | a0037 | 2659050.0 | agr + agr | a0086 | 634130.0 | agr + >>> sql("select * from (file 'testing/colpref.tsv' delimiter:| ) limit 3;") + C1 | C2 | C3 | C4 + ----------------------------- + agr | | 6617580.0 | agr + agr | a0037 | 2659050.0 | agr + agr | a0086 | 634130.0 | agr + >>> sql("select * from (file 'testing/colpref.tsv.gz' delimiter:| compression:t compressiontype:gzip) limit 3;") + C1 | C2 | C3 | C4 + ----------------------------- + agr | | 6617580.0 | agr + agr | a0037 | 2659050.0 | agr + agr | a0086 | 634130.0 | agr + >>> sql("select * from file('http://sites.google.com/site/stats202/data/test_data.csv?attredirects=0') limit 10;") + C1 + ----------------- + Age,Number,Start + middle,5,10 + young,2,17 + old,10,6 + young,2,17 + old,4,15 + middle,5,15 + young,3,13 + old,5,8 + young,7,9 + >>> sql("select * from file('file:testing/GeoIPCountryCSV.zip','compression:t','dialect:csv') limit 4") + C1 | C2 | C3 | C4 | C5 | C6 + ---------------------------------------------------------------------- + 2.6.190.56 | 2.6.190.63 | 33996344 | 33996351 | GB | United Kingdom + 3.0.0.0 | 4.17.135.31 | 50331648 | 68257567 | US | United States + 4.17.135.32 | 4.17.135.63 | 68257568 | 68257599 | CA | Canada + 4.17.135.64 | 4.17.142.255 | 68257600 | 68259583 | US | United States +""" + +registered=True +external_stream=True + +from vtiterable import SourceVT +from lib.dsv import reader +import lib.gzip34 as gzip +import urllib2 +import urlparse +import functions +from lib.iterutils import peekable +from lib.ziputils import ZipIter +import lib.inoutparsing +from functions.conf import domainExtraHeaders +from functions import mstr +import itertools +import json +import os.path +from codecs import utf_8_decode +import csv + +# Set maximum field size to 20MB +csv.field_size_limit(20000000) + +class defaultcsv(csv.Dialect): + def __init__(self): + self.delimiter=',' + self.doublequote=True + self.quotechar='"' + self.quoting=csv.QUOTE_MINIMAL + self.lineterminator='\n' + +class tsv(csv.Dialect): + def __init__(self): + self.delimiter='\t' + self.doublequote=True + self.quotechar='"' + self.quoting=csv.QUOTE_MINIMAL + self.lineterminator='\n' + + +class line(csv.Dialect): + def __init__(self): + self.delimiter='\n' + self.doublequote=False + self.quotechar='"' + self.quoting=csv.QUOTE_NONE + self.lineterminator='\n' + +csvkeywordparams=set(['delimiter','doublequote','escapechar','lineterminator','quotechar','quoting','skipinitialspace','dialect', 'fast']) +nonstringargs = {'quoting':{'QUOTE_ALL':csv.QUOTE_ALL, 'QUOTE_NONE':csv.QUOTE_NONE, 'QUOTE_MINIMAL':csv.QUOTE_MINIMAL, 'QUOTE_NONNUMERIC':csv.QUOTE_NONNUMERIC}} + +def nullify(iterlist): + for lst in iterlist: + yield [x if x.upper()!='NULL' else None for x in lst] + +def directfile(f, encoding='utf_8'): + for line in f: + yield ( unicode(line.rstrip("\r\n"), encoding), ) + +def directfileutf8(f): + try: + for line in f: + yield ( utf_8_decode(line.rstrip("\r\n"))[0], ) + except UnicodeDecodeError, e: + raise functions.OperatorError(__name__.rsplit('.')[-1], unicode(e)+"\nFile is not %s encoded" %(self.encoding)) + +def strict0(tabiter, colcount): + while True: + row = tabiter.next() + if len(row) == colcount: + yield row + +def convnumbers(r): + out = [] + for c in r: + try: + c = int(c) + except ValueError: + try: + c = float(c) + except ValueError: + pass + out.append(c) + return out + +def tojdict(tabiter, header, preable): + for r in tabiter: + yield r[:preable] + [json.dumps(dict(zip(header, convnumbers(r[preable:]))), separators=(',',':'), ensure_ascii=False)] + +def tojlist(tabiter, preable): + for r in tabiter: + yield r[:preable] + [json.dumps(convnumbers(r[preable:]), separators=(',',':'), ensure_ascii=False)] + +def strict1(tabiter, colcount): + linenum = 0 + while True: + row = tabiter.next() + linenum += 1 + if len(row) != colcount: + raise functions.OperatorError(__name__.rsplit('.')[-1],"Line " + str(linenum) + " is invalid. Found "+str(len(row))+" of expected "+str(colcount)+" columns\n"+"The line's parsed contents are:\n" + u','.join([mstr(x) for x in row])) + yield row + +def strictminus1(tabiter, colcount, hasheader = False): + linenum = 0 + if hasheader: + linenum += 1 + while True: + linenum += 1 + row = tabiter.next() + if len(row) != colcount: + yield (linenum, len(row), colcount, u','.join([unicode(x) for x in row])) + +def cleanBOM(t): + return t.encode('ascii', errors = 'ignore').strip() + +class FileCursor: + def __init__(self,filename,isurl,compressiontype,compression,hasheader,first,namelist,extraurlheaders,**rest): + self.encoding='utf_8' + self.fast = False + self.strict = None + self.toj = -1 + self.namelist = None + self.hasheader = hasheader + self.namelist = namelist + self.dialect = 'csv' + + if 'encoding' in rest: + self.encoding=rest['encoding'] + del rest['encoding'] + + if 'strict' in rest: + self.strict = int(rest['strict']) + del rest['strict'] + + if 'fast' in rest: + self.fast = True + del rest['fast'] + + if 'toj' in rest: + try: + self.toj = int(rest['toj']) + except ValueError: + self.toj = 0 + del rest['toj'] + + if 'dialect' in rest: + self.dialect = rest['dialect'] + dialects = {'line':line(), 'tsv':tsv(), 'csv':defaultcsv()} + if self.dialect in dialects: + rest['dialect'] = dialects[self.dialect] + + self.nonames=first + for el in rest: + if el not in csvkeywordparams: + raise functions.OperatorError(__name__.rsplit('.')[-1],"Invalid parameter %s" %(el)) + + pathname=None + gzipcompressed=False + + try: + if compression and compressiontype=='zip': + self.fileiter=ZipIter(filename,"r") + elif not isurl: + pathname = filename.strip() + if self.fast or compression or \ + (pathname is not None and (pathname.endswith('.gz') or pathname.endswith('.gzip') or pathname.endswith('.avro'))): + self.fileiter = open(filename, "rb", buffering=1000000) + else: + if "MSPW" in functions.apsw_version: + self.fileiter = open(filename, "r", buffering=1000000) + else: + self.fileiter = open(filename, "rU", buffering=1000000) + else: + pathname=urlparse.urlparse(filename)[2] + req=urllib2.Request(filename,None,extraurlheaders) + hreq=urllib2.urlopen(req) + if [1 for x,y in hreq.headers.items() if x.lower() in ('content-encoding', 'content-type') and y.lower().find('gzip')!=-1]: + gzipcompressed=True + self.fileiter=hreq + + if pathname!=None and ( pathname.endswith('.gz') or pathname.endswith('.gzip') ): + gzipcompressed=True + + if compression and compressiontype=='gz': + gzipcompressed=True + + if gzipcompressed: + if filename.endswith('.gz'): + filename = filename[:-3] + if filename.endswith('.gzip'): + filename = filename[:-5] + self.fileiter = gzip.GzipFile(mode = 'rb', fileobj=self.fileiter) + + except Exception,e: + raise functions.OperatorError(__name__.rsplit('.')[-1], e) + + _, filenameExt = os.path.splitext(filename) + filenameExt = filenameExt.lower() + + if filenameExt == '.json' or filenameExt == '.js' or ('dialect' in rest and type(rest['dialect']) == str + and rest['dialect'].lower() == 'json'): + self.fast = True + firstline = self.fileiter.readline() + try: + schemaline = json.loads(firstline) + except ValueError: + namelist.append(['C1', 'text']) + self.iter = directfile(itertools.chain([firstline], self.fileiter), self.encoding) + return + schemalinetype = type(schemaline) + + if schemalinetype == list: + for i in xrange(1, len(schemaline)+1): + namelist.append(['C'+str(i), 'text']) + self.fileiter = itertools.chain([firstline], self.fileiter) + + elif schemalinetype == dict and 'schema' in schemaline: + namelist += schemaline['schema'] + + else: + namelist.append(['C1', 'text']) + self.iter = directfile(itertools.chain([firstline], self.fileiter), self.encoding) + return + + if "MSPW" in functions.apsw_version: + self.iter = (json.loads(x) for x in self.fileiter) + else: + jsonload = json.JSONDecoder().scan_once + self.iter = (jsonload(x, 0)[0] for x in self.fileiter) + return + + if filenameExt == '.avro': + self.fast = True + from lib import fastavro as avro + + afi = avro.reader(self.fileiter) + fields = [x['name'] for x in afi.schema['fields']] + namelist.extend([[x, ''] for x in fields]) + self.iter = ([x[y] for y in fields] for x in afi) + return + + if filenameExt == '.csv': + if self.fast: + rest['delimiter'] = ',' + rest['dialect'] = lib.inoutparsing.defaultcsv() + + if filenameExt == '.tsv': + if self.fast: + rest['delimiter'] = '\t' + rest['dialect'] = lib.inoutparsing.tsv() + + if self.fast: + if 'delimiter' not in rest: + rest['delimiter'] = ',' + if self.dialect == 'tsv': + rest['delimiter'] = '\t' + + if hasheader or len(rest) > 0: #if at least one csv argument default dialect is csv else line + if 'dialect' not in rest: + rest['dialect']=lib.inoutparsing.defaultcsv() + + linelen = 0 + if first and not hasheader: + if self.fast: + delim = rest['delimiter'] + self.iter=peekable((unicode(r[:-1] if r[-1] == '\n' else r, 'utf_8').split(delim) for r in self.fileiter)) + else: + self.iter=peekable(nullify(reader(self.fileiter, encoding=self.encoding,**rest))) + if self.strict == None: + self.strict = 1 + sample=self.iter.peek() + linelen = len(sample) + else: ###not first or header + if self.fast: + delim = rest['delimiter'] + self.iter = (unicode(r[:-1] if r[-1] == '\n' else r, 'utf_8').split(delim) for r in self.fileiter) + else: + self.iter=nullify(reader(self.fileiter, encoding=self.encoding, **rest)) + if self.strict == None: + self.strict = 1 + linelen = len(namelist) + + if hasheader: + sample=self.iter.next() + linelen = len(sample) + + if self.strict == 0: + self.iter = strict0(self.iter, linelen) + + if self.strict == 1: + self.iter = strict1(self.iter, linelen) + + if self.strict == -1: + self.iter = strictminus1(self.iter, linelen, hasheader) + namelist += [['linenumber', 'int'], ['foundcols', 'int'], ['expectedcols', 'int'],['contents', 'text']] + + if first and namelist==[]: + if hasheader: + for i in sample: + namelist.append( [cleanBOM(i), 'text'] ) + else: + for i in xrange(1, linelen+1): + namelist.append( ['C'+str(i), 'text'] ) + + else: #### Default read lines + if self.encoding == 'utf_8': + self.iter = directfileutf8(self.fileiter) + self.fast = True + else: + self.iter = directfile(self.fileiter, encoding=self.encoding) + namelist.append( ['C1', 'text'] ) + + if self.toj >=0: + header = [x[0] for x in namelist] + while len(namelist) > self.toj: namelist.pop() + header = header[self.toj:] + if self.hasheader: + namelist.append( ['Cjdict', 'text'] ) + self.iter = tojdict(self.iter, header, self.toj) + else: + namelist.append( ['Cjlist', 'text'] ) + self.iter = tojlist(self.iter, self.toj) + + if self.fast: + self.next = self.iter.next + + def __iter__(self): + if self.fast: + return self.iter + else: + return self + + def next(self): + try: + return self.iter.next() + except UnicodeDecodeError, e: + raise functions.OperatorError(__name__.rsplit('.')[-1], unicode(e)+"\nFile is not UTF8 encoded") + + def close(self): + self.fileiter.close() + +class FileVT: + def __init__(self,envdict,largs,dictargs): #DO NOT DO ANYTHING HEAVY + self.largs=largs + self.envdict=envdict + self.dictargs=dictargs + self.nonames=True + self.names=[] + self.destroyfiles=[] + self.inoutargs={} + self.extraheader={} + + def getdescription(self): + if not self.names: + raise functions.OperatorError(__name__.rsplit('.')[-1],"VTable getdescription called before initiliazation") + self.nonames=False + return self.names + + def open(self): + if self.nonames: + try: + self.inoutargs=lib.inoutparsing.inoutargsparse(self.largs,self.dictargs) + except lib.inoutparsing.InputsError: + raise functions.OperatorError(__name__.rsplit('.')[-1]," One source input is required") + if not self.inoutargs['filename']: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No input provided") + + if self.inoutargs['url']: + for domain in domainExtraHeaders: + if domain in self.inoutargs['filename']: + self.extraheader=domainExtraHeaders[domain] + break + if 'User-Agent' not in self.extraheader: + self.extraheader['User-Agent']='Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)' + if self.inoutargs['url'] and self.inoutargs['compression'] and self.inoutargs['compressiontype']=='zip': + self.inoutargs['filename']=lib.inoutparsing.cacheurl(self.inoutargs['filename'], self.extraheader) + self.destroyfiles=[self.inoutargs['filename']] + self.inoutargs['url']=False + + return FileCursor(self.inoutargs['filename'],self.inoutargs['url'],self.inoutargs['compressiontype'],self.inoutargs['compression'],self.inoutargs['header'],self.nonames,self.names,self.extraheader,**self.dictargs) + + def destroy(self): + import os + for f in self.destroyfiles: + os.remove(f) + +def Source(): + global boolargs, nonstringargs + return SourceVT(FileVT, lib.inoutparsing.boolargs+['header','compression'], nonstringargs, lib.inoutparsing.needsescape) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/flow.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/flow.py new file mode 100644 index 0000000..3fb6130 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/flow.py @@ -0,0 +1,108 @@ +""" +.. function:: flow(query:None) + +Translates the input query results into sql statements if possible. + +:Returned table schema: + - *query* text + A complete sql query statement with the semicolon at the end + +.. note:: + + Input query results must be sql statements separated with semicolons in the first place. Using in the input query the :func:`~functions.vtable.file.file` operator any file with sql statements can be divided in sql query statements. Multiline comments are considered as statements. + + + +Examples: + +.. doctest:: + + >>> sql("select * from (flow file 'testing/testflow.sql') limit 1") # doctest: +NORMALIZE_WHITESPACE + query + ----------------------------------------------------------------------------------------------------------------------------------------------------------- + /*====== countries: table of Country ISO codes , country names ===========*/ + CREATE TABLE countries ( + country2 PRIMARY KEY UNIQUE, + country_name + ); + >>> sql("select * from (flow file 'testing/colpref.csv' limit 5) ") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator FLOW: Incomplete statement found : userid colid pr ... 41 416900.0 agr + +Test files: + +- :download:`testflow.sql <../../functions/vtable/testing/testflow.sql>` +- :download:`colpref.csv <../../functions/vtable/testing/colpref.csv>` + + + +""" +import setpath +import vtbase +import functions +import apsw +import re + +registered=True + +def filterlinecomment(s): + if re.match(r'\s*--', s, re.DOTALL| re.UNICODE): + return '' + else: + return s + +class FlowVT(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + largs, dictargs = self.full_parse(parsedArgs) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No query argument ") + + query=dictargs['query'] + connection=envars['db'] + + yield (('query', 'text'),) + cur=connection.cursor() + execit=cur.execute(query, parse = False) + + st='' + for row in execit: + strow=filterlinecomment(' '.join(row)) + if strow=='': + continue + if st!='': + st+='\n'+strow + else: + st+=strow + if apsw.complete(st): + yield [st] + st='' + if len(st)>0 and not re.match(r'\s+$', st, re.DOTALL| re.UNICODE): + if len(st)>35: + raise functions.OperatorError(__name__.rsplit('.')[-1],"Incomplete statement found : %s ... %s" %(st[:15],st[-15:])) + else: + raise functions.OperatorError(__name__.rsplit('.')[-1],"Incomplete statement found : %s" %(st)) + +def Source(): + return vtbase.VTGenerator(FlowVT) + + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/hidden.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/hidden.py new file mode 100644 index 0000000..0d71ccd --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/hidden.py @@ -0,0 +1,77 @@ +""" + +.. function:: hidden(query) -> query results + +Executes the query, without returning any of its rows. + +:Returned table schema: + Same as input query schema. + +Examples:: + + >>> table1(''' + ... James 10 2 + ... Mark 7 3 + ... Lila 74 1 + ... ''') + >>> sql("hidden select * from table1") + a | b | c + --------- + + >>> sql("hidden select * from table1 order by c") + a | b | c + --------- + +""" +import setpath +import vtbase +import functions + +### Classic stream iterator +registered=True + +class NopVT(vtbase.VT): + def VTiter(self, *parsedArgs, **envars): + largs, dictargs = self.full_parse(parsedArgs) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1], "No query argument ") + query = dictargs['query'] + + c = envars['db'].cursor() + q = c.execute(query, parse=False) + + try: + yield list(c.getdescriptionsafe()) + except StopIteration: + try: + raise + finally: + try: + c.close() + except: + pass + + for _ in q: + pass + + +def Source(): + return vtbase.VTGenerator(NopVT) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/jsonpipe.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/jsonpipe.py new file mode 100644 index 0000000..9896cc3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/jsonpipe.py @@ -0,0 +1,118 @@ +""" + +.. function:: jsonpipe(query:None[,lines:t]) + +Executes *query* as a shell command and returns the standard output lines as rows of one column table. +Setting *lines* parameter to *f* the command output will be returned in one table row. + +:Returned table schema: + - *output* text + Output of shell command execution + +Examples:: + +.. doctest:: + + >>> sql("pipe 'ls ./testing/*.csv' ") + C1 + --------------------- + ./testing/colpref.csv + + >>> sql("pipe wc ./testing/colpref.csv") + C1 + --------------------------------- + 19 20 463 ./testing/colpref.csv + +.. doctest:: + :hide: + + >>> sql("pipe wc nonexistingfile") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator PIPE: Command 'wc nonexistingfile' failed to execute because: + wc: nonexistingfile: No such file or directory +""" + + +import functions +import vtbase +import itertools +import json +import subprocess + +registered = True +external_stream = True + +class JSONPipeVT(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + largs, dictargs = self.full_parse(parsedArgs) + + command = None + + if len(largs) > 0: + command = largs[-1] + + if 'query' in dictargs: + command = dictargs['query'] + + if command is None: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No command argument found") + + child = subprocess.Popen(command, shell=True, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + jsondecode = json.JSONDecoder().scan_once + pipeiter = iter(child.stdout.readline, '') + firstline = '' + + try: + firstline = pipeiter.next() + except StopIteration: + yield (('C1', 'text'),) + raise StopIteration + return + + namelist = [] + schemaline = json.loads(firstline) + schemalinetype = type(schemaline) + + if schemalinetype == list: + for i in xrange(1, len(schemaline)+1): + namelist.append( ['C'+str(i), 'text'] ) + pipeiter = itertools.chain([firstline], self.fileiter) + elif schemalinetype == dict: + namelist += schemaline['schema'] + else: + raise functions.OperatorError(__name__.rsplit('.')[-1], "Input file is not in line JSON format") + + yield tuple(namelist) + + if "MSPW" in functions.apsw_version: + for line in pipeiter: + yield json.loads(line) + else: + for line in pipeiter: + yield jsondecode(line, 0)[0] + + output, error = child.communicate() + + if child.returncode != 0: + raise functions.OperatorError(__name__.rsplit('.')[-1], "Command '%s' failed to execute because:\n%s" %(command,error.rstrip('\n\t '))) + +def Source(): + return vtbase.VTGenerator(JSONPipeVT) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/mysql.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/mysql.py new file mode 100644 index 0000000..43b24b4 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/mysql.py @@ -0,0 +1,114 @@ +""" +.. function:: mysql(host, port, user, passwd, db, query:None) + +Connects to an MySQL DB and returns the results of query. + +Examples: + + >>> sql("select * from (mysql h:127.0.0.1 port:3306 u:root p:rootpw db:mysql select 5 as num, 'test' as text);") + num | text + ----------- + 5 | test + +""" + +import setpath +import vtbase +import functions +from types import NoneType + +registered = True +external_query = True + +class MySQL(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + from lib import pymysql + t = pymysql.FIELD_TYPE + + typetrans = { + t.DECIMAL:'INT', + t.TINY: 'INT', + t.SHORT: 'INT', + t.LONG: 'INT', + t.FLOAT: 'REAL', + t.DOUBLE: 'REAL', + t.NULL: '', + t.TIMESTAMP: 'TEXT', + t.LONGLONG: 'TEXT', + t.INT24: 'TEXT', + t.DATE: 'TEXT', + t.TIME: 'TEXT', + t.DATETIME: 'TEXT', + t.YEAR: 'INT', + t.NEWDATE: 'TEXT', + t.VARCHAR: 'TEXT', + t.BIT: 'INT', + t.NEWDECIMAL: 'INT', + t.ENUM: 'TEXT', + t.SET: 'TEXT', + t.TINY_BLOB: 'TEXT', + t.MEDIUM_BLOB: 'TEXT', + t.LONG_BLOB: 'TEXT', + t.BLOB: 'TEXT', + t.VAR_STRING: 'TEXT', + t.STRING: 'TEXT', + t.GEOMETRY: 'TEXT' + } + + largs, dictargs = self.full_parse(parsedArgs) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No query argument ") + + query=dictargs['query'] + + host = dictargs.get('host', dictargs.get('h', '127.0.0.1')) + port = int(dictargs.get('port', 3306)) + user = dictargs.get('user', dictargs.get('u', 'root')) + passwd = dictargs.get('passwd', dictargs.get('p', '')) + db = dictargs.get('db', 'mysql') + + try: + conn = pymysql.connect(host=host, port=port, user=user, passwd=passwd, db=db, use_unicode = True) + + cur = conn.cursor(pymysql.cursors.SSCursor) + cur.execute(query) + + desc = cur.description + if desc == None: + yield [( 'None', )] + else: + yield [( c[0], typetrans.get(c[1], '') ) for c in desc] + + for i in cur: + yield [unicode(c) if type(c) not in (long, int, float, str, unicode, NoneType, bool) else c for c in i] + + except (pymysql.err.InternalError, pymysql.err.ProgrammingError) as e: + raise functions.OperatorError(__name__.rsplit('.')[-1], str(e[0]) +': ' + e[1]) + except Exception, e: + raise functions.OperatorError(__name__.rsplit('.')[-1], str(e)) + finally: + try: + conn.close() + except: + pass + + +def Source(): + return vtbase.VTGenerator(MySQL) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/oaiget.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/oaiget.py new file mode 100644 index 0000000..2cac1e9 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/oaiget.py @@ -0,0 +1,127 @@ +""" +.. function:: oaiget(url, verb, metadataPrefix,...) + +Fetches data from an OAIPMH service, using resumption tokens to fetch large datasets. + +- If no *verb* is provided then *verb* is assumed to be 'ListRecords'. +- If no *metadataPrefix* is provided then *verb* is assumed to be 'ListMetadataFormats', which will list + all metadata formats. + +:Returned table schema: + Column C1 as text + +Examples: + + >>> sql("select * from oaiget('verb:ListRecords', 'metadataPrefix:ctxo')") # doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator OAIGET: An OAIPMH URL should be provided + + >>> sql("select * from (oaiget verb:ListRecords metadataPrefix:ctxo 'http://oaiurl' )") # doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator OAIGET: + +""" +import vtbase +import functions +import time + +registered=True +external_stream=True + +class oaiget(vtbase.VT): + def VTiter(self, *parsedArgs, **envars): + + import urllib2 + import re + + def buildURL(baseurl, opts): + return '?'.join([ baseurl, '&'.join([x+'='+unicode(y) for x,y in opts if y!=None]) ]) + + def buildopener(): + o = urllib2.build_opener() + o.addheaders = [ + ('Accept', '*/*'), + ('Connection', 'Keep-Alive'), + ('Content-type', 'text/xml') + ] + return o + + yield [('c1', 'text')] + + opts= self.full_parse(parsedArgs)[1] + + if 'verb' not in opts: + opts['verb']='ListRecords' + if 'metadataPrefix' not in opts: + opts['verb']='ListMetadataFormats' + if 'resumptionToken' in opts: + opts['verb']='ListRecords' + if 'http' not in opts: + raise functions.OperatorError(__name__.rsplit('.')[-1],"An OAIPMH URL should be provided") + + baseurl='http:'+opts['http'] + + del(opts['http']) + + opts=list(opts.iteritems()) + + findrestoken=re.compile(r""">([^\s]+?)""", re.DOTALL| re.UNICODE) + + resumptionToken=lastResToken=None + firsttime=True + url=buildURL(baseurl, opts+[('resumptionToken', resumptionToken)]) + + opener=buildopener() + + errorcount=0 + while True: + try: + for i in opener.open(url, timeout=1200): + if resumptionToken==None: + t=findrestoken.search(i) + if t: + errorcount=0 + resumptionToken=t.groups()[0] + yield (unicode(i.rstrip("\n"), 'utf-8'),) + if resumptionToken==None: + break + url=buildURL(baseurl, [(x,y) for x,y in opts if x=='verb']+[('resumptionToken', resumptionToken)]) + lastResToken=resumptionToken + resumptionToken=None + firsttime=False + except KeyboardInterrupt: + raise + except Exception,e: + if errorcount<10 and not firsttime: + time.sleep(2**errorcount) + errorcount+=1 + opener=buildopener() + else: + if lastResToken==None: + raise functions.OperatorError(__name__.rsplit('.')[-1], e) + else: + raise functions.OperatorError(__name__.rsplit('.')[-1], str(e)+'\n'+'To continue use:\nresumptionToken:'+str(lastResToken)) + + +def Source(): + return vtbase.VTGenerator(oaiget) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/oracle.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/oracle.py new file mode 100644 index 0000000..af0b2f0 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/oracle.py @@ -0,0 +1,101 @@ +""" +.. function:: oracle(jdbc_connection_string, user, passwd, query:None) + +Connects to an Oracle DB and returns the results of query. + +The requirements for this to work are: + + - Install JPype Python package: + + Homepage: http://jpype.sourceforge.net/ + + In Debian based systems such as Ubuntu, install python-jpype using: + + sudo apt-get install python-jpype + + - Add the Oracle JDBC JAR (ojdbc5.jar) in directory madis/lib/jdbc/. + + - Have a JVM installed, and the JAVA_HOME environment variable set correctly. + +Examples: + + >>> sql("select * from (oracle jdbc:oracle:thin:@//127.0.0.1:6667/xe u:system p:password select 5 as num, 'test' as text);") + num | text + ----------- + 5 | test + +""" + +import setpath +import vtbase +import functions + +registered=True + +class Oracle(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + from lib import jaydebeapi + import os + from types import NoneType + try: + import jpype + except ImportError: + raise functions.OperatorError(__name__.rsplit('.')[-1],""" +For this operator to work you'll need to: + - Install JPype Python package. For Debian/Ubuntu do: + sudo apt-get install python-jpype + - Add the Oracle JDBC JAR (ojdbc5.jar) in directory madis/lib/jdbc/. + - Have a JVM installed, and the JAVA_HOME environment variable set correctly. + """) + + largs, dictargs = self.full_parse(parsedArgs) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No query argument ") + + query=dictargs['query'] + jdbc = 'jdbc:' + str(dictargs.get('jdbc', 'oracle:thin:@//127.0.0.1:6667/xe')) + user = str(dictargs.get('user', dictargs.get('u', 'system'))) + passwd = str(dictargs.get('passwd', dictargs.get('p', ''))) + jar = str(dictargs.get('jar', 'ojdbc5.jar')) + + if os.path.split(jar)[0] == '': + jarpath = os.path.dirname(os.path.abspath(__file__)) + jar = os.path.abspath(os.path.join(jarpath, '..', '..', 'lib', 'jdbc', jar)) + + try: + conn = jaydebeapi.connect('oracle.jdbc.pool.OracleDataSource', [jdbc, user, passwd], jar,) + cur = conn.cursor() + cur.execute(query) + yield [(c[0], c[1]) for c in cur.description] + + while True: + row = cur.fetchone() + if not row: + break + yield [unicode(c) if type(c) not in (long, int, float, str, unicode, NoneType, bool) else c for c in row] + + cur.close() + + except Exception, e: + raise functions.OperatorError(__name__.rsplit('.')[-1], ' '.join(str(t) for t in e)) + + +def Source(): + return vtbase.VTGenerator(Oracle) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/ordered.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/ordered.py new file mode 100644 index 0000000..28b80c3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/ordered.py @@ -0,0 +1,98 @@ +""" + +.. function:: ordered(query) -> query results + +Ordered virtual table returns its data as they are. The main difference with unindexed, is that +it signals to the SQLite engine that the results are ordered in whatever order +SQLite prefers, so a possible group by on the results will happen incrementally. + +:Returned table schema: + Same as input query schema. + +Examples:: + + >>> table1(''' + ... James 10 2 + ... Mark 7 3 + ... Lila 74 1 + ... ''') + + The following query is calculated incrementally + + >>> sql("select a, count(*) from (ordered select * from table1) group by a") + a | count(*) + ---------------- + James | 1 + Mark | 1 + Lila | 1 + + >>> sql("select * from (ordered select * from table1) order by c") + a | b | c + -------------- + James | 10 | 2 + Mark | 7 | 3 + Lila | 74 | 1 + + Notice that the order by does not work as it should because igroup has + fooled the SQLite engine into believing that the order of the results are + in the correct order (they aren't). + +""" +import setpath +import vtbase +import functions +import gc + +### Classic stream iterator +registered=True + +class Ordered(vtbase.VT): + def BestIndex(self, constraints, orderbys): + return (None, 0, None, True, 1000) + + def VTiter(self, *parsedArgs,**envars): + largs, dictargs = self.full_parse(parsedArgs) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No query argument ") + query=dictargs['query'] + + cur = envars['db'].cursor() + q = cur.execute(query, parse=False) + + try: + yield list(cur.getdescriptionsafe()) + except StopIteration: + try: + raise + finally: + try: + c.close() + except: + pass + + gc.disable() + while True: + yield q.next() + gc.enable() + + +def Source(): + return vtbase.VTGenerator(Ordered) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/output.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/output.py new file mode 100644 index 0000000..3fc46a1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/output.py @@ -0,0 +1,394 @@ + +""" +.. function:: output formatting_options 'filename' query + +Writes in *filename* the output of *query* formatted according to *formatting* options. + +:Returned table schema: + - *return_value* int + Boolean value 1 indicating success. On failure an exception is thrown. + +Formatting options: + +.. toadd html In html mode table is formatted as an html table TODO ???? + +:mode: + - plain *Default*. The columns are concatened and written together. + - tsv Writes data in a tab separated format. *TSV* mode is autoselected when the filename ends in ".tsv". + - csv Writes data in a comma separated format. *CSV* mode is autoselected when the filename ends in ".csv". + - json Writes data in a line separated JSON format. Header is always added. *JSON* mode is autoselected when the filename ends in ".JSON". + - db Writes data in a SQLite DB. *DB* mode is autoselected when the filename ends in ".db". + + - If pagesize:xxxxx option is given, set new DBs page size to parameter given, if not inherit page size from parent DB. + + - gtable In gtable mode table is formatted as a google Data Table for visualisation. + - gjson In gjson mode table is formatted in a json format accepted by google visualisation widgets. + + If *mode* is not *csv* any given csv formatting options are ignored. + +:append: + t/f If true the output is append in the file, ignored in compression mode. + +:compression: + t/f If true the output will be compressed. Default compressor type is *gz*. + +:compressiontype: + gz/zip Selects between the two compression types. + +:split: + (number) It splits the input to many *db* or *json* files. Splitting only works when writting to a *db* or *JSON*. Splitting is done by using the first column of + the input and it outputs all columns except the first one. If the *split* argument is greater than *1* then the output will + always be splitted to the defined number of files. If the split argument is 1 or lower, then the output will only contain the parts of which + a key were found on the first column of the input data. + +Detailed description of additional output formating options can be found in :func:`~functions.vtable.file.file` function description. + +Examples: + + >>> table1(''' + ... James 10 2 + ... Mark 7 3 + ... Lila 74 1 + ... ''') + >>> sql("select * from table1") + a | b | c + -------------- + James | 10 | 2 + Mark | 7 | 3 + Lila | 74 | 1 + >>> sql("output file:../../tests/table1.csv delimiter:# header:t select a as name , b as age, c as rank from table1") + return_value + ------------ + 1 + >>> sql("file file:../../tests/table1.csv delimiter:# header:t") + name | age | rank + ------------------ + James | 10 | 2 + Mark | 7 | 3 + Lila | 74 | 1 +""" +import os.path + +import setpath +from vtout import SourceNtoOne +from lib.dsv import writer +import gzip +from lib.ziputils import ZipIter +import functions +from lib.vtoutgtable import vtoutpugtformat +import lib.inoutparsing +import os +import apsw +import gc +from collections import defaultdict + +registered=True + +def fileit(p, append=False): + if append: + return open(p, "a", buffering=100000) + return open(p, "w" , buffering=100000) + +def getoutput(p, append,compress,comptype): + source=p + it=None + + if compress and ( comptype == 'zip'): + it = ZipIter(source, "w") + elif compress and (comptype=='gzip' or comptype == 'gz'): + itt = fileit(source+'.gz') + it = gzip.GzipFile(mode="w", compresslevel=6, fileobj=itt) + else: + it=fileit(source,append) + return it + +def autoext(f, ftype, typelist): + fname, ext=os.path.splitext(f) + if ext=='' and ftype in typelist: + ext=typelist[ftype] + return fname+'.'+ext + return f + +def autotype(f, extlist): + fname, ext=os.path.splitext(f) + if ext!='': + ext=ext[1:] + if ext in extlist: + return extlist[ext] + return 'plain' + +def outputData(diter, schema, connection, *args, **formatArgs): + ### Parameter handling ### + where=None + if len(args)>0: + where=args[0] + elif 'file' in formatArgs: + where=formatArgs['file'] + else: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No destination provided") + + if 'file' in formatArgs: + del formatArgs['file'] + + if 'mode' not in formatArgs: + formatArgs['mode']=autotype(where, {'csv':'csv', 'tsv':'tsv', 'xls':'tsv', 'db':'db', 'json':'json'}) + + if 'header' not in formatArgs: + header=False + else: + header=formatArgs['header'] + del formatArgs['header'] + + if 'compression' not in formatArgs: + formatArgs['compression']=False + if 'compressiontype' not in formatArgs: + formatArgs['compressiontype']='gz' + + orderby = None + if 'orderby' in formatArgs: + orderby = formatArgs['orderby'] + del formatArgs['orderby'] + + if 'orderbydesc' in formatArgs: + orderby = formatArgs['orderbydesc'] + ' desc' + del formatArgs['orderbydesc'] + + append=False + if 'append' in formatArgs: + append=formatArgs['append'] + del formatArgs['append'] + + type2ext={'csv':'csv', 'tsv':'xls', 'plain':'txt', 'db':'db', 'json':'json'} + + where=autoext(where, formatArgs['mode'], type2ext) + filename, ext=os.path.splitext(os.path.basename(where)) + fullpath=os.path.split(where)[0] + + if not (formatArgs['mode'] == 'db' or (formatArgs['mode']=='json' and 'split' in formatArgs)): + fileIter=getoutput(where,append,formatArgs['compression'],formatArgs['compressiontype']) + + del formatArgs['compressiontype'] + del formatArgs['compression'] + try: + + if formatArgs['mode']=='json': + del formatArgs['mode'] + import json + je = json.JSONEncoder(separators = (',',':'), ensure_ascii = True, check_circular = False).encode + + if 'split' in formatArgs: + def cjs(): + unikey = unicode(key) + t=open(os.path.join(fullpath, filename+'.'+unikey+ext), 'w') + print >> t, je( {'schema':schema[1:]} ) + splitkeys[unikey]=t + jsfiles[key]=t + # Case for number as key + if unikey != key: + splitkeys[key] = splitkeys[unikey] + return splitkeys[key] + + jsfiles = {} + splitkeys=defaultdict(cjs) + + gc.disable() + for row in diter: + key=row[0] + print >> splitkeys[key], je(row[1:]) + gc.enable() + + # Create other parts + maxparts = 1 + try: + maxparts = int(formatArgs['split']) + except ValueError: + maxparts = 1 + + if maxparts > 1: + for i in xrange(0, maxparts): + if i not in splitkeys: + key = i + tmp = splitkeys[key] + + for f in jsfiles.values(): + if f is not None: + f.close() + else: + fileIter.write(je({'schema':schema}) + '\n') + + for row in diter: + print >> fileIter, je(row) + + elif formatArgs['mode'] == 'csv': + del formatArgs['mode'] + csvprinter = writer(fileIter, 'excel', **formatArgs) + if header: + csvprinter.writerow([h[0] for h in schema]) + + for row in diter: + csvprinter.writerow(row) + + elif formatArgs['mode'] == 'tsv': + del formatArgs['mode'] + csvprinter = writer(fileIter, 'excel-tab', **formatArgs) + if header: + csvprinter.writerow([h[0] for h in schema]) + + for row in diter: + csvprinter.writerow([x.replace('\t', ' ') if type(x) is str or type(x) is unicode else x for x in row]) + + elif formatArgs['mode']=='gtable': + vtoutpugtformat(fileIter,diter,simplejson=False) + + elif formatArgs['mode']=='gjson': + vtoutpugtformat(fileIter,diter,simplejson=True) + + elif formatArgs['mode']=='html': + raise functions.OperatorError(__name__.rsplit('.')[-1],"HTML format not available yet") + + elif formatArgs['mode']=='plain': + for row in diter: + fileIter.write(((''.join([unicode(x) for x in row]))+'\n').encode('utf-8')) + + elif formatArgs['mode']=='db': + def createdb(where, tname, schema, page_size=16384): + c = apsw.Connection(where) + cursor = c.cursor() + list(cursor.execute('pragma page_size='+str(page_size)+';pragma cache_size=-1000;pragma legacy_file_format=false;pragma synchronous=0;pragma journal_mode=OFF;PRAGMA locking_mode = EXCLUSIVE')) + if orderby: + tname = '_' + tname + create_schema='create temp table '+tname+'(' + else: + create_schema='create table '+tname+'(' + create_schema+='`'+unicode(schema[0][0])+'`'+ (' '+unicode(schema[0][1]) if schema[0][1]!=None else '') + for colname, coltype in schema[1:]: + create_schema+=',`'+unicode(colname)+'`'+ (' '+unicode(coltype) if coltype!=None else '') + create_schema+='); begin exclusive;' + list(cursor.execute(create_schema)) + insertquery="insert into "+tname+' values('+','.join(['?']*len(schema))+')' + return c, cursor, insertquery + + if 'pagesize' in formatArgs: + page_size=int(formatArgs['pagesize']) + else: + page_size=list(connection.cursor().execute('pragma page_size'))[0][0] + + tablename=filename + if 'tablename' in formatArgs: + tablename=formatArgs['tablename'] + + if 'split' in formatArgs: + maxparts = 0 + try: + maxparts = int(formatArgs['split']) + except ValueError: + maxparts = 0 + + # If not split parts is defined + if maxparts == 0: + ns = lambda x:x + def cdb(): + unikey = unicode(key) + t=createdb(os.path.join(fullpath, filename+'.'+unikey+ext), tablename, schema[1:], page_size) + splitkeys[unikey]=t[1].execute + ns.insertqueryw = t[2] + dbcon[key]=t[0], t[1] + # Case for number as key + if unikey != key: + splitkeys[key] = splitkeys[unikey] + return splitkeys[key] + + dbcon = {} + splitkeys=defaultdict(cdb) + + gc.disable() + for row in diter: + key=row[0] + splitkeys[key](ns.insertqueryw, row[1:]) + gc.enable() + + for c, cursor in dbcon.values(): + if c != None: + cursor.execute('commit') + c.close() + else: + # Splitparts defined + cursors = [] + dbcon = [] + if "MSPW" in functions.apsw_version: + iters = [] + senders = [] + for i in xrange(0, maxparts): + t = createdb(os.path.join(fullpath, filename+'.'+str(i)+ext), tablename, schema[1:], page_size) + it = t[1].executesplit(t[2]) + iters.append(it) + senders.append(it.send) + it.send(None) + dbcon.append((t[0], t[1])) + senders = tuple(senders) + + for row in diter: + senders[hash(row[0]) % maxparts](row) + + for it in iters: + it.close() + else: + for i in xrange(0, maxparts): + t = createdb(os.path.join(fullpath, filename+'.'+str(i)+ext), tablename, schema[1:], page_size) + cursors.append(t[1].execute) + dbcon.append((t[0], t[1])) + insertqueryw = t[2] + cursors = tuple(cursors) + + for row in diter: + cursors[hash(row[0]) % maxparts](insertqueryw, row[1:]) + + for c, cursor in dbcon: + if c != None: + if orderby: + cursor.execute('pragma cache_size=-'+str(100000)+';create table '+tablename+' as select * from _'+tablename+' order by '+orderby) + cursor.execute('commit') + c.close() + else: + # Write to db without split + c, cursor, insertquery=createdb(where, tablename, schema, page_size) + + gc.disable() + cursor.executemany(insertquery, diter) + gc.enable() + + list(cursor.execute('commit')) + c.close() + else: + raise functions.OperatorError(__name__.rsplit('.')[-1],"Unknown mode value") + + except StopIteration,e: + pass + + try: + fileIter.close() + except NameError: + pass + +boolargs=lib.inoutparsing.boolargs+['append','header','compression'] + + +def Source(): + global boolargs, nonstringargs + return SourceNtoOne(outputData,boolargs, lib.inoutparsing.nonstringargs,lib.inoutparsing.needsescape, connectionhandler=True) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/pipe.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/pipe.py new file mode 100644 index 0000000..09686bf --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/pipe.py @@ -0,0 +1,99 @@ +""" + +.. function:: pipe(query:None[,lines:t]) + +Executes *query* as a shell command and returns the standard output lines as rows of one column table. +Setting *lines* parameter to *f* the command output will be returned in one table row. + +:Returned table schema: + - *output* text + Output of shell command execution + +Examples:: + +.. doctest:: + + >>> sql("pipe 'ls ./testing/*.csv' ") + C1 + --------------------- + ./testing/colpref.csv + + >>> sql("pipe wc ./testing/colpref.csv") + C1 + --------------------------------- + 19 20 463 ./testing/colpref.csv + +.. doctest:: + :hide: + + >>> sql("pipe wc nonexistingfile") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator PIPE: Command 'wc nonexistingfile' failed to execute because: + wc: nonexistingfile: No such file or directory +""" + + +import functions +import vtbase + +import subprocess + +registered = True +external_stream = True + +class PipeVT(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + largs, dictargs = self.full_parse(parsedArgs) + + command = None + + if len(largs) > 0: + command = largs[-1] + + if 'query' in dictargs: + command = dictargs['query'] + + if command is None: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No command argument found") + + linesplit = True + if 'lines' in dictargs and dictargs['lines'][0] in ('f', 'F', '0'): + linesplit = False + + yield (('C1', 'text'),) + + child = subprocess.Popen(command, shell=True, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + if linesplit: + pipeiter = iter(child.stdout.readline, '') + for line in pipeiter: + yield (line.rstrip("\r\n").decode('utf_8', 'replace'), ) + + output, error = child.communicate() + else: + output, error = child.communicate() + + yield [output.decode('utf_8', 'replace').rstrip("\r\n")] + + if child.returncode != 0: + raise functions.OperatorError(__name__.rsplit('.')[-1], "Command '%s' failed to execute because:\n%s" %(command,error.rstrip('\n\t '))) + +def Source(): + return vtbase.VTGenerator(PipeVT) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/postgres.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/postgres.py new file mode 100644 index 0000000..d913fcc --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/postgres.py @@ -0,0 +1,111 @@ +""" +.. function:: postgres(host, port, user, passwd, db, query:None) + +Connects to an PostgreSQL DB and returns the results of query. + +Examples: + + >>> sql("select * from (postgres h:127.0.0.1 port:5432 u:root p:rootpw db:testdb select 5 as num, 'test' as text);") + num | text + ----------- + 5 | test + +""" + +import setpath +import vtbase +import functions +from types import NoneType + +registered = True +external_query = True + +class Postgres(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + from lib.pg8000 import DBAPI + DBAPI.warn = lambda x,stacklevel:x + + typetrans = { + 16: 'INT', + 17: 'INT', + 19: 'TEXT', # name type + 20: 'INT', + 21: 'INT', + 23: 'INT', + 25: 'TEXT', # TEXT type + 26: 'INT', # oid type + 142: 'TEXT', # XML + 194: 'TEXT', # "string representing an internal node tree" + 700: 'REAL', + 701: 'REAL', + 705: 'TEXT', + 829: 'TEXT', # MACADDR type + 1000: 'INT', # BOOL[] + 1003: 'TEXT', # NAME[] + 1005: 'INT', # INT2[] + 1007: 'INT', # INT4[] + 1009: 'TEXT', # TEXT[] + 1014: 'TEXT', # CHAR[] + 1015: 'TEXT', # VARCHAR[] + 1016: 'INT', # INT8[] + 1021: 'REAL', # FLOAT4[] + 1022: 'REAL', # FLOAT8[] + 1042: 'TEXT', # CHAR type + 1043: 'TEXT', # VARCHAR type + 1082: 'TEXT', + 1083: 'TEXT', + 1114: 'TEXT', + 1184: 'TEXT', # timestamp w/ tz + 1186: '', + 1231: '', # NUMERIC[] + 1263: 'TEXT', # cstring[] + 1700: '', + 2275: 'TEXT', # cstring + } + + largs, dictargs = self.full_parse(parsedArgs) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No query argument ") + + query=dictargs['query'] + + host = str(dictargs.get('host', dictargs.get('h', '127.0.0.1'))) + port = int(dictargs.get('port', 5432)) + user = str(dictargs.get('user', dictargs.get('u', ''))) + passwd = str(dictargs.get('passwd', dictargs.get('p', ''))) + db = str(dictargs.get('db', '')) + + try: + conn = DBAPI.connect(host=host, user=user, password=passwd, database=db, port=port, socket_timeout=3600) + + cur = conn.cursor() + cur.execute(query) + + yield [(c[0], typetrans.get(c[1], '')) for c in cur.description] + + for i in cur: + yield [unicode(c) if type(c) not in (long, int, float, str, unicode, NoneType, bool) else c for c in i] + + cur.close() + except Exception, e: + raise functions.OperatorError(__name__.rsplit('.')[-1], ' '.join(str(t) for t in e)) + +def Source(): + return vtbase.VTGenerator(Postgres) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/queryplan.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/queryplan.py new file mode 100644 index 0000000..ba7c903 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/queryplan.py @@ -0,0 +1,78 @@ +""" +.. function:: queryplan(query) -> Query plan + +Returns the query plan of the input query. + +Examples:: + + >>> sql("queryplan select 5") + operation | paramone | paramtwo | databasename | triggerorview + ------------------------------------------------------------------ + SQLITE_SELECT | None | None | None | None + +""" + +import setpath +import vtbase +import functions +import apsw + +registered=True + +class QueryPlan(vtbase.VT): + def VTiter(self, *parsedArgs, **envars): + def authorizer(operation, paramone, paramtwo, databasename, triggerorview): + """Called when each operation is prepared. We can return SQLITE_OK, SQLITE_DENY or + SQLITE_IGNORE""" + # find the operation name + plan.append([apsw.mapping_authorizer_function[operation], paramone, paramtwo, databasename, triggerorview]) + return apsw.SQLITE_OK + + def buststatementcache(): + c = connection.cursor() + for i in xrange(110): + a=list(c.execute("select "+str(i))) + + _, dictargs = self.full_parse(parsedArgs) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1]," needs query argument ") + query=dictargs['query'] + + connection = envars['db'] + plan=[] + + buststatementcache() + + cursor = connection.cursor() + + cursor.setexectrace(lambda x,y,z:apsw.SQLITE_DENY) + connection.setauthorizer(authorizer) + + + cursor.execute(query) + + connection.setauthorizer(None) + yield [('operation', 'text'), ('paramone', 'text'), ('paramtwo', 'text'), ('databasename', 'text'), ('triggerorview', 'text')] + for r in plan: + yield r + def destroy(self): + pass + +def Source(): + return vtbase.VTGenerator(QueryPlan) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/range.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/range.py new file mode 100644 index 0000000..d01fad5 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/range.py @@ -0,0 +1,134 @@ +""" +.. function:: range([from:0,[to:10,[step:1]]]) + +Returns a range of integer numbers. + +:Returned table schema: + - *value* int + Number in range. + +.. note:: + + The parameters can be given both named or unnamed. In unnamed mode parameter order is from,to,step. + + +Named parameters: + +:from: + Number to begin from. Default is 0 +:to: + Number to reach. Default is 10. The *to* number is not returned +:step: + Step to augment the returned numbers. Default is 1 + +Examples:: + + >>> sql("select * from range()") + C1 + -- + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + + >>> sql("select * from range('from:1','to:11')") + C1 + -- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + + >>> sql("select * from range('from:2','to:15','step:3')") + C1 + -- + 2 + 5 + 8 + 11 + 14 + + >>> sql("select * from range(1,10,2)") + C1 + -- + 1 + 3 + 5 + 7 + 9 + + >>> sql("select * from range(5)") + C1 + -- + 1 + 2 + 3 + 4 + 5 + +""" + +import vtbase +registered=True + +class RangeVT(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + largs, dictargs = self.full_parse(parsedArgs) + fromv=0 + tov=10 + stepv=1 + + if 'from' in dictargs: + fromv=int(dictargs['from']) + if 'to' in dictargs: + tov=int(dictargs['to']) + if 'step' in dictargs: + stepv=int(dictargs['step']) + if len(largs)>=1: + fromv=int(largs[0]) + if len(largs)>=2: + tov=int(largs[1]) + if len(largs)>=3: + stepv=int(largs[2]) + if len(largs)==1: + fromv=1 + tov=int(largs[0])+1 + + if 'query' in dictargs: + fromv=1 + tov=int(dictargs['query'])+1 + + yield [('C1', 'int')] + + for i in xrange(fromv,tov,stepv): + yield [i] + +def Source(): + return vtbase.VTGenerator(RangeVT) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/rc2db.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/rc2db.py new file mode 100644 index 0000000..d532cdf --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/rc2db.py @@ -0,0 +1,137 @@ +import os.path +import sys +import functions +import os +from itertools import izip +import cPickle +import cStringIO +import vtbase +import struct +import vtbase +import os +import gc +import re +import zlib +### Classic stream iterator +registered=True +BLOCK_SIZE = 200000000 +import apsw +import time +import marshal + + + +class RC2DB(vtbase.VT): + + + def VTiter(self, *args,**formatArgs): + import bz2 + import msgpack + serializer = msgpack + largs, dictargs = self.full_parse(args) + where = None + mode = 'row' + input = cStringIO.StringIO() + + if 'file' in dictargs: + where=dictargs['file'] + else: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No destination provided") + col = 0 + + filename, ext=os.path.splitext(os.path.basename(where)) + if 'cols' in dictargs: + a = re.split(' |,| , |, | ,' , dictargs['cols']) + column = [x for x in a if x != ''] + else: + col = 1 + start = 0 + end = sys.maxint-1 + if 'start' in dictargs: + start = int(dictargs['start']) + if 'end' in dictargs: + end = int(dictargs['end']) + + fullpath = str(os.path.abspath(os.path.expandvars(os.path.expanduser(os.path.normcase(where))))) + fileIterlist = [] + for x in xrange(start,end+1): + try: + fileIterlist.append(open(fullpath+"."+str(x), "rb")) + except: + break + + if fileIterlist == []: + try: + fileIterlist = [open(where, "rb")] + except : + raise functions.OperatorError(__name__.rsplit('.')[-1],"No such file") + cursor = [] + for filenum,fileObject in enumerate(fileIterlist): + b = struct.unpack('!B',fileObject.read(1)) + schema = cPickle.load(fileObject) + colnum = len(schema) + readtype = '!'+'i'*colnum + readsize = 4 * colnum + + if filenum == 0: + yield schema + + def createdb(where, tname, schema, page_size=16384): + c=apsw.Connection(where) + cursor=c.cursor() + list(cursor.execute('pragma page_size='+str(page_size)+';pragma cache_size=-1000;pragma legacy_file_format=false;pragma synchronous=0;pragma journal_mode=OFF;PRAGMA locking_mode = EXCLUSIVE')) + create_schema='create table '+tname+' (' + create_schema+='`'+unicode(schema[0][0])+'`'+ (' '+unicode(schema[0][1]) if schema[0][1]!=None else '') + for colname, coltype in schema[1:]: + create_schema+=',`'+unicode(colname)+'`'+ (' '+unicode(coltype) if coltype!=None else '') + create_schema+='); begin exclusive;' + list(cursor.execute(create_schema)) + insertquery="insert into "+tname+' values('+','.join(['?']*len(schema))+')' + return c, cursor, insertquery + c, cursor, insertquery=createdb(where+".db", filename, schema) + + while True: + try: + b = struct.unpack('!B',fileObject.read(1)) + except : + break + if b[0]: + input.truncate(0) + ind = struct.unpack(readtype,fileObject.read(readsize)) + input.write(fileObject.read(sum(ind))) + input.seek(0) + gc.disable() + cursor.executemany(insertquery, izip(*tuple(serializer.loads(zlib.decompress(input.read(ind[col]))) for col in xrange(colnum)))) + gc.enable() + elif not b[0]: + schema = cPickle.load(fileObject) + list(cursor.execute('commit')) + c.close() + + try: + for fileObject in fileIterlist: + fileObject.close() + except NameError: + pass + + +def Source(): + return vtbase.VTGenerator(RC2DB) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + + + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/rowidvt.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/rowidvt.py new file mode 100644 index 0000000..df3f33a --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/rowidvt.py @@ -0,0 +1,97 @@ +""" + +.. function:: rowidvt(query:None) + +Returns the query input result adding rowid number of the result row. + +:Returned table schema: + Same as input query schema with addition of rowid column. + + - *rowid* int + Input *query* result rowid. + +Examples:: + + >>> table1(''' + ... James 10 2 + ... Mark 7 3 + ... Lila 74 1 + ... ''') + >>> sql("rowidvt select * from table1") + rowid | a | b | c + ---------------------- + 1 | James | 10 | 2 + 2 | Mark | 7 | 3 + 3 | Lila | 74 | 1 + >>> sql("rowidvt select * from table1 order by c") + rowid | a | b | c + ---------------------- + 1 | Lila | 74 | 1 + 2 | James | 10 | 2 + 3 | Mark | 7 | 3 + + Note the difference with rowid table column. + + >>> sql("select rowid,* from table1 order by c") + rowid | a | b | c + ---------------------- + 3 | Lila | 74 | 1 + 1 | James | 10 | 2 + 2 | Mark | 7 | 3 +""" +import setpath +import vtbase +import functions + +### Classic stream iterator +registered=True + +class RowidVT(vtbase.VT): + def VTiter(self, *parsedArgs, **envars): + largs, dictargs = self.full_parse(parsedArgs) + + self.nonames=True + self.names=[] + self.types=[] + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No query argument ") + query=dictargs['query'] + + cur = envars['db'].cursor() + c=cur.execute(query) + + try: + yield [('rowid', 'integer')] + list(cur.getdescriptionsafe()) + except StopIteration: + try: + raise + finally: + try: + c.close() + except: + pass + i = 1 + for r in c: + yield [i] + list(r) + i += 1 + +def Source(): + return vtbase.VTGenerator(RowidVT) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/sample.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/sample.py new file mode 100644 index 0000000..d75837c --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/sample.py @@ -0,0 +1,110 @@ +""" + +.. function:: sample(sample_size query) -> samples rows from input + +Returns a random sample_size set of rows. + +:Returned table schema: + Same as input query schema. + +Options: + +:size: + + Sample size + +Examples:: + + >>> table1(''' + ... James 10 2 + ... Mark 7 3 + ... Lila 74 1 + ... ''') + >>> sql("sample '10' select * from table1") + a | b | c + -------------- + James | 10 | 2 + Mark | 7 | 3 + Lila | 74 | 1 + + >>> sql("sample size:1 select * from table1") # doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + a | b | c + ... + + >>> sql("sample size:0 select * from table1") + +""" +import setpath +import vtbase +import functions + +registered = True + +class SampleVT(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + largs, dictargs = self.full_parse(parsedArgs) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No query argument ") + query=dictargs['query'] + + samplesize = 1 + + if len(largs) > 0: + samplesize = int(largs[0]) + + + if 'size' in dictargs: + samplesize = int(dictargs['size']) + + try: + samplesize = int(samplesize) + except ValueError: + raise functions.OperatorError(__name__.rsplit('.')[-1],"Sample size should be integer") + + cur = envars['db'].cursor() + c = cur.execute(query, parse = False) + + try: + yield list(cur.getdescriptionsafe()) + except StopIteration: + try: + raise + finally: + try: + c.close() + except: + pass + + from itertools import islice + samplelist = list(islice(c, samplesize)) + index = len(samplelist) + + from random import randint + for i, row in enumerate(c, index): + r = randint(0, i) + if r < samplesize: + samplelist[r] = row + + for r in samplelist: + yield r + +def Source(): + return vtbase.VTGenerator(SampleVT) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/sdc2db.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/sdc2db.py new file mode 100644 index 0000000..3b243f3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/sdc2db.py @@ -0,0 +1,188 @@ +import os.path +import sys +import functions +import os +from itertools import repeat, imap +import cPickle +import cStringIO +import vtbase +import functions +import struct +import vtbase +import os +import re +import zlib +import apsw +from array import array +import marshal + + +if hasattr(sys, 'pypy_version_info'): + from __pypy__ import newlist_hint + + def izip(*iterables): + # izip('ABCD', 'xy') --> Ax By + iterators = tuple(map(iter, iterables)) + ilen = len(iterables) + res = [None] * ilen + while True: + ci = 0 + while ci < ilen: + res[ci] = iterators[ci].next() + ci += 1 + yield res +else: + from itertools import izip + newlist_hint = lambda size: [] + +registered=True + + + +def imapm(function, iterable): + # imap(pow, (2,3,10), (5,2,3)) --> 32 9 1000 + it = iter(iterable) + while True: + yield function(it.next()) + +def repeatm(object, times): + for i in xrange(times): + yield object + +class SDC2DB(vtbase.VT): + + + def VTiter(self, *args,**formatArgs): + import msgpack + import bz2 + serializer = msgpack + largs, dictargs = self.full_parse(args) + where = None + mode = 'row' + input = cStringIO.StringIO() + + if 'file' in dictargs: + where=dictargs['file'] + else: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No destination provided") + col = 0 + + filename, ext=os.path.splitext(os.path.basename(where)) + if 'cols' in dictargs: + a = re.split(' |,| , |, | ,' , dictargs['cols']) + column = [x for x in a if x != ''] + else: + col = 1 + start = 0 + end = sys.maxint-1 + if 'start' in dictargs: + start = int(dictargs['start']) + if 'end' in dictargs: + end = int(dictargs['end']) + + fullpath = str(os.path.abspath(os.path.expandvars(os.path.expanduser(os.path.normcase(where))))) + + fileIterlist = [] + for x in xrange(start,end+1): + try: + fileIterlist.append(open(fullpath+"."+str(x), "rb")) + except: + break + + if fileIterlist == []: + try: + fileIterlist = [open(where, "rb")] + except : + raise functions.OperatorError(__name__.rsplit('.')[-1],"No such file") + cursor = [] + for filenum,fileIter in enumerate(fileIterlist): + blocksize = struct.unpack('!i',fileIter.read(4)) + b = struct.unpack('!B',fileIter.read(1)) + schema = cPickle.load(fileIter) + colnum = len(schema) + if filenum == 0: + yield schema + def createdb(where, tname, schema, page_size=16384): + c=apsw.Connection(where) + cursor=c.cursor() + list(cursor.execute('pragma page_size='+str(page_size)+';pragma cache_size=-1000;pragma legacy_file_format=false;pragma synchronous=0;pragma journal_mode=OFF;PRAGMA locking_mode = EXCLUSIVE')) + create_schema='create table '+tname+' (' + create_schema+='`'+unicode(schema[0][0])+'`'+ (' '+unicode(schema[0][1]) if schema[0][1]!=None else '') + for colname, coltype in schema[1:]: + create_schema+=',`'+unicode(colname)+'`'+ (' '+unicode(coltype) if coltype!=None else '') + create_schema+='); begin exclusive;' + list(cursor.execute(create_schema)) + insertquery="insert into "+tname+' values('+','.join(['?']*len(schema))+')' + return c, cursor, insertquery + cur, cursor, insertquery=createdb(where+".db", filename, schema) + input = cStringIO.StringIO() + + + while True: + input.truncate(0) + try: + blocksize = struct.unpack('!i', fileIter.read(4)) + except: + break + if blocksize[0]: + input.write(fileIter.read(blocksize[0])) + input.seek(0) + b = struct.unpack('!B', input.read(1)) + if b[0]: + decompression = struct.unpack('!B', input.read(1)) + if decompression[0] : + decompress = zlib.decompress + else: + decompress = bz2.decompress + + type = '!'+'i'*(colnum*2+1) + ind = list(struct.unpack(type, input.read(4*(colnum*2+1)))) + + cols = [None]*colnum + for c in xrange(colnum): + s = serializer.loads(decompress(input.read(ind[c*2]))) + if (len(s)>1 and ind[c*2+1]==0 and ind[colnum*2]>1): + cols[c] = s + else: + if len(s)==1: + tmp = s[0] + cols[c] = repeat(tmp, ind[colnum*2]) + elif len(s)<256: + cols[c] = imap(s.__getitem__, array('B', decompress(input.read(ind[c*2+1])))) + else: + cols[c] = imap(s.__getitem__, array('H', decompress(input.read(ind[c*2+1])))) + + # for r in izip(*cols): + # pass + cursor.executemany(insertquery, izip(*cols)) + + elif not b[0]: + schema = cPickle.load(fileIter) + list(cursor.execute('commit')) + cur.close() + try: + for fileObject in fileIterlist: + fileObject.close() + except NameError: + pass + +def Source(): + return vtbase.VTGenerator(SDC2DB) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + + + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/setpath.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/setpath.py new file mode 100644 index 0000000..1dc6e8d --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/setpath.py @@ -0,0 +1,2 @@ +import sys, os +sys.path.append((os.path.join(sys.path[0],'..','..'))) \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/setschema.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/setschema.py new file mode 100644 index 0000000..dec0545 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/setschema.py @@ -0,0 +1,155 @@ +""" + +.. function:: setschema(query:None,schemadefinition) + + Returns the result of the input *query* with changed schema according to *schemadefinition* parameter. + Parameter *schemadefinition* is text identical to schema definition between parenthesis of a CREATE TABLE SQL statement. + + Can perform renaming, typecasting and projection on some columns of the input *query* result. + +.. note:: + + This function can be used to avoid DynamicSchemaWithEmptyResultError caused by dynamic schema virtual tables on empty query input result. + + .. toadd link. + + + +:Returned table schema: + As defined at *schemadefinition* parameter. + + +Examples:: + + >>> sql("setschema 'col1 int,col2 text' select 5,6") + col1 | col2 + ----------- + 5 | 6 + + >>> sql("select strsplitv(q) from (select 5 as q) where q!=5") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + DynamicSchemaWithEmptyResultError: Madis SQLError: + Operator EXPAND: Cannot initialise dynamic schema virtual table without data + + >>> sql("setschema 'a,b' select strsplitv(q) from (select 5 as q) where q!=5") + a | b + ----- + + >>> sql("select * from (file file:testing/colpref.csv dialect:csv header:t) limit 3") + userid | colid | preference | usertype + -------------------------------------- + agr | | 6617580.0 | agr + agr | a0037 | 2659050.0 | agr + agr | a0086 | 634130.0 | agr + +The query below has constraints preference column to be less than an int value , but preference is text ( outcomes from :func:`~functions.vtable.file.file` are *text*), so an empty result is produced + + >>> sql("select * from (select * from (file file:testing/colpref.csv dialect:csv header:t) limit 3) where cast(preference as int) <634130") + +With setschema functions preference column is casted as float. + + >>> sql("select * from (setschema 'type,colid , pref float, userid' select * from (file file:testing/colpref.csv dialect:csv header:t) limit 3) where pref<634131") + type | colid | pref | userid + -------------------------------- + agr | a0086 | 634130.0 | agr + +""" +from lib.sqlitetypes import typestoSqliteTypes +import vtbase +import functions +from lib.pyparsing import Word, alphas, alphanums, Optional, Group, delimitedList, quotedString , ParseBaseException + +registered=True + +ident = Word(alphas+"_",alphanums+"_") +columnname = ident | quotedString +columndecl = Group(columnname + Optional(ident)) +listItem = columndecl + +def parsesplit(s): + global listItem + return delimitedList(listItem).parseString(s,parseAll=True).asList() + +def checkexceptionisfromempty(e): + e=str(e).lower() + if 'no' in e and 'such' in e and 'table' in e and 'vt_' in e: + return True + return False + +class SetSchema(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + """ + Works only with one argument splited with ,,,, + """ + + largs, dictargs = self.full_parse(parsedArgs) + + names = [] + types = [] + + if len(largs)<1: + raise functions.OperatorError(__name__.rsplit('.')[-1]," Schema argument was not provided") + try: + schema=parsesplit(largs[0]) + except ParseBaseException: + raise functions.OperatorError(__name__.rsplit('.')[-1]," Error in schema definition: %s" %(largs[0])) + for el in schema: + names.append(el[0]) + if len(el)>1: + types.append(el[1]) + else: + types.append('') + + query = dictargs['query'] + c=envars['db'].cursor() + + ### Find names and types + execit=c.execute(query) + qtypes=[str(v[1]) for v in c.getdescriptionsafe()] + + for i in xrange(len(types)): + if types[i]=='' and i query results + +Returns the query input results annotated with the window id as an extra column. +The window parameter defines the size of the window. + +:Returned table schema: + Same as input query schema. + +Examples:: + + >>> table1(''' + ... James 10 + ... Mark 7 + ... Lila 74 + ... Jane 44 + ... ''') + >>> sql("slidingwindow window:2 select * from table1") + wid | a | b + ---------------- + 0 | James | 10 + 1 | James | 10 + 1 | Mark | 7 + 2 | Mark | 7 + 2 | Lila | 74 + 3 | Lila | 74 + 3 | Jane | 44 + >>> sql("slidingwindow window:3 select * from table1") + wid | a | b + ---------------- + 0 | James | 10 + 1 | James | 10 + 1 | Mark | 7 + 2 | James | 10 + 2 | Mark | 7 + 2 | Lila | 74 + 3 | Mark | 7 + 3 | Lila | 74 + 3 | Jane | 44 + + +""" + +import setpath +import vtbase +import functions +import gc +from collections import deque + +### Classic stream iterator +registered=True + +class SlidingWindow(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + largs, dictargs = self.full_parse(parsedArgs) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No query argument ") + query=dictargs['query'] + + if 'window' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No window argument ") + + cur=envars['db'].cursor() + c=cur.execute(query, parse = False) + + try: + yield [('wid','integer')] + list(cur.getdescriptionsafe()) + except StopIteration: + try: + raise + finally: + try: + c.close() + except: + pass + + wid=0 + window=deque([], int(dictargs['window'])) + while True: + window.append(c.next()) + for r in window: + yield (wid,) + r + wid+=1 + +def Source(): + return vtbase.VTGenerator(SlidingWindow) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/sqlite.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/sqlite.py new file mode 100644 index 0000000..2bb1ec7 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/sqlite.py @@ -0,0 +1,68 @@ +""" +.. function:: sqlite(dbfilename, query:None) + +Connects to an SQLite DB and returns the results of query. + +Examples: + + >>> sql("select * from (sqlite 'testdb.db' select 5 as num, 'test' as text);") + num | text + ----------- + 5 | test + +""" + +import setpath +import vtbase +import functions +import os + +registered=True +external_query = True + +class SQLite(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + largs, dictargs = self.full_parse(parsedArgs) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No query argument ") + + query=dictargs['query'] + + if len(largs) > 0: + sqdb = largs[0] + + if 'db' in dictargs: + sqdb = dictargs['db'] + + sqdb = str(os.path.abspath(os.path.expandvars(os.path.expanduser(os.path.normcase(sqdb))))) + conn = functions.Connection(sqdb) + + cur = conn.cursor() + cur.execute(query) + + yield cur.getdescriptionsafe() + + while True: + yield cur.next() + + cur.close() + +def Source(): + return vtbase.VTGenerator(SQLite) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/stdinput.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/stdinput.py new file mode 100644 index 0000000..e151fb7 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/stdinput.py @@ -0,0 +1,50 @@ +""" +.. function:: stdinput() -> standard input stream + +Returns the standard input stream + +:Returned table schema: + One column automatically named C1. + +Examples:: + >>> sql("select * from stdinput()") + c1 + ------------- + stdinputline1 + stdinputline2 + stdinputline3 +""" +import sys +import vtbase + +registered=True + +class StdInput(vtbase.VT): + def VTiter(self, *args,**formatArgs): + yield [('C1', 'text')] + + while True: + a = sys.stdin.readline() + if not a: + break + yield (unicode(a.rstrip('\r\n'), 'utf_8'),) + +def Source(): + return vtbase.VTGenerator(StdInput) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/GeoIPCountryCSV.zip b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/GeoIPCountryCSV.zip new file mode 100644 index 0000000..061e059 Binary files /dev/null and b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/GeoIPCountryCSV.zip differ diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/colpref.csv b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/colpref.csv new file mode 100644 index 0000000..4cf0904 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/colpref.csv @@ -0,0 +1,20 @@ +userid,colid,preference,usertype +agr,,6617580.0,agr +agr,a0037,2659050.0,agr +agr,a0086,634130.0,agr +agr,a0141,416900.0,agr +agr,a0010,408170.0,agr +agr,a0000,337300.0,agr +agr,a0132,254590.0,agr +agr,a0211,207030.0,agr +agr,a0262,184900.0,agr +agr,a0035,174850.0,agr +agr,a0130,148340.0,agr +agr,a0314,115990.0,agr +agr,a0075,111520.0,agr +agr,a0073,110880.0,agr +agr,a0001,106750.0,agr +agr,a0081,100370.0,agr +agr,a0038,93420.0,agr +agr,a0232,92900.0,agr +agr,a0200,92410.0,agr \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/colpref.tsv b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/colpref.tsv new file mode 100644 index 0000000..c89bdd9 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/colpref.tsv @@ -0,0 +1,20 @@ +agr||6617580.0|agr +agr|a0037|2659050.0|agr +agr|a0086|634130.0|agr +agr|a0141|416900.0|agr +agr|a0010|408170.0|agr +agr|a0000|337300.0|agr +agr|a0132|254590.0|agr +agr|a0211|207030.0|agr +agr|a0262|184900.0|agr +agr|a0035|174850.0|agr +agr|a0130|148340.0|agr +agr|a0314|115990.0|agr +agr|a0075|111520.0|agr +agr|a0073|110880.0|agr +agr|a0001|106750.0|agr +agr|a0081|100370.0|agr +agr|a0038|93420.0|agr +agr|a0232|92900.0|agr +agr|a0200|92410.0|agr +agr|a0066|88350.0|agr diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/colpref.tsv.gz b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/colpref.tsv.gz new file mode 100644 index 0000000..8c5213c Binary files /dev/null and b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/colpref.tsv.gz differ diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/colpref.zip b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/colpref.zip new file mode 100644 index 0000000..9028ab4 Binary files /dev/null and b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/colpref.zip differ diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/internalflow.sql b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/internalflow.sql new file mode 100644 index 0000000..de57ef3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/internalflow.sql @@ -0,0 +1 @@ +create table %{tablename} as select * from getvars() where variable!='execdb'; \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/testflow.sql b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/testflow.sql new file mode 100644 index 0000000..5fd4031 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/testflow.sql @@ -0,0 +1,17 @@ +/*====== countries: table of Country ISO codes , country names ===========*/ +CREATE TABLE countries ( + country2 PRIMARY KEY UNIQUE, + country_name +); +insert into countries select country2, country_name from (file 'countries.tsv' delimiter:\t quoting:QUOTE_NONE header:t); +/*====== ilang Table Interface languages (name and portal lang code) ===========*/ +CREATE TABLE ilang ( + lang_name TEXT, + lang TEXT +); +insert into ilang select lang_name , lang from (file 'ilang.tsv' delimiter:\t quoting:QUOTE_NONE header:t ); +/*====== User_countries: table of id's of registered user's code ===========*/ +CREATE TABLE user_countries ( + country PRIMARY KEY, + country_name +); diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/testtable.sql b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/testtable.sql new file mode 100644 index 0000000..ca1bf3c --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/testtable.sql @@ -0,0 +1,4 @@ +create table table1 (a,b,c); +insert into table1 values('James',10,2); +insert into table1 values('Mark',7,3); +insert into table1 values('Lila',74,1); diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/topflow.sql b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/topflow.sql new file mode 100644 index 0000000..2b545e9 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/testing/topflow.sql @@ -0,0 +1,5 @@ +var 'v' 5; +var 'tablename' 'internaltable'; +var 'lastdate' from select '2008-01-01'; +create table topflowvars as select * from getvars() where variable!='execdb'; +exec 'tablename' 'c:v' file 'internalflow.sql'; \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/timeslidingwindow.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/timeslidingwindow.py new file mode 100644 index 0000000..3a237d9 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/timeslidingwindow.py @@ -0,0 +1,211 @@ +""" + +.. function:: timeslidingwindow(timewindow, timecolumn) -> query results + +Returns the query input results annotated with the window id as an extra column. +The following arguments can be passed as parameters: + +timewindow: It can be a numeric value that specifies the time length of +the window (in seconds). + +timecolumn: It is the index of the temporal column (starting from 0) For +the moment, we assume that the data is ordered by the temporal column that + the user gives as input in ascending order. + + + + + Examples:: + + >>> table1(''' + ... "12.05.2010 00:00:00" + ... "12.05.2010 00:01:00" + ... "12.05.2010 00:02:00" + ... "12.05.2010 00:03:00" + ... "12.05.2010 00:04:00" + ... ''') + >>> sql("timeslidingwindow timewindow:180 timecolumn:0 select * from table1") + wid | a + ------------------------- + 0 | 12.05.2010 00:00:00 + 0 | 12.05.2010 00:01:00 + 0 | 12.05.2010 00:02:00 + 0 | 12.05.2010 00:03:00 + 1 | 12.05.2010 00:01:00 + 1 | 12.05.2010 00:02:00 + 1 | 12.05.2010 00:03:00 + 1 | 12.05.2010 00:04:00 + >>> table1(''' + ... "12.05.2010 00:00:00" + ... "12.05.2010 00:01:00" + ... "12.05.2010 00:01:00" + ... "12.05.2010 00:02:00" + ... "12.05.2010 00:03:00" + ... "12.05.2010 00:04:00" + ... "12.05.2010 00:05:00" + ... ''') + + ... ''') + >>> sql("timeslidingwindow timewindow:120 timecolumn:0 select * from table1") + wid | a + ------------------------- + 0 | 12.05.2010 00:00:00 + 0 | 12.05.2010 00:01:00 + 0 | 12.05.2010 00:01:00 + 0 | 12.05.2010 00:02:00 + 1 | 12.05.2010 00:01:00 + 1 | 12.05.2010 00:01:00 + 1 | 12.05.2010 00:02:00 + 1 | 12.05.2010 00:03:00 + 2 | 12.05.2010 00:02:00 + 2 | 12.05.2010 00:03:00 + 2 | 12.05.2010 00:04:00 + 3 | 12.05.2010 00:03:00 + 3 | 12.05.2010 00:04:00 + 3 | 12.05.2010 00:05:00 + + >>> table2(''' + ... "12/05/2010 00:00:00" + ... "12/05/2010 00:01:00" + ... "12/05/2010 00:02:00" + ... ''') + + + ... ''') + >>> sql("timeslidingwindow timewindow:180 timecolumn:0 select * from table2") + wid | a + ------------------------- + 0 | 12/05/2010 00:00:00 + 0 | 12/05/2010 00:01:00 + 0 | 12/05/2010 00:02:00 + +""" + +import setpath +import vtbase +import functions +from collections import deque +import time +from lib.dateutil import parser + +### Classic stream iterator +registered = True + + +class TimeSlidingWindow(vtbase.VT): + def VTiter(self, *parsedArgs, **envars): + largs, dictargs = self.full_parse(parsedArgs) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1], "No query argument ") + query = dictargs['query'] + + if 'timewindow' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1], "No TimeWindow argument ") + else: + winlen = int(dictargs['timewindow']) + + if 'timecolumn' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1], "No timecolumn argument ") + else: + timecolumn = int(dictargs['timecolumn']) + + cur = envars['db'].cursor() + + c = cur.execute(query, parse=False) + + try: + yield [('wid', 'integer')] + list(cur.getdescriptionsafe()) + except StopIteration: + try: + raise + finally: + try: + c.close() + except: + pass + + wid = 0 + secs = 0 + row = c.next() + firstTime = int(time.mktime(parser.parse(row[timecolumn], fuzzy=True).timetuple())) + + head = {firstTime: [row]} + window = deque([]) + while row: + prev = row + + try: + row = c.next() + except StopIteration: + if wid == 0: + for k in head.keys(): + for t in head[k]: + yield (wid,) + t + for rl in window: + for k in rl.keys(): + for t in rl[k]: + yield (wid,) + t + break + + secs = int(time.mktime(parser.parse(row[timecolumn], fuzzy=True).timetuple())) + + if secs <= firstTime + winlen: + if prev[0] == row[timecolumn] and window: + old = window.pop()[secs] + old.append(row) + rowlist = {secs: old} + else: + rowlist = {secs: [row]} + + window.append(rowlist) + else: + if wid == 0: + for k in head.keys(): + for t in head[k]: + yield (wid,) + t + for rl in window: + for k in rl.keys(): + for t in rl[k]: + yield (wid,) + t + while secs > firstTime + winlen and window: + try: + head = window.popleft() + firstTime = head.keys()[0] + except IndexError: + break + + rowlist = {secs: [row]} + window.append(rowlist) + wid += 1 + for k in head.keys(): + for t in head[k]: + yield (wid,) + t + for rl in window: + for k in rl.keys(): + for t in rl[k]: + yield (wid,) + t + + + + +def Source(): + return vtbase.VTGenerator(TimeSlidingWindow) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/toeav.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/toeav.py new file mode 100644 index 0000000..a0b2d77 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/toeav.py @@ -0,0 +1,84 @@ +""" + +.. function:: toeav(query) -> Entity Attribute Value table + +Transforms the query input results to an Entity Attribute Value model table. + +:Returned table schema: + ID, Attribute, Value + +Examples:: + + >>> table1(''' + ... James 10 2 + ... Mark 7 3 + ... Lila 74 1 + ... ''') + >>> sql("toeav select * from table1") + rid | colname | val + --------------------- + James | b | 10 + James | c | 2 + Mark | b | 7 + Mark | c | 3 + Lila | b | 74 + Lila | c | 1 +""" +import setpath +import vtbase +import functions +import gc + +### Classic stream iterator +registered=True + +class toEAV(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + largs, dictargs = self.full_parse(parsedArgs) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No query argument ") + query = dictargs['query'] + + cur = envars['db'].cursor() + c = cur.execute(query, parse=False) + schema = [] + + try: + schema = [x[0] for x in cur.getdescriptionsafe()] + except StopIteration: + try: + raise + finally: + try: + c.close() + except: + pass + + yield [('rid',), ('colname',), ('val',)] + lr = len(schema) + while True: + l = c.next() + rid = l[0] + for i in xrange(1, lr): + yield (rid, schema[i], l[i]) + +def Source(): + return vtbase.VTGenerator(toEAV) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/unindexed.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/unindexed.py new file mode 100644 index 0000000..ad80d6a --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/unindexed.py @@ -0,0 +1,86 @@ +""" + +.. function:: unindexed(query) -> query results + +Returns the query input results without any change. UNINDEXED can be used as a +barrier for SQLite's optimizer, for debugging etc. + +:Returned table schema: + Same as input query schema. + +Examples:: + + >>> table1(''' + ... James 10 2 + ... Mark 7 3 + ... Lila 74 1 + ... ''') + >>> sql("unindexed select * from table1") + a | b | c + -------------- + James | 10 | 2 + Mark | 7 | 3 + Lila | 74 | 1 + + >>> sql("unindexed select * from table1 order by c") + a | b | c + -------------- + Lila | 74 | 1 + James | 10 | 2 + Mark | 7 | 3 + + Note the difference with rowid table column. + +""" +import setpath +import vtbase +import functions +import gc + +### Classic stream iterator +registered=True + +class NopVT(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + largs, dictargs = self.full_parse(parsedArgs) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No query argument ") + query=dictargs['query'] + + cur=envars['db'].cursor() + c=cur.execute(query, parse = False) + + try: + yield list(cur.getdescriptionsafe()) + except StopIteration: + try: + raise + finally: + try: + c.close() + except: + pass + + while True: + yield c.next() + +def Source(): + return vtbase.VTGenerator(NopVT) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/unionalldb.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/unionalldb.py new file mode 100644 index 0000000..7bfdb94 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/unionalldb.py @@ -0,0 +1,126 @@ +""" +.. function:: unionalldb(db_filename) + +This function returns the contents of a table that has been split using OUTPUT split functionality. + +Its input are DBs with names such as: + + dbname.0.db + dbname.1.db + ... + +It is assumed that inside each of above DBs, a table named as *dbname* will exist. All of these +tables should have the same schema + +If a *start* or *end* argument is present then *unionalldb* will start scanning from the *start* numbered part +and end scanning at *end* numbered db part (without including the *end* numbered part). + +Usage examples: + + select * from (unionalldb 'dbname'); + + select * from (unionalldb start:1 end:4 'dbname'); + +""" +import vtbase +import functions +import apsw +import os +import sys +import gc + +registered=True + +class UnionAllDB(vtbase.VT): + def findschema(self): + try: + # Try to get the schema the normal way + schema = self.xcursor.getdescription() + except apsw.ExecutionCompleteError: + # Else create a tempview and query the view + list(self.xcursor.execute('create temp view temp.___schemaview as '+ self.query + ';')) + schema = [(x[1], x[2]) for x in list(self.xcursor.execute('pragma table_info(___schemaview);'))] + list(self.xcursor.execute('drop view temp.___schemaview;')) + + return schema + + def VTiter(self, *parsedArgs,**envars): + opts=self.full_parse(parsedArgs) + + self.query=None + + self.start = 0 + self.end = sys.maxint + + if 'start' in opts[1]: + self.start = int(opts[1]['start']) + + if 'end' in opts[1]: + self.end = int(opts[1]['end']) + + try: + dbname=opts[0][0] + except: + raise functions.OperatorError(__name__.rsplit('.')[-1],"A DB filename should be provided") + + try: + self.query=opts[1]['query'] + except: + pass + + self.dbfile = str(os.path.abspath(os.path.expandvars(os.path.expanduser(os.path.normcase(dbname))))) + + tablename = os.path.split(self.dbfile)[1] + if 'tablename' in opts[1]: + tablename=opts[1]['tablename'] + + if 'table' in opts[1]: + tablename=opts[1]['table'] + + if self.query == None: + self.query = 'select * from '+tablename+';' + + self.part = self.start + try: + self.xcon=apsw.Connection(self.dbfile+'.' + str(self.part) + '.db', flags=apsw.SQLITE_OPEN_READONLY) + except Exception,e: + print e + raise functions.OperatorError(__name__.rsplit('.')[-1],"DB could not be opened") + + self.xcursor=self.xcon.cursor() + self.xexec=self.xcursor.execute(self.query) + yield self.findschema() + + while self.part < self.end: + try: + self.xcon = apsw.Connection(self.dbfile+'.' + str(self.part) + '.db', flags=apsw.SQLITE_OPEN_READONLY) + self.xcursor = self.xcon.cursor() + self.xexec =self.xcursor.execute(self.query) + except apsw.CantOpenError,e: + raise StopIteration + + gc.disable() + for row in self.xexec: + yield row + gc.enable() + + self.part += 1 + +def Source(): + return vtbase.VTGenerator(UnionAllDB) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/unionallrcfiles.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/unionallrcfiles.py new file mode 100644 index 0000000..de884fe --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/unionallrcfiles.py @@ -0,0 +1,116 @@ +import os.path +import sys +import functions +import os +from itertools import izip +import cPickle +import cStringIO +import vtbase +import functions +import struct +import vtbase +import functions +import os +import gc +import re +import zlib +### Classic stream iterator +registered=True +BLOCK_SIZE = 200000000 +import marshal + + +class UnionAllRC(vtbase.VT): + + + def VTiter(self, *args,**formatArgs): + import bz2 + import msgpack + serializer = msgpack + largs, dictargs = self.full_parse(args) + where = None + mode = 'row' + input = cStringIO.StringIO() + + if 'file' in dictargs: + where=dictargs['file'] + else: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No destination provided") + col = 0 + + if 'cols' in dictargs: + a = re.split(' |,| , |, | ,' , dictargs['cols']) + column = [x for x in a if x != ''] + else: + col = 1 + start = 0 + end = sys.maxint-1 + if 'start' in dictargs: + start = int(dictargs['start']) + if 'end' in dictargs: + end = int(dictargs['end']) + + fullpath = str(os.path.abspath(os.path.expandvars(os.path.expanduser(os.path.normcase(where))))) + fileIterlist = [] + for x in xrange(start,end+1): + try: + fileIterlist.append(open(fullpath+"."+str(x), "rb")) + except: + break + + if fileIterlist == []: + try: + fileIterlist = [open(where, "rb")] + except : + raise functions.OperatorError(__name__.rsplit('.')[-1],"No such file") + + for filenum,fileObject in enumerate(fileIterlist): + b = struct.unpack('!B',fileObject.read(1)) + schema = cPickle.load(fileObject) + colnum = len(schema) + readtype = '!'+'i'*colnum + readsize = 4 * colnum + if filenum == 0: + yield schema + + while True: + try: + b = struct.unpack('!B',fileObject.read(1)) + except : + break + if b[0]: + input.truncate(0) + ind = struct.unpack(readtype,fileObject.read(readsize)) + input.write(fileObject.read(sum(ind))) + input.seek(0) + for row in izip(*tuple(serializer.loads(zlib.decompress(input.read(ind[col]))) for col in xrange(colnum))): + yield row + elif not b[0]: + schema = cPickle.load(fileObject) + + try: + for fileObject in fileIterlist: + fileObject.close() + except NameError: + pass + + +def Source(): + return vtbase.VTGenerator(UnionAllRC) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/unionallsdc.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/unionallsdc.py new file mode 100644 index 0000000..8d054f3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/unionallsdc.py @@ -0,0 +1,152 @@ +import os.path +import sys +import functions +import os +from itertools import izip, repeat, imap +import cPickle +import cStringIO +import vtbase +import struct +import os +import gc +import re +import zlib +from array import array +import marshal +### Classic stream iterator +registered=True +BLOCK_SIZE = 200000000 + +class UnionAllSDC(vtbase.VT): + + + def VTiter(self, *args,**formatArgs): + import bz2 + import msgpack + serializer = msgpack + largs, dictargs = self.full_parse(args) + where = None + mode = 'row' + input = cStringIO.StringIO() + + if 'file' in dictargs: + where=dictargs['file'] + else: + raise functions.OperatorError(__name__.rsplit('.')[-1],"No destination provided") + col = 0 + + if 'cols' in dictargs: + a = re.split(' |,| , |, | ,' , dictargs['cols']) + column = [x for x in a if x != ''] + else: + col = 1 + start = 0 + end = sys.maxint-1 + if 'start' in dictargs: + start = int(dictargs['start']) + if 'end' in dictargs: + end = int(dictargs['end']) + + fullpath = str(os.path.abspath(os.path.expandvars(os.path.expanduser(os.path.normcase(where))))) + fileIterlist = [] + for x in xrange(start,end+1): + try: + fileIterlist.append(open(fullpath+"."+str(x), "rb")) + except: + break + + if fileIterlist == []: + try: + fileIterlist = [open(where, "rb")] + except : + raise functions.OperatorError(__name__.rsplit('.')[-1],"No such file") + + for filenum,fileIter in enumerate(fileIterlist): + blocksize = struct.unpack('!i',fileIter.read(4)) + b = struct.unpack('!B',fileIter.read(1)) + schema = cPickle.load(fileIter) + colnum = len(schema) + if filenum == 0: + yield schema + input = cStringIO.StringIO() + while True: + + input.truncate(0) + try: + blocksize = struct.unpack('!i', fileIter.read(4)) + except: + break + if blocksize[0]: + input.write(fileIter.read(blocksize[0])) + input.seek(0) + b = struct.unpack('!B', input.read(1)) + if b[0]: + decompression = struct.unpack('!B', input.read(1)) + if decompression[0] : + decompress = zlib.decompress + else: + decompress = bz2.decompress + + type = '!'+'i'*(colnum*2+1) + ind = list(struct.unpack(type, input.read(4*(colnum*2+1)))) + cols = [None] * colnum + for c in xrange(colnum): + s = serializer.loads(decompress(input.read(ind[c*2]))) + if (len(s)>1 and ind[c*2+1]==0 and ind[colnum*2]>1): + cols[c] = s + else: + if len(s)==1: + cols[c] = repeat(s[0], ind[colnum*2]) + elif len(s)<256: + cols[c] = imap(s.__getitem__, array('B', decompress(input.read(ind[c*2+1])))) + else: + cols[c] = imap(s.__getitem__, array('H', decompress(input.read(ind[c*2+1])))) + + if hasattr(sys, 'pypy_version_info'): + iterators = tuple(map(iter, cols)) + ilen = len(cols) + res = [None] * ilen + + while True: + ci = 0 + try: + while ci < ilen: + res[ci] = iterators[ci].next() + ci += 1 + yield res + except: + break + + else: + for row in izip(*cols): + yield row + + elif not b[0]: + schema = cPickle.load(fileIter) + + try: + for fileObject in fileIterlist: + fileObject.close() + except NameError: + pass + + +def Source(): + return vtbase.VTGenerator(UnionAllSDC) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/variables.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/variables.py new file mode 100644 index 0000000..a03e4d6 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/variables.py @@ -0,0 +1,59 @@ +""" +.. function:: variables() + +Returns the defined variables with their values. + +:Returned table schema: + - *variable* text + Variable name. + - *value* text + Variable value + +.. toadd See also variables.. + +Examples: + + >>> sql("var 'env' 'testing' ") + var('env','testing') + -------------------- + testing + >>> sql("variables") + variable | value + ------------------- + flowname | + execdb | :memory: + env | testing + + +""" + +import vtbase +import functions +registered=True + +class Variables(vtbase.VT): + def VTiter(self, *parsedArgs,**envars): + yield [('variable', 'text'),('value', 'text')] + + for i in functions.variables.__dict__: + yield [i,functions.variables.__dict__[i]] + +def Source(): + return vtbase.VTGenerator(Variables) + + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/vtbase.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/vtbase.py new file mode 100644 index 0000000..336ebc1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/vtbase.py @@ -0,0 +1,218 @@ +""" +Basis code for Virtual table. The schema is extracted from firstrow. +""" + +import setpath +import functions +import apsw +from lib import argsparse ,schemaUtils +import sys +if hasattr(sys, 'pypy_version_info'): + PYPY = True + from __pypy__ import newlist_hint +else: + PYPY = False + newlist_hint = lambda size: [] + +autostring='automatic_vtable:1' + +# Decorator to extended a function by calling first another function with no arguments +def echocall(func): + def wrapper(*args, **kw): + if functions.settings['vtdebug']: + obj=args[0] + Extra="" + if 'tablename' in obj.__dict__: + Extra=obj.tablename + print "Table %s:Before Calling %s.%s(%s)" %(Extra+str(obj),obj.__class__.__name__,func.__name__,','.join([repr(l) for l in args[1:]]+["%s=%s" %(k,repr(v)) for k,v in kw.items()])) + return func(*args, **kw) + return wrapper + +class VT(object): + def parse(self,*args): + return args + def full_parse(self,args,boolargs=None,nonstringargs=None,needsescape=None, notsplit=None): + return argsparse.parse(args,boolargs,nonstringargs,needsescape,notsplit) + def open(self,*args,**kargs): + raise NotImplementedError + def disconnect(self): + pass + def destroy(self): + pass + +class VTGenerator(object): + def __init__(self,fobj): ####parse auto argument and throw!!!! + self.tableObjs=dict() + self.fobj=fobj + + @echocall + def Create(self, db, modulename, dbname, tablename,*args): + envars={'tablename':tablename,'db':db,'dbname':dbname,'modulename':modulename} + uargs=[argsparse.unquote(a) for a in args] + if len(uargs)>0 and uargs[-1]==autostring: + auto=True + uargs=uargs[:-1] + TableVT=self.fobj() + parsedArgs = list(TableVT.parse(*uargs)) + iterFunc = lambda:TableVT.VTiter(*parsedArgs,**envars) + openedIter = iterFunc() + + try: + schema = openedIter.next() + except (StopIteration,apsw.ExecutionCompleteError),e: + try: + if hasattr(openedIter,'close'): + openedIter.close() + openedIter = None + except: + pass + raise functions.DynamicSchemaWithEmptyResultError(envars['modulename']) + except apsw.AbortError: + openedIter.close() + openedIter = iterFunc() + schema = openedIter.next() + + self.tableObjs[tablename]=(schemaUtils.CreateStatement(schema,tablename),LTable(self.tableObjs, envars, TableVT, iterFunc, openedIter)) + if functions.settings['tracing']: + print 'VT_Schema: %s' %(self.tableObjs[tablename][0]) + return self.tableObjs[tablename] + @echocall + def Connect(self, db, modulename, dbname, tablename,*args): + if tablename not in self.tableObjs: + return self.Create( db, modulename, dbname, tablename,*args) + return self.tableObjs[tablename] + +class LTable(object): ####Init means setschema and execstatus + @echocall + def __init__(self, tblist, envars, tableObj , iterFunc ,openedIter=None): # tablename, auto , cursorfunc, ommit tuple OPTIONAL [] + self.tblist=tblist + self.envars=envars + self.iterFunc=iterFunc + self.openedIter=openedIter + self.tableObj=tableObj + self.cursors = [] + + @echocall + def BestIndex(self, *args): + try: + return self.tableObj.BestIndex(*args) + except AttributeError: + if functions.SQLITEAFTER380: + return (None, 0, None, False, 1e99) + else: + return (None, 0, None, False, 1000) + + @echocall + def Open(self): + tmpIter = None + if self.openedIter == None: + tmpIter = self.iterFunc() + tmpIter.next() + else: + tmpIter = self.openedIter + self.openedIter = None + + c = Cursor(self.iterFunc, tmpIter, self.envars) + self.cursors.append(c) + return c + + def CloseCursors(self): + for c in self.cursors: + c.Close() + self.cursors = [] + + @echocall + def Disconnect(self): + """ + This method is called when a reference to a virtual table is no longer used + """ + self.CloseCursors() + if self.tableObj.__class__.__dict__.has_key('disconnect'): + self.tableObj.disconnect() + + @echocall + def Destroy(self): + """ + This method is called when the table is no longer used + """ + self.CloseCursors() + del self.tblist[self.envars['tablename']] + if self.tableObj.__class__.__dict__.has_key('destroy'): + self.tableObj.destroy() + +# Represents a cursor +class Cursor(object): ##### Needs Cursor Function , Iterator instance, tablename ...... if has close + __slots__ = ("Column", "Next", "Eof", "Rowid", "iterNext", "pos", "row", "eof", "envars", "firsttime", "openIter", "iterFunc") + + @echocall + def __init__(self, iterFunc, openIter, envars): + self.envars = envars + self.firsttime = True + self.openIter=openIter + self.iterNext = self.openIter.next + self.iterFunc=iterFunc + self.row = [] + self.eof = False + self.pos = 0 + self.Column = lambda col: self.row[col] + self.Rowid = lambda: self.pos + 1 + self.Eof = lambda: self.eof + if PYPY: + self.Next = self.NextPyPy + else: + self.Next = self.NextCPython + + # @echocall + def Filter(self, *args): + self.eof=False + self.pos=0 + + if not self.firsttime: + if hasattr(self.openIter,'close'): + self.openIter.close() + self.openIter=self.iterFunc() + self.iterNext = self.openIter.next + self.iterNext() + + self.firsttime=False + self.Next() + return + + #@echocall #-- Commented out for speed reasons + # def Eof(self): + # return self.eof + + #@echocall #-- Commented out for speed reasons + # def Rowid(self): + # return self.pos + + #@echocall #-- Commented out for speed reasons + # def Column(self, col): + # return self.row[col] + + #@echocall #-- Commented out for speed reasons + def NextCPython(self): + try: + self.row = self.iterNext() + self.Column = self.row.__getitem__ +# self.pos+=1 + except StopIteration: + self.row = [] + self.eof = True + self.Close() + + def NextPyPy(self): + try: + self.row = self.iterNext() +# self.pos+=1 + except StopIteration: + self.row = [] + self.eof = True + self.Close() + + # @echocall + def Close(self): + if hasattr(self.openIter, 'close'): + self.openIter.close() + self.openIter = None + diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/vtiterable.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/vtiterable.py new file mode 100644 index 0000000..3a8da07 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/vtiterable.py @@ -0,0 +1,267 @@ +""" +Basis code for +OnetoN and NtoN operators +""" + +import setpath +import functions +import apsw +from lib import argsparse + +from lib import schemaUtils + + +# Decorator to extended a function by calling first another function with no arguments + +def echocall(func): + def wrapper(*args, **kw): + if functions.settings['vtdebug']: + obj=args[0] + Extra="" + if 'tablename' in obj.__dict__: + Extra=obj.tablename + print "Table %s:Before Calling %s.%s(%s)" %(Extra+str(obj),obj.__class__.__name__,func.__name__,','.join([repr(l) for l in args[1:]]+["%s=%s" %(k,repr(v)) for k,v in kw.items()])) +# aftermsg="Table %s:After Calling %s.%s(%s)" %(Extra,obj.__class__.__name__,func.__name__,','.join([repr(l) for l in args[1:]]+["%s=%s" %(k,repr(v)) for k,v in kw.items()])) + return func(*args, **kw) + return wrapper + + +class SourceVT: + def __init__(self,table,boolargs=None,nonstringargs=None,needsescape=None,staticschema=False,notsplit=None): + self.tableObjs=dict() + self.tableCl=table + if boolargs==None: + self.boolargs=[] + else: + self.boolargs=boolargs + if nonstringargs==None: + self.nonstringargs=dict() + else: + self.nonstringargs=nonstringargs + if needsescape==None: + self.needsescape=[] + else: + self.needsescape=needsescape + if notsplit==None: + self.notsplit=[] + else: + self.notsplit=notsplit + self.staticschema=staticschema + + @echocall + def Create(self, db, modulename, dbname, tablename,*args): + dictargs={'tablename':tablename,'db':db,'dbname':dbname,'modulename':modulename} + self.tableObjs[tablename]=LTable(self.tableCl,self.tableObjs,self.boolargs,self.nonstringargs,self.needsescape,self.notsplit,self.staticschema,*args,**dictargs) + return [self.tableObjs[tablename].getschema(),self.tableObjs[tablename]] + + @echocall + def Connect(self, db, modulename, dbname, tablename,*args): + if tablename not in self.tableObjs: + dictargs={'tablename':tablename,'db':db,'dbname':dbname,'modulename':modulename} + self.tableObjs[tablename]=LTable(self.tableCl,self.tableObjs,self.boolargs,self.nonstringargs,self.needsescape,self.notsplit,self.staticschema,*args,**dictargs) + return [self.tableObjs[tablename].getschema(),self.tableObjs[tablename]] + + +class emptyiter: + def init(self): + pass + def __iter__(self): + return self + def next(self): + raise StopIteration + def close(self): + pass + + +class LTable: ####Init means setschema and execstatus + autostring='automatic_vtable' + @echocall + def __init__(self,vtable,tblist,boolargs,nonstringargs,needsescape,notsplit,staticschema,*args,**envars): # envars tablename, auto , OPTIONAL [] + self.delayedexception=None + self.tblist=tblist + self.auto=False + self.first=True + self.staticschema=staticschema + self.schema="create table %s('Error')" % (envars['tablename']) + self.tablename=envars['tablename'] + self.envars=envars + largs, kargs = [] ,dict() + try: + largs, kargs = argsparse.parse(args,boolargs,nonstringargs,needsescape,notsplit) + except Exception,e: + raise #functions.MadisError(e) + if self.autostring in kargs: + del kargs[self.autostring] + self.auto=True + ####init schema and set + try: + self.vtable=vtable(envars,largs,kargs) + if not self.staticschema: + self.iter=self.vtable.open() + self._setschema() + if not self.auto and not self.staticschema: + if functions.settings['vtdebug']: + print "Manual vtable creation:Closing Vtable iterator" + self.iter.close() + except (StopIteration,apsw.ExecutionCompleteError),e: ### + try: + raise functions.DynamicSchemaWithEmptyResultError(self.envars['modulename']) + finally: + try: + self.iter.close() + except: + pass + + @echocall + def _setschema(self): + descr=self.vtable.getdescription() ### get list of tuples columnname, type + self.schema=schemaUtils.CreateStatement(descr, self.tablename) + + @echocall + def getschema(self): + if functions.settings['tracing']: + print 'VT_Schema: %s' %(self.schema) + return self.schema + + @echocall + def BestIndex(self, *args): + return (None, 0, None, False, 1000) + + @echocall + def Open(self): + if self.delayedexception: + raise self.delayedexception[1], None, self.delayedexception[2] ### Re - raise Exception of Create + if self.first and self.auto and not self.staticschema: + self.first=False + return Cursor(self,self.iter) + else: + try: + itt=self.vtable.open() + except StopIteration: + itt=emptyiter() + return Cursor(self,itt) + + return ret + @echocall + def reset(self,iter): + iter.close() + ret=self.vtable.open() + return ret + + @echocall + def Disconnect(self): + """ + This method is called when a reference to a virtual table is no longer used + """ + if self.first and self.auto and not self.staticschema: + self.iter.close() + self.first=False + if self.vtable.__class__.__dict__.has_key('disconnect'): + self.vtable.disconnect() + @echocall + def Destroy(self): + """ + This method is called when the table is no longer used + """ + if self.first and self.auto and not self.staticschema: + self.iter.close() + del self.tblist[self.tablename] + if self.vtable.__class__.__dict__.has_key('destroy'): + self.vtable.destroy() + + + +# Represents a cursor +class Cursor: + __slots__ = ("Next", "Close", "Column", "Rowid", "Eof", "pos", "row", "table", "eof", "iterNext", "iter") + + @echocall + def __init__(self, table,iter): + self.table=table + self.iter=iter + self.iterNext = self.iter.next + self.row=None + self.tablename=table.tablename + self.firsttime=True + self.pos=0 + self.Column = lambda col: self.row[col] + self.Rowid = lambda: self.pos + 1 + self.Eof = lambda: self.eof + + @echocall + def Filter(self, *args): + self.eof=False + self.pos=-1 + + if not self.firsttime: + self.iter=self.table.reset(self.iter) + self.iterNext = self.iter.next + self.firsttime=False + self.Next() + +# @echocall #-- Commented out for speed reasons +# def Eof(self): +# return self.eof + + #@echocall + # def Rowid(self): + # return self.pos+1 + +# @echocall #-- Commented out for speed reasons + def ColumnStop(self, col): + raise functions.OperatorError(self.table.envars['modulename'],"Not enough data in input") + +# @echocall #-- Commented out for speed reasons +# def Column(self, col): +# return self.row[col] + +# @echocall #-- Commented out for speed reasons + def Next(self): + try: + self.row = self.iterNext() +# self.pos+=1 + except StopIteration: + self.row=None + self.eof=True + + @echocall + def Close(self): + try: + self.iter.close() + except AttributeError: + pass + +def unify(slist): + if len(set(slist))==len(slist): + return slist + eldict={} + for s in slist: + if s in eldict: + eldict[s]+=1 + else: + eldict[s]=1 + for val,fr in eldict.items(): + if fr==1: + del eldict[val] + for val in eldict: + eldict[val]=1 + uniquelist=[] + for s in slist: + if s in eldict: + uniquelist+=[s+str(eldict[s])] + eldict[s]+=1 + else: + uniquelist+=[s] + + return uniquelist + +import re +onlyalphnum=re.compile('[a-zA-Z]\w*$') + +def schemastr(tablename,colnames,typenames=None): + stripedcolnames=[el if onlyalphnum.match(el) else '"'+el.replace('"','""')+'"' for el in colnames] + if not typenames: + return "create table %s(%s)" %(tablename,','.join(['"'+str(c)+'"' for c in unify(stripedcolnames)])) + else: + stripedtypenames=['' if el.lower()=="none" else el if onlyalphnum.match(el) else '"'+el.replace('"','""')+'"' for el in typenames] + return "create table %s(%s)" %(tablename,','.join([str(c)+' '+str(t) for c,t in zip(unify(stripedcolnames),stripedtypenames)])) diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/vtout.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/vtout.py new file mode 100644 index 0000000..93f3b44 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/vtout.py @@ -0,0 +1,181 @@ +""" +TODO : add logging on continue +--------------------------------- +Base module for NtoOne operators: + +Creates a virtual table with one columname : return_value and returns 1 if the execution succeds + and raises an exception or return 0 on failure + +To create an NtoOneOperator as VT + +def Source: + return SourceNtoOne(PARAMETERS) + +PARAMETERS: +1. Function to be called on execution (at the end there is the inteface of the function) +Optional parameters: +boolargs : List of names of dictionary boolean parameters of input function +nonstringargs : Dictionary of the translation of non-string and boolean parameters +connectionhandler : If True the connection is passed to the running function +retalways : If True any exeption during execution will be caught and 0 will be returned + +Gets a function to execute on execution +Input Function INTERFACE: +1. Tuple of (Iterator on query result,tuple of columntypes) +2. OPTIONAL db connection (to receive this argument...) +3+ rest of parsed arguments in list and dictionary + +IF function returns normally 1 value is returned, else exeption is raised EXCEPT if .... + +""" + +import setpath +from lib import argsparse +import functions +import logging +import itertools +import apsw + +class doall(object): + def __init__(self,query,connection,func,returnalways,passconnection,*args,**kargs): + self.connection=connection + self.query=query + self.args=args + self.func=func + self.kargs=kargs + self.returnalways=returnalways + self.passconnection=passconnection + + def run(self): + c = self.connection.cursor() + try: + cexec = c.execute(self.query, parse=False) + + try: + schema = c.getdescriptionsafe() + except functions.ExecutionCompleteError: + raise functions.DynamicSchemaWithEmptyResultError("got empty input") + + if self.passconnection: + try: + self.func(cexec, schema, self.connection, *self.args, **self.kargs) + except apsw.AbortError: + cexec = c.execute(self.query, parse=False) + self.func(cexec, schema, self.connection, *self.args, **self.kargs) + else: + try: + self.func(cexec, schema, *self.args, **self.kargs) + except apsw.AbortError: + cexec = c.execute(self.query, parse=False) + self.func(cexec, schema, *self.args, **self.kargs) + + ret = True + except Exception,e: + if functions.settings['logging']: + lg = logging.LoggerAdapter(logging.getLogger(__name__), {"flowname": functions.variables.flowname}) + lg.exception(e) + if self.returnalways: + return False + else: + if functions.settings['tracing']: + import traceback + print "---Deep Execution traceback--" + print traceback.print_exc() + raise functions.MadisError(e) + finally: + try: + c.close() + except: + pass + return ret + +class SourceNtoOne: + def __init__(self, func, boolargs=None, nonstringargs=None, needsescape=None, notsplit=None, connectionhandler=False, retalways=False): + self.func=func + if boolargs==None: + self.boolargs=[] + else: + self.boolargs=boolargs + if nonstringargs==None: + self.nonstringargs=dict() + else: + self.nonstringargs=nonstringargs + if needsescape==None: + self.needsescape=[] + else: + self.needsescape=needsescape + if notsplit==None: + self.notsplit=[] + else: + self.notsplit=notsplit + self.connectionhandler=connectionhandler + self.retalways=retalways + def Create(self, db, modulename, dbname, tablename, *args): + + schema="create table %s(return_value)" %(tablename) + return [schema,Table(lambda:maincode(args,self.boolargs,self.nonstringargs,self.needsescape,self.notsplit,db,self.func,self.retalways,self.connectionhandler))] + Connect=Create + +def maincode(args,boolargs,nonstringargs,needsescape,notsplit,db,func,retalways,connectionhandler): + autostring='automatic_vtable' + try: + largs, kargs = argsparse.parse(args,boolargs,nonstringargs,needsescape,notsplit) + except Exception,e: + raise functions.MadisError(e) + if 'query' not in kargs: + raise functions.OperatorError(func.__globals__['__name__'].rsplit('.')[-1],"needs query argument ") + query=kargs['query'] + del kargs['query'] + if autostring in kargs: + del kargs[autostring] + return doall(query,db,func,retalways,connectionhandler,*largs,**kargs) + +# Represents a table +class Table: + def __init__(self, dobj): + self.dobj=dobj + + def BestIndex(self, *args): + return (None, 0, None, False, 1000) + + def Rollback(self,*args): + pass + + def Open(self): + return Cursor(self) + + def Disconnect(self): + pass + + def Destroy(self): + pass + +# Represents a cursor +class Cursor: + def __init__(self, table): + self.table=table + self.row=None + + def Filter(self, *args): + if self.table.dobj().run(): + self.row=[1] + else: + self.row=[0] + self.eof=False + self.pos=0 + + def Eof(self): + return self.eof + + def Rowid(self): + return self.pos+1 + + def Column(self, col): + + return self.row[col] + + def Next(self): + self.eof = True + + def Close(self): + pass \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/webtable.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/webtable.py new file mode 100644 index 0000000..a06369a --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/webtable.py @@ -0,0 +1,113 @@ +""" +.. function:: webtable(url[,tableNumber]) + + Returns the result of the first or the *tableNumber* HTML table from the *url*. + +:Returned table schema: + Column names same as HTML table column headers. If there are no headers columns are named as C1,C2....Cn + +Examples: + + >>> sql("select * from webtable('http://en.wikipedia.org/wiki/List_of_countries_by_public_debt',2) order by 2 desc limit 3") + Country | Public debt as % of GDP(CIA)[1] | Date1 | Gross government debt as % of GDP(IMF)[2] | Date2 | Region + ----------------------------------------------------------------------------------------------------------------------------- + Belize | 90.8 | 2012 est. | 81.003 | 2012 est. | North America + Sudan | 89.3 | 2012 est. | 112.15 | 2012 est. | Africa + France | 89.1 | 2012 est. | 89.97 | 2012 est. | Europe + +""" +import setpath +import functions +import urllib2 +import vtbase +from lib import TableHTMLParser + +registered=True +external_stream=True + +class WebTable(vtbase.VT): + def parse(self,*args): + tableNum=1 + argsnum=len(args) + if argsnum<1 or argsnum>2: + raise functions.OperatorError(__name__.rsplit('.')[-1],"Wrong number of arguments") + tableUrl=args[0] + if argsnum==2: + try: + tableNum=int(args[1]) + except Exception: + raise functions.OperatorError(__name__.rsplit('.')[-1],"Table number must be integer") + return (tableUrl, tableNum) + + def VTiter(self,tableUrl, tableNum,**envars): + tableiter = TableParse(tableUrl, tableNum) + + samplerow = tableiter.next() + + if type(samplerow) == tuple: + yield [(header,'text') for header in samplerow] + else: + yield [('C'+str(i),'text') for i in range(1, len(samplerow)+1)] + yield samplerow + + for r in tableiter: + yield r + + +class TableParse: + def __init__(self,tableUrl, tableNum): + url = tableUrl + + try: + txdata = None + txheaders = { + 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)', + } + req = urllib2.Request(url, txdata, txheaders) + self.ufile = urllib2.urlopen(req) + headers = self.ufile.info() + except Exception: + raise functions.OperatorError(__name__.rsplit('.')[-1],"Cannot load url:'%s'" %(repr(url))) + parser = TableHTMLParser.TableHTMLParser(tableNum) + + self.iterator=linkiter(self.ufile,parser.parse) + def __iter__(self): + return self + def next(self): + try: + current = self.iterator.next() + return current + except TableHTMLParser.HTMLParseError,e: + raise functions.OperatorError(__name__.rsplit('.')[-1],e) + + + def close(self): + self.ufile.close() + + +def linkiter(source,consume): + for inp in source: + for out in consume(inp): + yield out + + + +def Source(): + return vtbase.VTGenerator(WebTable) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() + \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/whilevt.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/whilevt.py new file mode 100644 index 0000000..6c0f274 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/whilevt.py @@ -0,0 +1,158 @@ +""" +.. function:: whilevt([from:0,[to:10, step:1]], query) + +Returns a range of integer numbers while a query's result is true. + +:Returned table schema: + - *value* int + Number in range. + +:from: + Number to begin from. Default is 0 +:to: + Number to reach. Default is 10. The *to* number is not returned +:step: + Step to augment the returned numbers. Default is 1 + +Examples:: + + >>> sql("select * from range()") + C1 + -- + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + + >>> sql("select * from range('from:1','to:11')") + C1 + -- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + + >>> sql("select * from range('from:2','to:15','step:3')") + C1 + -- + 2 + 5 + 8 + 11 + 14 + + >>> sql("select * from range(1,10,2)") + C1 + -- + 1 + 3 + 5 + 7 + 9 + + >>> sql("select * from range(5)") + C1 + -- + 1 + 2 + 3 + 4 + 5 + +""" + +import setpath +import functions +import vtbase +registered = True +external_query = True + +class WhileVT(vtbase.VT): + def VTiter(self, *parsedArgs, **envars): + largs, dictargs = self.full_parse(parsedArgs) + fromv = 0 + tov = None + stepv = 1 + checkfirst = True + query = 'select 1' + con = None + + if 'from' in dictargs: + fromv = int(dictargs['from']) + if 'to' in dictargs: + tov = int(dictargs['to']) + if 'step' in dictargs: + stepv = int(dictargs['step']) + if 'checkfirst' in dictargs and dictargs['checkfirst'] in ('f', 'F', '0'): + checkfirst = False + if len(largs) >= 1: + fromv = int(largs[0]) + if len(largs) >= 2: + tov = int(largs[1]) + if len(largs) >= 3: + stepv = int(largs[2]) + if len(largs) == 1: + fromv = 1 + tov = int(largs[0])+1 + + if functions.variables.execdb is None: + con = functions.Connection('') + else: + con = functions.Connection(functions.variables.execdb) + functions.register(con) + + if 'query' not in dictargs: + raise functions.OperatorError(__name__.rsplit('.')[-1], "Needs a query") + else: + query = dictargs['query'] + yield [('C1', 'int')] + + if checkfirst: + cur = con.cursor() + res = list(cur.execute(query)) + cur.close() + if len(res) == 0 or len(res[0]) == 0 or res[0][0] != 1: + return + + yield (fromv,) + + while True: + cur = con.cursor() + res = list(cur.execute(query)) + cur.close() + if len(res) == 0 or len(res[0]) == 0 or res[0][0] != 1: + return + fromv += 1 + if tov is not None and fromv >= tov: + return + yield (fromv, ) + +def Source(): + return vtbase.VTGenerator(WhileVT) + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/functions/vtable/xmlparse.py b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/xmlparse.py new file mode 100644 index 0000000..d9cc530 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/functions/vtable/xmlparse.py @@ -0,0 +1,783 @@ +""" +.. function:: xmlparse([root:None, strict:1, namespace:False, xmlprototype], query:None) + +Parses an input xml stream. It starts parsing when it finds a root tag. A provided XML prototype fragment is used to create an schema, mapping from xml to a relational table. +If multiple values are found for the same tag in the input stream, then all values are returned separated with a tab (use tab-set operators to process them). + +If no XML prototype is provided, then a jdict of the data is returned. If no *root* tag is provided, then the output is a raw feed of {path:data} pairs without any row aggregation. +Rootless mode is usefull when trying to find what *root* tag to use. + +Is a *root* tag is provided then each returned row, contains a jdict of all the paths found below the specified *root* tag. + +:XML prototype: + + XML prototype may be: + + - a fragment of XML which will be matched with the input data. + - a jpack. + - a jdict. + + If a the characters **"*"** or **"$"** are provided as a value of any of these prototypes, then a full XML subtree of a path will be returned in the resulting data. + +:'namespace' or 'ns' option: + + Include namespace information in the returned jdicts. + +:'fast' option (default 0): + + Read input data in bulk. For some XML input files (having lots of small line lengths), it can speed up XML processing by up to 30%. The downside of this option, is that when an error + occurs no last line information is returned, so use this option only when you are sure that the XML input is well formed. + + - fast:0 (default), parses the input stream in a conservative line by line way + - fast:1 ,is the same as fast:0, but it doesn't return *Last line* information in the case of an error + - fast:2 ,in this mode XMLPARSER doesn't convert HTML entities and doesn't skip ">> table1(''' + ... 'row1val1row1val1brow1val1c' + ... '' + ... '' + ... 'row2val1row2val' + ... '' + ... ''') + + >>> sql("select * from (xmlparse select * from table1)") # doctest: +NORMALIZE_WHITESPACE + C1 + ------------------- + {"a/b":"row1val1"} + {"a/b":"row1val1b"} + {"a/b":"row1val1c"} + {"a/b":"row2val1"} + {"a/c/d":"row2val"} + + >>> sql("select jgroupunion(jdictkeys(c1)) from (xmlparse select * from table1)") # doctest: +NORMALIZE_WHITESPACE + jgroupunion(jdictkeys(c1)) + -------------------------- + ["a/b","a/c/d"] + + >>> sql('''select * from (xmlparse '["a/b","a/c/d"]' select * from table1)''') # doctest: +NORMALIZE_WHITESPACE + b | c_d + -------------------------------------- + row1val1 row1val1b row1val1c | + row2val1 | row2val + + >>> sql("select * from (xmlparse 'val1val1val2' select * from table1)") # doctest: +NORMALIZE_WHITESPACE + b | b1 | c_d + ---------------------------------------- + row1val1 | row1val1b row1val1c | + row2val1 | | row2val + + >>> sql("select * from (xmlparse root:a 'val1val2' select * from table1)") # doctest: +NORMALIZE_WHITESPACE + b | c_d + -------------------------------------- + row1val1 row1val1b row1val1c | + row2val1 | row2val + + >>> table2(''' + ... 'row1val1' + ... '' + ... '' + ... 'row2val1asdfrow2val' + ... '' + ... ''') + >>> sql("select * from (xmlparse 'vv' select * from table2)") + b | b1 | c_d + ----------------------------- + attrval1 | row1val1 | + | row2val1 | row2val + + >>> sql('''select * from (xmlparse '["a/@/b","a/b","a/c/d"]' select * from table2)''') + b | b1 | c_d + ----------------------------- + attrval1 | row1val1 | + | row2val1 | row2val + + >>> sql('''select * from (xmlparse '{"a/b":[1,2] ,"a/c/d":1}' select * from table2)''') + b | b1 | c_d + ----------------------- + row1val1 | | + row2val1 | | row2val + + >>> sql('''select * from (xmlparse '{"a/b":[1,2] ,"a/c":[1,"*"]}' select * from table2)''') + b | b1 | c | c_$ + ----------------------------------------- + row1val1 | | | + row2val1 | | asdf | asdfrow2val + + >>> sql('''select * from (xmlparse '["a/b", "a/c", "a/c/*"]' select * from table2)''') + b | c | c_$ + ------------------------------------ + row1val1 | | + row2val1 | asdf | asdfrow2val + + >>> sql('''select * from (xmlparse root:a '{"a/b":"", "a":"*"}' select * from table2)''') # doctest: +NORMALIZE_WHITESPACE + b | $ + ------------------------------------------------------ + row1val1 | row1val1 + row2val1 | + + row2val1asdfrow2val + + >>> sql("select * from (xmlparse 'v*' select * from table2)") + b | c_$ + ----------------------------- + row1val1 | + row2val1 | asdfrow2val + + >>> sql("select * from (xmlparse root:a select * from table2)") + C1 + ------------------------------------------------- + {"a/@/b":"attrval1","a/b":"row1val1"} + {"a/b":"row2val1","a/c/d":"row2val","a/c":"asdf"} + + >>> table2(''' + ... 'row1val1' + ... '' + ... '
' + ... 'row2val1
row2val' + ... '' + ... ''') + >>> sql("select * from (xmlparse strict:0 'vv' select * from table2)") + b | b1 | c_d + ------------------------- + attrval1 | row1val1 | + + >>> table3(''' + ... 'row1val1' + ... '' + ... '' + ... 'row2val1row2val' + ... '' + ... ''') + >>> sql("select * from (xmlparse strict:2 'val1val2' select * from table3)") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ... + OperatorError: Madis SQLError: + Operator XMLPARSE: Undeclared path in XML-prototype was found in the input data. The path is: + /b/@/np + The data to insert into path was: + np + Last input line was: + + + + >>> table4(''' + ... 'row1val1' + ... 'row1val2' + ... 'row1val1' + ... 'row1val3/b>' + ... 'row1val4' + ... ''') + >>> sql("select * from (xmlparse strict:-1 'val1val2' select * from table4)") + C1 + ---------------------- + row1val2 + row1val3/b> + + >>> table5(''' + ... 'row1val1' + ... 'row2val1' + ... 'row3val1' + ... 'row4val1row4val2' + ... '' + ... ''') + >>> sql('''select * from (xmlparse '["a/b", "a/c"]' select * from table5)''') + b | c + ------------------- + row1val1 | + row2val1 | + row3val1 | + row4val1 | row4val2 +""" +import vtbase +import functions +import json +import cStringIO as StringIO +import StringIO as unicodeStringIO +import re +try: + from collections import OrderedDict +except ImportError: + # Python 2.6 + from lib.collections26 import OrderedDict + +try: + import xml.etree.cElementTree as etree +except: + import xml.etree.ElementTree as etree + +registered = True +cleandata = re.compile(r'[\n\r]*(.*?)\s*$', re.DOTALL| re.UNICODE) +cleansubtree = re.compile(r'[^<]*<[^<>]+?>(.*)]+?>[^>]*$', re.DOTALL| re.UNICODE) +attribguard = '@' + +# Workaround for older versions of elementtree +if not hasattr(etree, 'ParseError'): + etree.ParseError=etree.XMLParserError + +def matchtag(a, b): + if b[0] == '{': + return a == b + else: + if a[0] == '{': + return a.split('}')[1] == b + return a == b + +def pathwithoutns(path): + outpath=[] + for i in path: + if i[0]=="{": + i=i.split('}')[1] + elif ":" in i: + i=i.split(':')[1] + outpath+=[i] + return "/".join(outpath) + +def itertext(elem): + tag = elem.tag + if not isinstance(tag, basestring) and tag is not None: + return + if elem.text: + yield elem.text + for e in elem: + for s in e.itertext(): + yield s + if e.tail: + yield e.tail + +class rowobj(): + def __init__(self, schema, strictness): + self.schema=schema.schema + self.schemagetall=schema.getall + self.sobj=schema + self.schemacolsnum=len(schema.schema)+len(schema.getall) + self.row=['']*self.schemacolsnum + self.strict= strictness + self.tabreplace=' ' + if self.schemagetall=={}: + self.addtorowall=lambda x, y, z:0 + else: + self.addtorowall=self.addtorow + + def addtorow(self, xpath, data, elem=None): + fullp='/'.join(xpath) + path=None + + if elem!=None: + s=self.schemagetall + if fullp in s: + path=fullp + else: + shortp=pathwithoutns(xpath) + if shortp in s: + path=shortp + + if path == None: + return + + try: + data = cleansubtree.match(etree.tostring(elem)).groups()[0] + except AttributeError: + data = etree.tostring(elem) + else: + s=self.schema + + if fullp in s: + path=fullp + else: + shortp=pathwithoutns(xpath) + if shortp in s: + path=shortp + + if path==None: + if self.strict==2 and elem==None: + path=xpath + self.resetrow() + msg='Undeclared path in XML-prototype was found in the input data. The path is:\n' + shortp='/'+pathwithoutns(path) + fullp='/'+'/'.join(path) + if shortp!=fullp: + msg+=shortp+'\n' + msg+=fullp+'\nThe data to insert into path was:\n'+functions.mstr(data) + raise etree.ParseError(msg) + else: + if self.row[s[path][0]]=='': + self.row[s[path][0]]=data.replace('\t', self.tabreplace) + return + + i=1 + attribnum=path+'1' + + oldattribnum=path + while attribnum in s: + if self.row[s[attribnum][0]]=='': + self.row[s[attribnum][0]]=data.replace('\t', self.tabreplace) + return + i+=1 + oldattribnum=attribnum + attribnum=path+str(i) + + self.row[s[oldattribnum][0]]+='\t'+data.replace('\t', self.tabreplace) + + def resetrow(self): + self.row=['']*self.schemacolsnum + +class jdictrowobj(): + def __init__(self, ns, subtreeroot=None): + self.rowdata = OrderedDict() + self.namespace = ns + if subtreeroot is not None: + self.root = [subtreeroot] + else: + self.root = [] + + def addtorow(self, xpath, data): + if self.namespace: + path='/'.join(self.root+xpath) + else: + path=pathwithoutns(self.root+xpath) + + if path not in self.rowdata: + self.rowdata[path] = data + else: + if type(self.rowdata[path]) is list: + self.rowdata[path].append(data) + else: + self.rowdata[path] = (self.rowdata[path], data) + return + + @staticmethod + def addtorowall(xpath, data, elem): + return + + @property + def row(self): + return [json.dumps(self.rowdata, separators=(',', ':'), ensure_ascii=False)] + + def resetrow(self): + self.rowdata = OrderedDict() + +class schemaobj(): + def __init__(self): + self.schema={} + self.colnames={} + self.getall={} + + def addtoschema(self, path, subtreeroot = None): + s=self.schema + pathpostfix=[] + if path!=[] and path[-1] in ('*', '$'): + path=path[0:-1] + s=self.getall + pathpostfix=['$'] + + fpath=cleandata.match("/".join(path)).groups()[0].lower() + + if fpath == '' and pathpostfix == []: + return + + if fpath not in s: + s[fpath]=(len(self.schema)+len(self.getall), self.colname(path+pathpostfix)) + else: + fpath1=fpath + i=1 + while True: + fpath1=fpath+str(i) + if fpath1 not in s: + s[fpath1]=(len(self.schema)+len(self.getall), self.colname(path+pathpostfix)) + break + i=i+1 + + def colname(self, path): + sp=self.shortifypath(path).lower() + if sp not in self.colnames: + self.colnames[sp]=0 + return sp + else: + self.colnames[sp]+=1 + return sp+str(self.colnames[sp]) + + def shortifypath(self, path): + outpath=[] + for i in path: + if i==attribguard: + continue + if i[0]=="{": + i=i.split('}')[1] + elif ":" in i: + i=i.split(':')[1] + i="".join([x for x in i if x=='$' or (x.lower()>="a" and x<="z")]) + outpath+=[i] + return "_".join(outpath) + + def getrelschema(self): + relschema=[None]*(len(self.schema)+len(self.getall)) + + for x,y in self.schema.itervalues(): + relschema[x]=(y, 'text') + + for x,y in self.getall.itervalues(): + relschema[x]=(y, 'text') + + return relschema + + +class XMLparse(vtbase.VT): + def __init__(self): + self.schema=None + self.subtreeroot=None + self.rowobj=None + self.query=None + self.strict=1 + self.namespace=False + self.fast=0 + + def getschema(self, *parsedArgs,**envars): + s=schemaobj() + + opts=self.full_parse(parsedArgs) + + if 'root' in opts[1]: + self.subtreeroot=opts[1]['root'].lower() + + if 'namespace' in opts[1] or 'ns' in opts[1]: + self.namespace=True + + if 'fast' in opts[1]: + try: + self.fast=int(opts[1]['fast']) + except: + self.fast=1 + + if 'strict' in opts[1]: + self.strict=int(opts[1]['strict']) + if self.strict<=0: + self.fast=0 + + try: + self.query=opts[1]['query'] + except: + raise functions.OperatorError(__name__.rsplit('.')[-1],"An input query should be provided as a parameter") + + try: + xp=opts[0][0] + except: + self.rowobj=jdictrowobj(self.namespace, self.subtreeroot) + self.schema=None + return [('C1', 'text')] + + try: + jxp=json.loads(xp, object_pairs_hook=OrderedDict) + except ValueError: + jxp=None + + if type(jxp) is list: + for i in jxp: + path=i.split('/') + if path[0] == '': + path=path[1:] + + if self.subtreeroot==None: + self.subtreeroot=path[0] + + try: + path = path[ path.index(self.subtreeroot)+1: ] + except ValueError: + continue + + if path!=[]: + s.addtoschema(path) + + elif type(jxp) is OrderedDict: + for k,v in jxp.iteritems(): + path = k.split('/') + if path[0] == '': + path = path[1:] + + if self.subtreeroot is None: + self.subtreeroot = path[0] + + try: + path = path[path.index(self.subtreeroot)+1:] + except ValueError: + continue + + if type(v) in (list, OrderedDict): + for i in v: + if i in ('*', '$'): + s.addtoschema(path+['*']) + else: + # if path == []: + # continue + s.addtoschema(path) + else: + if v in ('*', '$'): + s.addtoschema(path+['*']) + else: + # if path == []: + # continue + s.addtoschema(path) + else: + xpath=[] + capture=False + + for ev, el in etree.iterparse(unicodeStringIO.StringIO(xp), ("start", "end")): + if ev=="start": + if self.subtreeroot==None: + self.subtreeroot=el.tag + if capture: + xpath.append(el.tag) + if matchtag(el.tag.lower(), self.subtreeroot) and not capture: + capture=True + if capture and el.attrib!={}: + for k in el.attrib: + s.addtoschema(xpath+[attribguard, k]) + continue + + if capture: + if el.text!=None and cleandata.match(el.text).groups()[0]!='': + if el.text.strip() in ('$', '*'): + s.addtoschema(xpath+['*']) + else: + s.addtoschema(xpath) + if ev=="end": + if el.tag.lower()==self.subtreeroot: + capture=False + if len(xpath)>0: + xpath.pop() + + if ev=="end": + el.clear() + + relschema=s.getrelschema() + + if relschema==[]: + raise functions.OperatorError(__name__.rsplit('.')[-1], 'No input schema found') + + self.rowobj=rowobj(s, self.strict) + if self.strict>=0: + return s.getrelschema() + else: + return [('C1', 'text')] + + def VTiter(self, *parsedArgs, **envars): + + class inputio(): + def __init__(self, connection, query, fast=False): + from lib import htmlentities as htmlentities + + self.lastline = '' + self.qiter = connection.cursor().execute(query) + self.read = self.readstart + self.fast = fast + self.htmlentities = htmlentities.entities.copy() + del(self.htmlentities['lt']) + del(self.htmlentities['gt']) +# del(self.htmlentities['quot']) +# del(self.htmlentities['amp']) + self.forcedroottag='\n' + if self.fast == 2: + self.header = self.forcedroottag + else: + self.header ='' for x,v in self.htmlentities.iteritems()]) + self.header +=']>\n'+self.forcedroottag + self.replacexmlheaders = re.compile(r'\<\?xml.+?(\<[\w\d:])', re.DOTALL| re.UNICODE) + self.finddatatag = re.compile(r'(\<[\w\d:])', re.DOTALL| re.UNICODE) + self.deldoctype = re.compile(r'\]+?\>', re.DOTALL| re.UNICODE) + + def unescape(self, text): + return self.unescapere.sub(self.fixup, text) + + def restart(self): + self.read=self.readstart + + def readstart(self, n): + + def readline(): + l = self.qiter.next()[0] + if l.endswith('\n'): + return l + else: + return l+'\n' + + self.lastline = readline() + line = self.lastline.strip() + longline = line + + while not self.finddatatag.search(line): + line = readline() + longline += line + + if longline.find('= 0 and len(self.rowobj.rowdata) != 0: + yield self.rowobj.row + else: + capture = False + if self.strict >= 0: + yield self.rowobj.row + resetrow() + root.clear() + + if len(xpath) > 0: + xpath.pop() + + else: # Else is needed for clear to not happen while a possible all (*) op is running + el.clear() + + etreeended = True + except etree.ParseError, e: + rio.restart() + resetrow() + if self.strict >= 1: + raise functions.OperatorError(__name__.rsplit('.')[-1], str(e)+'\n'+'Last input line was:\n'+rio.lastline) + if self.strict == -1: + yield [rio.lastline] + finally: + rio.close() + + +def Source(): + return vtbase.VTGenerator(XMLparse) + + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + import sys + import setpath + from functions import * + testfunction() + if __name__ == "__main__": + reload(sys) + sys.setdefaultencoding('utf-8') + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/functionslocal/__init__.py b/interactive-mining-3rdparty-madis/madis/src/functionslocal/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/interactive-mining-3rdparty-madis/madis/src/functionslocal/aggregate/__init__.py b/interactive-mining-3rdparty-madis/madis/src/functionslocal/aggregate/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/interactive-mining-3rdparty-madis/madis/src/functionslocal/row/__init__.py b/interactive-mining-3rdparty-madis/madis/src/functionslocal/row/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/interactive-mining-3rdparty-madis/madis/src/functionslocal/vtable/__init__.py b/interactive-mining-3rdparty-madis/madis/src/functionslocal/vtable/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/afrikaans.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/afrikaans.lm new file mode 100644 index 0000000..c110f15 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/afrikaans.lm @@ -0,0 +1,400 @@ +_ 23602 +e 8036 +a 4087 +n 3782 +i 3726 +o 3314 +r 2951 +s 2885 +t 2749 +d 2479 +e_ 2118 +l 1854 +k 1741 +ie 1670 +g 1601 +n_ 1447 +m 1440 +_d 1219 +t_ 1143 +er 1124 +h 1124 +u 1110 +ie_ 1079 +y 1048 +w 986 +s_ 982 +_s 969 +_h 956 +di 924 +an 922 +r_ 912 +aa 882 +v 876 +en 807 +_di 807 +. 790 +y_ 747 +_v 709 +et 706 +._ 694 +die 691 +die_ 667 +_n 666 +_die 651 +p 639 +_m 634 +_die_ 633 +_w 632 +ee 607 +ge 606 +_o 598 +b 586 +te 568 +, 560 +in 555 +k_ 550 +_e 550 +,_ 548 +oo 516 +et_ 511 +de 509 +el 489 +_g 486 +f 461 +ar 451 +ni 450 +nd 442 +an_ 440 +en_ 437 +_i 426 +he 423 +g_ 418 +_t 412 +oe 410 +at 406 +er_ 400 +om 381 +wa 378 +_a 378 +_b 377 +_k 371 +nie 371 +_he 370 +aar 355 +_ge 351 +es 351 +_ni 348 +da 346 +m_ 342 +ou 338 +it 335 +_nie 335 +d_ 332 +l_ 330 +_wa 329 +or 327 +le 326 +we 326 +ek 324 +het 321 +me 319 +_het 319 +is 318 +j 315 +at_ 311 +on 309 +se 308 +_en 298 +ma 294 +st 291 +as 280 +va 277 +_en_ 270 +re 270 +" 269 +' 265 +het_ 261 +_het_ 260 +om_ 254 +al 252 +ar_ 250 +li 248 +te_ 247 +aar_ 247 +_da 245 +u_ 242 +nde 241 +ou_ 237 +_l 231 +be 229 +_' 226 +rd 224 +_va 224 +ig 223 +ng 222 +ns 221 +ve 220 +it_ 218 +_j 216 +_me 216 +sy 215 +ke 213 +_sy 212 +aan 212 +van 212 +_in 210 +is_ 210 +in_ 208 +sy_ 206 +_sy_ 206 +'n 205 +ro 205 +ko 204 +_'n 203 +ra 203 +'n_ 203 +_'n_ 202 +so 202 +D 202 +ho 201 +rs 200 +eer 200 +ik 199 +la 198 +_te 196 +_van 196 +_ma 195 +as_ 194 +ui 194 +ver 192 +e. 192 +der 191 +to 188 +op 187 +van_ 184 +ag 184 +_ve 182 +and 180 +_van_ 178 +ha 178 +f_ 176 +ka 176 +ne 175 +_is 175 +sk 174 +e._ 174 +oor 174 +_ver 170 +ek_ 170 +_hy 170 +hy 170 +p_ 168 +_be 168 +ri 168 +ur 167 +nie_ 165 +_so 165 +_D 164 +si 164 +ll 164 +no 164 +_in_ 163 +_hy_ 162 +hy_ 162 +ed 161 +ers 160 +_r 156 +ak 156 +_ho 155 +_nie_ 153 +eg 153 +nt 152 +de_ 152 +_p 151 +_we 148 +_is_ 148 +ei 147 +es_ 142 +maa 142 +wee 142 +na 141 +nder 139 +a_ 138 +ing 138 +ew 138 +S 135 +lle 135 +_om 135 +_te_ 134 +eu 134 +ie. 134 +wo 132 +em 132 +wat 131 +_no 130 +_" 130 +vo 130 +E 129 +H 128 +_wat 127 +ti 126 +mo 126 +A 126 +e, 126 +_ha 125 +vi 125 +el_ 125 +ter 125 +e,_ 124 +dat 124 +eer_ 124 +wat_ 124 +le_ 124 +ta 124 +Di 123 +dat_ 123 +_wat_ 122 +ie._ 122 +was 121 +ste 121 +_H 121 +_se 121 +se_ 120 +ul 120 +al_ 120 +_was 120 +_om_ 119 +_st 119 +lik 118 +"_ 118 +_ko 118 +_maa 118 +lo 117 +_to 117 +ns_ 115 +aan_ 115 +nie. 114 +_vi 114 +met 114 +_nie. 111 +nk 110 +_Di 110 +- 110 +_op 109 +_oo 109 +_on 108 +ir 108 +ord 108 +uit 106 +ens 105 +_was_ 105 +was_ 105 +een 105 +_met 105 +os 105 +_S 104 +nie._ 104 +ig_ 103 +_sk 102 +op_ 101 +_ek 101 +_wee 101 +ir_ 101 +met_ 100 +_met_ 100 +rt 100 +ik_ 99 +end 99 +nd_ 99 +gt 99 +ond 98 +ot 98 +_aa 97 +og 97 +vir_ 95 +vir 95 +_ka 94 +hu 94 +_mo 94 +_vir_ 94 +_vir 94 +_dit 93 +kr 93 +am 93 +ol 93 +dit 93 +_ek_ 93 +ki 93 +sa 93 +_aan 92 +man 92 +jy 92 +ng_ 92 +aak 92 +lle_ 91 +_hu 91 +_na 91 +_vo 90 +ewe 90 +of 90 +jy_ 90 +_dit_ 90 +dit_ 90 +_jy 89 +der_ 89 +jo 89 +_f 88 +_u 88 +sie 87 +_dat 87 +_jy_ 87 +daa 87 +do 87 +vr 87 +wi 86 +ry 86 +_dat_ 86 +eur 86 +rs_ 85 +_jo 85 +_wo 84 +_ne 84 +jie 84 +ji 84 +pe 83 +moe 83 +my 82 +ull 82 +Die 81 +maar 81 +_hom 81 +ulle 81 +_maar 81 +hom 81 +_uit 80 +_ui 80 +ges 80 +raa 80 +or_ 80 +ies 80 +jou 79 +_la 79 +maar_ 79 +ulle_ 79 +_daa 79 +Die_ 79 +daar 78 +_daar 78 +ien 78 +_my 78 +_jou 78 +ok 78 +il 78 +lik_ 77 +sta 77 +_Die 77 +ur_ 77 +ga 77 +ag_ 77 +kan 77 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/amharic-utf.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/amharic-utf.lm new file mode 100644 index 0000000..0c5bc81 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/amharic-utf.lm @@ -0,0 +1,400 @@ +á 21403 +_ 10092 +ˆ 7734 +ሠ6558 +_á 5003 +‹ 4717 +‰ 4401 +በ4274 +á‹ 4176 +Š 4054 +አ3868 + 2728 +Œ 1656 +ጠ1591 +µ 1579 +  1425 + á 1402 +_አ1261 +_á‹ 1231 +¨ 1217 +á 1187 +¨á 1183 +_ሠ1160 +• 1145 +ˆá 1123 +­ 1097 +ን 1043 +Š• 1043 +° 1041 +°á 1004 +_በ991 +á 936 +« 880 +‹ 855 +á‹ 855 +¥ 849 +µá 805 +‰µ 783 +ት 783 +µ_ 763 +«á 709 +¥á 704 +‰  682 +በ 682 +­á 679 +˜ 670 +•á 667 +በá 666 +‰ á 666 +˜á 658 + 643 +የ 637 +‹¨ 637 +‹¨á 627 +የá 627 +ለ 614 +ˆˆ 614 +ˆ­ 611 +ር 611 +_ 588 +‰µ_ 583 +ት_ 583 +_የ 577 +_የá 574 +ለá 573 +ˆˆá 573 +ንá 570 +Š•á 570 +መ 563 +ˆ˜ 563 +ˆ˜á 557 +መá 557 +Š  554 +አ 554 +አá 553 +ተ 553 +Š á 553 +‰° 553 +ተá 547 +‰°á 547 +ሠ534 +ˆ 534 + áˆ 532 +- 531 +ስ 525 +ˆµ 525 +-- 521 +ሠ515 +ˆ 515 +--- 512 +---- 503 +_በ 499 +----- 494 +_በá 487 +‹á 479 +¨áˆ 477 +•_ 473 +‹á 469 +á‹á 469 +ን_ 468 +Š•_ 468 +¢ 465 +³ 464 +á‹« 457 +‹« 457 +°áˆ 444 +_አ 424 +_አá 424 +ስá 423 +ˆµá 423 +­_ 415 +³á 402 +½ 401 + 390 +ˆáˆ 389 +› 382 +‹_ 378 +á‹_ 378 +á 365 +‹«á 364 +á‹«á 364 +“ 363 +áˆá 357 +ˆá 357 +£ 356 +¢_ 351 +‰½ 347 +ች 347 +Š 341 +አ341 +á‹­ 337 +¢ 337 +ᢠ337 +‹­ 337 +¢_ 337 +á¢_ 337 +á 336 +… 334 +Š¥ 320 +እ 320 +£á 320 +ሠ320 +Š¥á 318 +እá 318 +ˆ­_ 314 +ር_ 314 +•á‹ 312 +›á 311 +¨á‰ 301 +ና 300 +ገ 300 +Š“ 300 +Œˆ 300 + á‰ 299 +˜áˆ 297 +ርá 294 +Œ 294 +ጠ294 +ˆ­á 294 +š 293 +ˆá 291 +ከ 291 +Œˆá 291 +Šá 291 +Š¨ 291 +áˆá 291 +ገá 291 +áŠá 291 +á‹° 288 +‹° 288 +_እ 285 +_እá 283 +® 279 +Š¨á 279 +ከá 279 +‰ áˆ 279 +በሠ279 +ንዠ276 +šá 276 +Š•á‹ 276 +_ጠ272 +‰¥ 270 +ብ 270 +_ 269 +áŒá 264 +Œá 264 +ˆ˜áˆ 262 +¥áˆ 262 +መሠ262 +¥áŠ 262 +á‹­á 261 +‹­á 261 +ˆ› 260 +ማ 260 +á‹°á 259 +‹°á 259 +ራ 254 +‰£ 254 +ባ 254 +ˆ« 254 +€ 253 +®á 249 +á 247 +€á 245 +µáˆ 244 +ላ 242 +ˆ‹ 242 +የሠ242 +‹¨áˆ 242 +ማá 238 +ˆ›á 238 + áŠ 237 +ረ 237 +ˆ¨ 237 +‰°áˆ 236 +ተሠ236 +áˆ_ 235 +ˆ_ 235 +ˆá‹ 234 +­áˆ 233 +«áˆ 233 +‰£á 230 +ˆš 230 +ባá 230 +ሚ 230 +ድ 228 +‹µ 228 +_መ 227 +በ227 +_መá 226 +ˆ¨á 225 +ረá 225 +² 225 +ᢠ222 +á¢_ 222 + á‹ 216 +እአ214 +ሚá 214 +Š¥áŠ 214 +ˆšá 214 +…á 213 +²á 212 +«á‹ 210 +ˆ‹á 209 +ላá 209 +© 208 +ˆá‰ 207 +‹áˆ 206 +½_ 206 +‰¥á 205 +ብá 205 +አ202 +ˆ° 200 +ታ 200 +‰³ 200 +ሰ 200 +ˆ«á 199 +ራá 199 +ሰá 198 +ˆ°á 198 +ትá 195 +ወ 195 +‰µá 195 +‹ˆ 195 +‹ˆá 194 +ወá 194 +½á 191 +Ž 191 +‰½_ 189 +ች_ 189 +“á 188 +¸á 186 +¸ 186 +_ለ 184 +_ለá 183 +ለሠ183 +ˆˆáˆ 183 +¥áŠ• 180 +‹¨á‰ 179 +የበ179 +Žá 178 +± 177 +¥áŠ•á 177 +_ከ 175 +Œ¥ 174 +ጥ 174 +Š áˆ 172 +አሠ172 +_ከá 170 +† 170 +«_ 169 +Š¥áŠ• 169 +†á 166 +°á‹ 166 +áˆá 165 +“_ 165 +ˆá 165 +ና_ 163 +Š“_ 163 +‰¸ 160 +ቸ 160 +ቸá 160 +‰¸á 160 +ˆáŠ 160 +¨áŠ 159 +¸á‹ 159 +‰€ 158 +ቀ 158 +­á‰ 158 +£áˆ 156 +ቀá 155 +‰€á 155 +ችá 154 +‰¸á‹ 154 +áˆ_ 154 +‰½á 154 +¸á‹ 154 +ቸዠ154 +ˆ_ 154 +µá‰ 152 +³á‹ 151 +‰¸á‹ 151 +Šá 150 +_አ150 +¶ 150 +_áŠá 150 +ƒ 150 +_á‹­á 150 +_á‹­ 150 +‰³á 149 +ታá 149 +ˆá¢ 148 +‰ á‰ 147 +ደሠ147 +‹°áˆ 147 +በበ147 + 146 +_ተ 146 +_ተá 146 +ለዠ145 +ˆˆá‹ 145 +ድá 144 +µáŠ 144 +›áˆ 144 +‹µá 144 +ቅ 143 +‰… 143 +¥_ 143 +áŒáˆ 142 +Œáˆ 142 +‹³ 141 +ዳ 141 +Žá‰ 139 +ህ 138 +ˆ… 138 +Š“á 137 +ናá 137 +«á‰ 137 +ን 136 +ጠ136 +አዠ135 +Š á‹ 135 +†áŠ 135 +ስበ134 +ˆµá‰ 134 +ጠ 133 +ዳá 133 +Œ  133 +ሆá 133 +ˆ†á 133 +ሆ 133 +‹³á 133 +ˆ† 133 +ሆአ132 +ˆ†áŠ 132 +¨á‰° 131 +ያሠ131 +¨á‰°á 131 +‹«áˆ 131 +á‹ 129 +µá‹ 128 +Š­ 128 +ክ 128 +á 128 + 128 +°á‰ 127 +Œ á 127 +ጠá 127 +Š« 126 +ካ 126 +á 124 +በአ123 +°áŒ 123 +á‹«á‹ 123 +‹«á‹ 123 +‰ áŠ 123 +Š¨áˆ 122 +ከሠ122 +Œˆáˆ 121 +ገሠ121 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/arabic-iso8859_6.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/arabic-iso8859_6.lm new file mode 100644 index 0000000..f7b7382 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/arabic-iso8859_6.lm @@ -0,0 +1,400 @@ +_ 9692 +Ø 7361 +Ù 6120 +ا 2417 +§ 2417 +_Ø 1691 +Ù„ 1587 +„ 1587 +ا٠1415 +§Ù 1415 +Ç 1241 +_Ù 1129 +_ا 987 +§Ù„ 978 +ال 978 +ä 952 +_ا٠894 +Ù… 869 +… 869 +Ù„Ø 801 +„Ø 801 +Š 798 +ÙŠ 798 +_ال 771 +ª 757 +ت 757 +Ø§Ø 738 +§Ø 738 +Ùˆ 680 +ˆ 680 +Ù† 659 +† 659 +è 622 +Ù„Ù 619 +„Ù 619 +§Ù„Ø 574 +Ø§Ù„Ø 574 +¹ 547 +ع 547 +ر 541 +± 541 +ê 527 +© 512 +Ø© 512 +…Ø 504 +Ù…Ø 504 +æ 496 +Çä 492 +ب 490 +¨ 490 +Ø©_ 482 +©_ 482 +å 477 +_Ç 470 +ŠØ 461 +ÙŠØ 461 +. 430 +_Çä 405 +§Ù„Ù 352 +ال٠352 +Ùƒ 350 +ƒ 350 +È 340 +د 339 +¯ 339 +ØªØ 334 +ªØ 334 +Ñ 324 + 314 +Ù 314 +ç 302 +_Ùˆ 289 +…Ù 278 +Ù…Ù 278 +Ù†Ø 276 +†Ø 276 +ع٠270 +¹Ù 270 +Ê 267 +ÙˆÙ 263 +ˆÙ 263 +Ù†_ 262 +†_ 262 +_Ù… 259 +‡ 258 +Ù‡ 258 +³ 258 +س 258 +لا 258 +„ا 258 +æ_ 257 +Ø¨Ø 252 +¨Ø 252 +ˆØ 252 +ÙˆØ 252 +¬ 252 +§_ 250 +ا_ 250 +Ï 242 +_è 235 +ت_ 226 +ª_ 226 +._ 223 +±Ù 213 +ر٠213 +§Øª 206 +ات 206 +­ 202 +Ø­ 202 +Ç_ 200 +±Ø 199 +Ø±Ø 199 +á 199 +¹Ø 198 +Ø¹Ø 198 +¨Ù 196 +ب٠196 +ÙƒØ 193 +ƒØ 193 +ت٠191 +لم 191 +ªÙ 191 +„Ù… 191 +.. 188 +Ù‚ 184 +‚ 184 +ج 183 +ان 180 +§Ù† 180 +§Ù„ا 178 +Š_ 176 +ية 176 +ŠØ© 176 +ÙŠ_ 176 +ã 175 +ÙÙ 175 +Ù 175 +_ب 171 +Ì 171 +§Ù„Ù… 170 +à 166 +ˆ_ 165 +Ùˆ_ 165 +Ù‡Ø 163 +_Ù 163 +‡Ø 163 +´ 162 +Ø´ 162 +Ù„_ 162 +„_ 162 +ŠÙ 161 +ÙŠÙ 161 +É 160 +â 159 +ية_ 158 +ŠØ©_ 158 +‰ 155 +Ù‰ 155 +Ø³Ø 153 +³Ø 153 +Ù‰_ 150 +‰_ 150 +Í 150 +Ó 148 +§Øª_ 147 +ات_ 147 +µ 144 +_å 144 +ص 144 +ç_ 142 +„Ù…Ø 139 +Ù„Ù…Ø 139 +_ÙÙ 136 +_Ù…Ù 133 +ما 130 +_Ø¨Ø 130 +…ا 130 +Ø´Ø 129 +´Ø 129 +_Ùˆ_ 129 +¯Ø 128 +Ø¯Ø 128 +É_ 127 +äÇ 127 +_Ù…Ø 126 +ر_ 124 +±_ 124 +عل 123 +¹Ù„ 123 +ÙÙŠ 122 +ÙŠ 122 +Ù‚Ø 121 +_È 121 +‚Ø 121 +­Ø 119 +Ø­Ø 119 +لا٠118 +„ا٠118 +ò 117 +ê_ 117 +_ع 117 +î 116 +†Ù 115 +_ت 115 +Ù†Ù 115 +äå 113 +¯Ù 113 +د٠113 +…Ù† 111 +مع 111 +…ع 111 +من 111 +عل٠110 +¹Ù„Ù 110 +_à 109 +_Ù„ 108 +ÙƒÙ 108 +ƒÙ 108 +ÙŠ_ 102 +ها 102 +Ù„Ø§Ø 102 +„Ø§Ø 102 +ÙÙŠ_ 102 +‡Ø§ 102 +® 101 +¬Ø 101 +Ø® 101 +_ÙˆØ 100 +Ø¬Ø 100 +_ÙÙŠ 99 +ÙØ 99 +Ø 99 +Ð 98 +¯_ 97 +ام 97 +§Ù… 97 +د_ 97 +... 94 +_من 94 +¨Ø§ 93 +· 93 +با 93 +_Ø§Ø 93 +Ø· 93 +ˆØ§ 92 +ï 92 +وا 92 +نت 91 +†Øª 91 +ä_ 90 +Çæ 89 +_á 89 +Ï_ 88 +èÇ 87 +_ع٠87 +لى 85 +„Ù‰ 85 +èä 84 +Ø° 84 +…Ù†_ 84 +س٠84 +³Ù 84 +„Ù‰_ 84 +° 84 +لى_ 84 +من_ 84 +Çäå 84 +- 83 +®Ø 83 +Ø®Ø 83 +_ä 82 +…_ 82 +§Ø³ 82 +اس 82 +Ù…_ 82 +_Çäå 81 +ˆÙ… 80 +é 80 +وم 80 +é_ 79 +Ø§Ù†Ø 79 +§Ù†Ø 79 +¹_ 78 +±Ø§ 78 +¹Ø§ 78 +عا 78 +§Ø± 78 +ها_ 78 +ع_ 78 +¬_ 78 +‡Ø§_ 78 +را 78 +ار 78 +µØ 78 +ØµØ 78 +.._ 77 +Ø£ 77 +..._ 77 +£ 77 +Ô 77 +„ÙŠ 76 +لي 76 +ªØ± 75 +تر 75 +« 74 +لك 73 +ان_ 73 +ض 73 +Ø« 73 +¬Ù 73 +ج٠73 +¶ 73 +§Ù†_ 73 +„Ùƒ 73 +مع٠72 +…ع٠72 +åæ 71 +èÌ 70 +†Ø§ 70 +نا 70 +­Ù 69 +î_ 69 +Ø­Ù 69 +êæ 69 +„ت 68 +لت 68 +ŠØ§ 68 +Ùä 68 +_ØªØ 68 +يا 68 +_ê 67 +Ë 66 +ò. 66 +èÏ 66 +_¬_ 65 +³Øª 65 +äè 65 +ست 65 +_¬ 65 +Ìè 65 +ð 64 +ÙˆÙ…Ø 64 +áê 64 +ˆÙ…Ø 64 +èæ 63 +Ø§Ø³Ø 63 +Õ 63 +§Ø³Ø 63 +Ñ_ 62 +-_ 62 +ÇÊ 61 +_- 61 +„Ùˆ 61 +لو 61 +_ان 61 +åÇ 61 +å_ 61 +äé_ 60 +§Ø¯ 60 +_ÙˆÙ 60 +èÌè 60 +Ö 60 +اد 60 +äé 60 +†ØªØ 59 +ÌèÏ 59 +_-_ 59 +_عل 59 +Ù†ØªØ 59 +èÌèÏ 58 +Ù‡Ù 58 +² 58 +جا 58 +‡Ù 58 +„ب 58 +لب 58 +_ÙŠ 58 +_åæ 58 +ز 58 +_Ù„Ø 58 +¬Ø§ 58 +ƒØ§ 57 +§Ù†Øª 57 +ˆÙ„ 57 +كا 57 +ول 57 +ò.. 56 +شب 56 +ò..._ 56 +´Ø¨ 56 +Çæ_ 56 +ò... 56 +¨ÙŠ 56 +بي 56 +تع 55 +عم 55 +¹Ù„Ù‰ 55 +_Ùƒ 55 +ªØ¹ 55 +_._ 55 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/arabic-windows1256.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/arabic-windows1256.lm new file mode 100644 index 0000000..65682cc --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/arabic-windows1256.lm @@ -0,0 +1,400 @@ +_ 3974 +Ç 1252 +á 958 +æ 626 +í 534 +ä 498 +Çá 496 +ã 482 +_Ç 473 +_Çá 408 +È 345 +. 335 +Ñ 326 +å 303 +Ê 269 +Ú 260 +ä_ 258 +Ï 244 +_æ 235 +Ý 202 +Ç_ 200 +.. 188 +ß 175 +Ì 173 +à 166 +É 162 +Þ 157 +Í 150 +Ó 150 +_ã 145 +å_ 143 +._ 130 +áÇ 129 +É_ 129 +_È 124 +í_ 120 +ú 117 +ó 116 +áã 115 +_à 109 +Ð 98 +... 94 +õ 92 +_Ý 92 +_Ú 90 +Çä 90 +á_ 90 +Ï_ 88 +æÇ 87 +Çáã 86 +æá 84 +_Çáã 83 +_á 82 +ì 80 +ì_ 79 +Ô 77 +.._ 77 +..._ 77 +æÌ 72 +ãä 71 +¡_ 69 +Úá 69 +¡ 69 +íä 69 +ó_ 68 +æÏ 68 +_í 67 +Ìæ 67 +Ýí 67 +Ë 66 +ú. 66 +áæ 65 +ö 64 +æä 63 +ÇÊ 63 +Õ 63 +ã_ 62 +ãÇ 62 +æÌæ 62 +Ñ_ 62 +ÌæÏ 61 +áì 60 +æÌæÏ 60 +Ö 60 +áì_ 60 +_¡_ 58 +_ãä 58 +_¡ 58 +Çä_ 57 +ú..._ 56 +ú.. 56 +ú... 56 +-_ 53 +- 53 +_- 52 +_-_ 52 +_Ýí 51 +ãä_ 50 +áí 50 +Çáæ 50 +_æÇ 50 +ÐÇ 49 +áÇ_ 48 +Á 48 +áÚ 47 +_ß 47 +È_ 47 +ö_ 46 +_Çáæ 45 +æä_ 45 +íÇ 44 +Ò 44 +Ýí_ 44 +_Úá 43 +_Ñ 43 +õ_ 43 +æÏ_ 43 +_ãä_ 43 +ÌæÏ_ 42 +æÌæÏ_ 42 +Î 42 +ÇáÚ 41 +Ø 41 +ÍÇ 41 +Úáì_ 40 +_Ê 40 +Úáì 40 +_Çä 40 +ãÑ 40 +íä_ 39 +Èí 39 +åÇ 39 +_ÇáÚ 38 +ÑÇ 38 +áå 37 +äí 37 +_Þ 37 +_Ýí_ 36 +Ê_ 36 +ÊÈ 35 +_æá 35 +áæÌ 35 +áá 35 +_Çä_ 35 +áæÌæ 35 +Êå 34 +ãÇ_ 34 +Á_ 34 +Æ 34 +ÐÇÊ 34 +áæÌæÏ 34 +ÇáæÌ 33 +ÇáæÌæ 33 +ÇáÇ 33 +ßæ 33 +_å 32 +Çæ 32 +äÇ 31 +ßæä 31 +ÇÈ 31 +ÈÉ 31 +åÇ_ 31 +_Ì 30 +áä 30 +Çæá 30 +íÑ 30 +_ÇáæÌ 30 +Êõ 30 +Çã 30 +Ãä 30 +Û 30 +_Í 30 +ø 29 +Èá 29 +ÇÁ 29 +Êå_ 29 +ÃÍ 29 +æÑ 29 +ÇÏ 29 +íå 29 +_ÃÍ 29 +Å 29 +ÈÇ 29 +_Úáì_ 28 +ÇÊå 28 +_ÇáÇ 28 +_Úáì 28 +ÈÉ_ 28 +ãæ 27 +ßæä_ 27 +_Ô 27 +ÑÊ 27 +íÉ 27 +áß 27 +æÇá 27 +æã 27 +ÐÇÊå 27 +Ó_ 26 +_. 26 +Çá_ 26 +ÞÇ 26 +_æÇá 26 +ßÇ 26 +íÉ_ 26 +äå 26 +ÇÊå_ 26 +_._ 26 +æá_ 25 +Ïí 25 +ÚÑ 25 +ÐÇÊå_ 25 +áå_ 25 +ãÓ 24 +ÇÆ 24 +ÏÇ 24 +íß 24 +_áÇ 24 +æÈ 23 +ÊÈÉ_ 23 +ãÑÊÈ 23 +_ÃÍÇæ 23 +äæ 23 +Ãí 23 +Çáá 23 +äú 23 +ÑÊÈ 23 +ÚÇ 23 +íßæ 23 +íßæä 23 +ÍÇæá 23 +ÊÈÉ 23 +ÃÍÇæá 23 +íßæä_ 23 +_ÃÍÇ 23 +ÇÑ 23 +ÃÍÇ 23 +Èú 23 +_Çáá 23 +ÍÇæ 23 +ãÑÊ 23 +ÃÍÇæ 23 +_íß 23 +_íßæä 22 +ãÑÊÈÉ 22 +ò 22 +ÇÌ 22 +ÌÈ 22 +äí_ 22 +_íßæ 22 +ÑÊÈÉ 22 +Çæá_ 22 +ÑÊÈÉ_ 22 +ß_ 22 +_Å 21 +_Èá 21 +áãÑ 21 +Þí 21 +ÑÈ 21 +ßá 21 +æáÇ 21 +Êõ_ 21 +ÇáãÑ 21 +Çáä 21 +_ÇáãÑ 20 +Ïå 20 +ÌÈ_ 20 +ááå 20 +ÇáË 20 +ÇÊ_ 20 +áË 20 +ÑÓ 20 +_Ð 20 +ÇÓ 20 +åæ 20 +Úí 19 +Çå 19 +Èä 19 +æ_ 19 +åÐ 19 +Ðå 19 +Èíä 19 +áã_ 19 +_Ãä 19 +íÑ_ 19 +áÊ 19 +ÍÇæá_ 18 +áÔ 18 +Çááå 18 +ÇÌÈ_ 18 +æÇÌÈ_ 18 +ËÇ 18 +Úä 18 +ááå_ 18 +Ãä_ 18 +íÏ 18 +ÇÌÈ 18 +Ôí 18 +_Çáä 18 +áãÑÊÈ 18 +_æà 18 +_Çááå 18 +áãÑÊ 18 +æÇÌ 18 +Ñí 18 +æà 18 +ÇáãÑÊ 18 +æÇÌÈ 18 +ÞÏ 18 +_ÞÇ 17 +ÇáÔ 17 +Úíä 17 +ÝÇ 17 +åã 17 +Ú_ 17 +íÇ_ 17 +ãæÌ 17 +ò_ 17 +Çááå_ 17 +ãÊ 17 +äú. 17 +ãæÌæ 17 +íÓ 17 +ÚÏ 17 +ÍÏ 17 +ÌÇ 17 +Óí 17 +_áÇ_ 17 +ãæÌæÏ 17 +æÑ_ 17 +Èå 16 +Õæ 16 +_æã 16 +ÇÁ_ 16 +äå_ 16 +Ù 16 +_æáÇ 16 +Çäí 16 +_åÐ 16 +_ÐÇ 16 +ÓÇ 16 +ÓÊ 16 +ßä 16 +áÐ 16 +Óã 16 +_ÐÇÊ 16 +ÇÚ 16 +ñ 16 +áæÇ 16 +íÊ 16 +ãÍ 16 +_ÈÐ 15 +íÞ 15 +æáÇ_ 15 +ÇáÚÑ 15 +áíå 15 +_Çáãæ 15 +áãæ 15 +äÇ_ 15 +ÚÑÈ 15 +_æÌ 15 +_ÇáÔ 15 +Çáãæ 15 +Þ_ 15 +Ëá 15 +_ÇáÚÑ 15 +áó 15 +áÚÑ 15 +æÝ 15 +_ä 15 +ÈÐ 15 +íá 14 +Óá 14 +ÐÇ_ 14 +! 14 +Èíä_ 14 +ÇáæÇ 14 +_ÑÓ 14 +ÇáÚÑÈ 14 +ÈÊ 14 +áó_ 14 +Úáí 14 +æÚ 14 +áÚÑÈ 14 +_ÇáÐ 14 +åä 14 +ÇáÊ 14 +ÇáÐ 14 +_Ãä_ 14 +Ý_ 14 +áÝ 14 +Èú. 14 +ãí 14 +áÛ 13 +åÐå_ 13 +åÐå 13 +_åÐå 13 +ÖÇ 13 +_ßá 13 +áØ 13 +ÈáÇ 13 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/basque.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/basque.lm new file mode 100644 index 0000000..32522a7 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/basque.lm @@ -0,0 +1,400 @@ +_ 12114 +a 5537 +e 4040 +i 3103 +t 2567 +n 2474 +r 2406 +o 1937 +k 1761 +z 1627 +u 1561 +d 1367 +l 1075 +s 1048 +b 995 +n_ 958 +a_ 957 +en 802 +g 772 +_e 736 +er 680 +ra 669 +. 625 +at 610 +_b 594 +ar 589 +an 585 +_d 580 +, 569 +,_ 569 +h 563 +ta 563 +te 555 +._ 520 +ko 513 +m 503 +o_ 486 +al 481 +en_ 471 +tz 458 +re 435 +_a 423 +ik 416 +in 409 +it 392 +za 391 +ak 388 +ba 358 +et 357 +da 352 +di 351 +ka 350 +ze 349 +ai 347 +p 340 +ri 335 +la 329 +an_ 327 +de 322 +ez 318 +na 314 +ti 307 +be 305 +i_ 302 +iz 294 +k_ 293 +tu 289 +eta 287 +( 280 +) 280 +_i 279 +or 276 +_( 270 +ko_ 269 +ek 265 +rr 264 +_h 263 +e_ 260 +es 260 +_ba 258 +nt 258 +ha 255 +_g 247 +era 246 +ia 240 +_be 234 +oa 229 +un 229 +ta_ 218 +ma 212 +on 211 +z_ 209 +du 207 +(_ 205 +_(_ 205 +: 204 +tze 204 +:_ 204 +us 191 +u_ 191 +_da 188 +ren 183 +az 183 +_) 183 +ur 182 +st 182 +ea 181 +_et 181 +eta_ 179 +zi 178 +si 177 +zen 177 +as 176 +_n 175 +go 175 +_eta 172 +il 169 +tik 169 +_z 167 +_eta_ 167 +ne 167 +bi 166 +zk 166 +sk 165 +ag 163 +t_ 162 +le 160 +rt 160 +ke 158 +- 150 +gu 148 +au 148 +tza 147 +_de 147 +ati 146 +ut 146 +A 145 +li 145 +hi 145 +E 144 +bat 144 +_o 143 +a, 142 +a,_ 142 +_m 141 +ntz 141 +ad 140 +ren_ 139 +_er 138 +io 138 +)_ 138 +_ez 138 +ir 137 +eh 137 +ab 135 +ate 135 +ak_ 134 +sa 134 +ra_ 134 +_bat 133 +nd 133 +_l 133 +ki 132 +ere 131 +ika 125 +ku 125 +f 124 +ga 123 +ld 122 +_di 121 +arr 120 +el 120 +eg 119 +uz 119 +are 116 +ng 116 +os 116 +_E 115 +gi 113 +_p 113 +_du 113 +mo 113 +zen_ 112 +ib 111 +_k 110 +ber 109 +ako 108 +_iz 107 +iza 107 +ala 107 +itz 107 +har 106 +eko 106 +adi 105 +l_ 105 +ie 105 +ste 105 +atu 104 +am 104 +ska 104 +ah 104 +_. 104 +r_ 104 +zt 103 +rri 103 +ait 103 +ua 103 +tzen 103 +ald 103 +usk 102 +aren 102 +_._ 102 +ro 102 +id 100 +la_ 99 +_s 98 +ue 98 +tek 97 +uska 97 +atz 96 +aren_ 96 +_ha 95 +rre 95 +" 94 +atik 94 +tzen_ 94 +ara 94 +in_ 93 +ni 93 +j 92 +ge 91 +ez_ 91 +ain 91 +od 91 +no 91 +na_ 91 +ri_ 90 +tan 90 +mat 90 +do 89 +_mo 88 +ho 88 +iko 88 +beh 88 +_ad 88 +al_ 87 +_iza 87 +I 87 +zan 87 +_ze 87 +_adi 87 +_A 86 +uk 86 +eha 85 +dit 85 +ru 85 +pe 85 +eko_ 84 +ela 84 +ed 84 +kar 84 +n,_ 83 +ari 83 +bil 83 +_beh 83 +bai 83 +tu_ 83 +n, 83 +ehar 83 +_izan 82 +itu 82 +_ho 82 +is 82 +ean 82 +ama 82 +izan 82 +_)_ 81 +ik_ 81 +B 80 +koa 80 +ot 80 +_na 79 +zu 79 +beha 78 +behar 78 +_t 78 +H 78 +_ko 78 +dir 77 +mati 76 +_j 75 +at_ 75 +em 74 +tika 74 +K 74 +_B 74 +zte 74 +ten 74 +_beha 74 +ter 74 +matik 73 +egi 73 +_dir 73 +a. 72 +ago 72 +kal 72 +ram 72 +ena 72 +unt 71 +lt 71 +_H 71 +su 71 +mod 71 +bo 71 +G 70 +_ber 70 +lde 70 +c 69 +te_ 69 +ar_ 69 +me 69 +ina 69 +dal 69 +ako_ 68 +L 68 +rik 68 +a._ 68 +ori 68 +ite 68 +raz 67 +alde 67 +)._ 67 +). 67 +zio 66 +_ez_ 66 +tan_ 66 +amat 66 +atika 66 +est 66 +ntza 65 +dut 65 +izk 65 +_ga 65 +ia_ 65 +s_ 65 +ita 65 +tea 64 +ei 64 +hal 64 +_mod 64 +pa 64 +bu 64 +re_ 63 +eu 63 +ert 63 +oa_ 63 +_era 63 +ten_ 63 +_G 63 +_eg 63 +rama 63 +odal 63 +ramat 63 +oda 63 +amati 62 +atze 62 +gr 62 +untz 62 +eza 62 +gra 62 +_ge 61 +gram 61 +kat 61 +abi 61 +_gr 60 +_gram 60 +_gra 60 +int 60 +rd 60 +_in 60 +k, 59 +_hi 59 +zko 59 +k,_ 59 +pr 59 +rab 59 +da_ 59 +ide 58 +_)._ 57 +tat 57 +ing 57 +ira 57 +tak 57 +x 57 +_). 57 +_ed 57 +_es 57 +_bi 57 +rak 56 +_- 56 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/breton.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/breton.lm new file mode 100644 index 0000000..7fd3a8f --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/breton.lm @@ -0,0 +1,400 @@ +_ 21447 +e 6375 +a 5414 +n 3228 +r 3039 +o 2968 +t 2392 +i 1812 +h 1751 +u 1650 +l 1630 +d 1506 +a_ 1352 +z 1319 +t_ 1310 +_e 1168 +_a 1168 +e_ 1133 +m 1105 +s 1100 +g 1090 +r_ 998 +k 997 +n_ 958 +et 941 +v 888 +_d 868 +an 859 +. 846 +' 841 +en 836 +b 757 +, 749 +,_ 743 +._ 716 +ar 703 +ou 700 +et_ 689 +c 686 +ez 572 +'h 572 +_g 565 +er 555 +p 553 +_k 535 +c'h 530 +c' 530 +nt 513 +_h 505 +re 505 +ra 478 +ha 466 +ñ 458 +ne 456 +oa 454 +_o 442 +_b 434 +- 432 +zh 422 +ar_ 415 +_m 414 +_e_ 414 +nn 384 +el 376 +_a_ 356 +ur 350 +o_ 346 +h_ 345 +ve 340 +nt_ 340 +w 339 +ke 338 +de 333 +añ 332 +_p 332 +s_ 327 +he 325 +on 318 +le 318 +ga 316 +ma 315 +_ar 312 +eu 312 +_n 310 +an_ 298 +ant 296 +enn 285 +z_ 282 +_ar_ 281 +be 280 +_v 276 +_r 272 +al 270 +en_ 268 +_ke 267 +l_ 264 +em 264 +_c 263 +ñ_ 262 +da 262 +_s 261 +ho 260 +di 259 +_ha 252 +ll 250 +tr 248 +oa_ 247 +me 246 +us 242 +_ga 234 +la 231 +ket 227 +ant_ 219 +_da 219 +_l 216 +ur_ 216 +_oa 215 +in 214 +ket_ 211 +gan 211 +_c' 207 +_u 207 +_c'h 207 +ad 207 +añ_ 207 +ao 204 +_ma 204 +_t 204 +_ket 201 +_an 199 +_di 197 +ezh 196 +ù 196 +où 196 +_de 195 +ev 193 +? 192 +st 192 +ro 192 +P 192 +_ket_ 188 +er_ 188 +f 186 +na 186 +ue 185 +da_ 184 +?_ 184 +_gan 184 +_da_ 184 +_ne 183 +ed 182 +_P 180 +g_ 180 +pe 179 +m_ 178 +A 177 +ri 176 +us_ 175 +ta 174 +ze 174 +gant 174 +ka 174 +i_ 172 +d_ 171 +G 167 +te 167 +ae 166 +zh_ 164 +ha_ 163 +_ha_ 163 +_he 161 +_gant 159 +do 159 +oue 159 +_G 158 +eus 158 +eo 158 +'h_ 157 +_en 157 +go 157 +am 157 +c'h_ 157 +_be 156 +we 156 +iz 154 +_an_ 151 +_A 150 +eus_ 147 +sk 147 +li 146 +as 146 +_pe 146 +j 146 +_oa_ 146 +av 144 +gant_ 143 +ut 142 +no 141 +vez 140 +va 140 +_ra 140 +ge 138 +ez_ 138 +bo 137 +  137 +_ur 136 +lo 134 +he_ 134 +où_ 133 +ù_ 133 +_ur_ 132 +es 130 +'ho 129 +ni 129 +uz 129 +tra 127 +se 126 +it 125 +ra_ 125 +out 125 +is 125 +at 125 +hi 125 +eg 125 +ig 124 +ko 124 +io 123 +k_ 123 +ch 123 +_w 121 +or 121 +Pe 121 +_ma_ 119 +ma_ 119 +gw 118 +_em 118 +_Pe 118 +un 118 +eme 117 +ne_ 117 +nn_ 117 +c'ho 117 +ol 116 +ag 116 +M 115 +'ha 115 +_en_ 115 +iv 115 +vi 113 +_ka 113 +K 113 +ud 112 +_he_ 111 +ont 110 +oc 110 +vo 110 +ec 109 +wa 109 +.. 107 +_M 107 +_z 107 +br 107 +om 106 +to 105 +_f 105 +N 105 +_c'ho 104 +ti 104 +ut_ 104 +D 104 +_o_ 103 +_la 103 +_go 101 +az 101 +out_ 101 +ba 101 +enn_ 101 +c'ha 101 +our 100 +oc'h 100 +ell 100 +oc' 100 +etr 99 +el_ 99 +_K 99 +_D 99 +: 99 +:_ 99 +eve 98 +_d' 97 +all 97 +d' 97 +E 97 +_ne_ 97 +_me 95 +eo_ 95 +ak 95 +bet 95 +_eu 95 +rc 94 +_do 94 +_gw 94 +zi 93 +oz 93 +aou 93 +etra 92 +pa 91 +ab 90 +on_ 90 +ei 90 +tra_ 90 +n, 89 +zo 89 +ag_ 89 +_ev 88 +ul 88 +'e 88 +n' 88 +n,_ 88 +ouz 87 +v_ 86 +_n' 86 +_eus 84 +H 83 +za 83 +S 83 +etra_ 83 +_eo 82 +t,_ 82 +t, 82 +il 81 +ent 81 +fe 81 +rc'h 81 +rc' 81 +_eus_ 80 +ie 80 +_bo 79 +ele 79 +_ve 79 +mp 79 +_bet 78 +B 78 +it_ 77 +_vo 77 +'a 77 +n. 76 +_S 76 +hag 76 +hoa 75 +_hag 75 +len 75 +_N 75 +'hoa 74 +_E 74 +ir 74 +hag_ 74 +_hag_ 74 +mañ 74 +as_ 73 +eze 73 +ont_ 73 +_. 73 +iñ 73 +r, 72 +pr 72 +ed_ 72 +n._ 72 +re_ 72 +in_ 72 +r,_ 72 +_H 71 +'he 70 +t. 70 +gou 70 +em_ 70 +_br 70 +rae 70 +rez 69 +t._ 69 +bet_ 69 +net 69 +dr 68 +_eo_ 68 +ll_ 68 +mo 67 +po 67 +oul 67 +rou 67 +c'hoa 67 +a- 67 +vel 67 +oc'h_ 67 +nna 66 +_B 66 +met 65 +ec' 65 +ec'h 65 +R 64 +den 64 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/catalan.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/catalan.lm new file mode 100644 index 0000000..7a055eb --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/catalan.lm @@ -0,0 +1,400 @@ +_ 16604 +e 5091 +a 4937 +s 3120 +r 3037 +i 2987 +l 2747 +n 2641 +t 2466 +o 2274 +d 1775 +c 1740 +u 1515 +a_ 1460 +s_ 1416 +_d 1116 +e_ 1067 +p 1014 +m 995 +es 985 +de 972 +_de 842 +en 700 +_l 691 +re 652 +_e 637 +de_ 611 +el 602 +_de_ 601 +_a 600 +, 599 +,_ 599 +er 598 +la 584 +ar 583 +_p 550 +l_ 547 +ci 522 +n_ 518 +es_ 515 +an 515 +ra 499 +nt 495 +ta 495 +b 476 +_c 452 +al 450 +v 440 +g 428 +. 420 +on 420 +or 404 +t_ 402 +at 396 +._ 377 +r_ 372 +i_ 371 +la_ 368 +_i 364 +_la 351 +_la_ 325 +f 325 +le 322 +te 312 +' 311 +_s 308 +st 308 +se 305 +ó 302 +ue 302 +na 301 +os 301 +qu 300 +q 300 +el_ 299 +it 292 +co 290 +ri 277 +ca 277 +ti 273 +ac 272 +in 268 +ll 264 +ic 264 +me 259 +un 257 +que 248 +C 248 +tr 244 +ns 242 +ió 238 +_i_ 236 +ad 233 +ent 232 +_el 227 +ne 226 +_t 223 +_co 221 +_m 221 +_C 217 +en_ 217 +li 217 +ia 212 +à 212 +pe 207 +_a_ 207 +pr 206 +ció 203 +ó_ 203 +pa 203 +ro 202 +o_ 198 +E 198 +di 197 +io 197 +ls 196 +h 192 +_q 192 +_qu 192 +_en 187 +aci 186 +am 186 +ec 183 +to 183 +as 180 +om 180 +ni 180 +da 179 +ió_ 179 +si 178 +ls_ 176 +L 175 +ma 172 +res 172 +ur 171 +_el_ 162 +rt 162 +ue_ 160 +A 160 +os_ 159 +_que 159 +que_ 158 +_r 158 +po 157 +_es 155 +er_ 155 +_que_ 155 +M 155 +_se 153 +va 153 +del 153 +ció_ 151 +_pr 151 +is 150 +_en_ 149 +P 147 +_pe 146 +_del 145 +ts 145 +lo 145 +_M 144 +ct 144 +_u 144 +ol 143 +ve 141 +_L 140 +x 140 +y 140 +a,_ 139 +a, 139 +nc 138 +men 137 +al_ 137 +_f 137 +_re 137 +_P 136 +ació 136 +les 136 +rs 134 +est 133 +tu 131 +_E 130 +et 130 +s,_ 129 +_un 129 +na_ 129 +_v 129 +s, 129 +ion 127 +per 126 +so 125 +em 125 +at_ 124 +no 124 +j 124 +br 123 +nt_ 122 +ar_ 122 +sa 121 +_n 119 +les_ 118 +é 118 +ce 117 +il 117 +ell 116 +_per 114 +í 114 +ob 113 +re_ 113 +ir 113 +_A 112 +ons 112 +do 112 +ua 112 +con 112 +ment 111 +gu 111 +ts_ 110 +ss 110 +ns_ 109 +ant 109 +ra_ 109 +Co 109 +par 108 +l' 107 +d' 107 +_l' 107 +els 107 +tat 107 +sc 106 +_d' 106 +an_ 105 +_Co 105 +vi 104 +els_ 104 +ica 104 +ran 103 +ul 102 +iv 102 +S 102 +_del_ 102 +del_ 102 +mb 101 +mi 101 +ita 101 +nta 100 +_pa 99 +_o 99 +_con 98 +ació_ 97 +rn 96 +_in 96 +ia_ 96 +z 96 +im 95 +rr 95 +art 94 +ta_ 93 +com 93 +tre 92 +_h 92 +s. 91 +mp 90 +ie 90 +J 90 +s._ 89 +cio 89 +_le 89 +bre 88 +_ca 88 +_al 88 +sta 88 +_com 88 +cu 88 +à_ 87 +pre 87 +fe 86 +ba 86 +tra 86 +ge 85 +pro 85 +_les 84 +des 84 +ter 84 +_po 84 +_les_ 84 +T 84 +_J 84 +nd 84 +cion 84 +_S 84 +ura 83 +nci 82 +va_ 81 +ha 81 +ona 81 +ent_ 80 +ues 80 +oc 80 +ea 80 +nte 80 +és 80 +_di 79 +ui 79 +as_ 78 +ut 78 +ici 78 +res_ 78 +us 77 +ot 77 +ara 77 +ip 75 +rm 75 +ab 75 +eg 75 +_per_ 75 +ng 75 +'a 75 +I 75 +per_ 75 +rec 74 +du 74 +_tr 74 +è 73 +cia 73 +_no 73 +b_ 73 +_par 72 +ep 72 +id 72 +lle 71 +rc 71 +_pro 70 +D 69 +G 69 +ga 69 +fo 69 +una 68 +El 68 +lit 68 +un_ 68 +ques 68 +amb 67 +ix 67 +és_ 67 +_G 67 +era 67 +cr 67 +) 66 +da_ 66 +- 66 +sp 66 +y_ 66 +ada 66 +tor 66 +( 66 +_( 66 +_T 65 +ment_ 65 +B 65 +_es_ 65 +Ma 65 +V 65 +uc 65 +ect 65 +ame 64 +iu 64 +_Ma 64 +orn 64 +_B 64 +_D 64 +Ca 64 +sti 64 +_g 63 +esc 63 +rd 63 +una_ 63 +là 62 +" 62 +ed 62 +amen 61 +mo 61 +ions 61 +_El 61 +_Ca 61 +Jo 61 +eu 61 +ari 61 +lt 61 +F 61 +u_ 61 +ament 60 +_V 60 +m_ 60 +fi 60 +au 60 +ev 60 +La 60 +itat 59 +_ha 59 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/chinese-big5.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/chinese-big5.lm new file mode 100644 index 0000000..0564f42 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/chinese-big5.lm @@ -0,0 +1,400 @@ +_ 30653 +¤ 2524 +_¤ 2123 +¡ 1457 +¥ 1406 +_¥ 1245 +¦ 1244 +_¡ 1196 +_¦ 1100 +ª 833 +M 783 +M_ 764 +_ª 727 +¡M_ 688 +¡M 688 +_¡M_ 684 +_¡M 684 +³ 680 +­ 675 +¨ 659 +° 629 +º 593 +¬ 566 +_¨ 560 +« 533 +_­ 516 +® 497 +_¬ 495 +_° 485 +¸ 483 +§ 473 +© 459 +· 458 +µ 448 +_« 442 +¹ 436 +_® 425 +± 422 +_© 422 +_³ 404 +² 401 +» 393 +º_ 385 +_· 382 +_§ 374 +_¸ 373 +´ 350 +C 333 +¾ 324 +ªº 318 +½ 315 +_¹ 314 +_± 312 +¶ 310 +ªº_ 303 +C_ 303 +_ªº 303 +_ªº_ 302 +_² 302 +@ 288 +_¶ 279 +@_ 275 +Ä 275 +À 272 +_´ 269 +_µ 269 +| 268 +Q 265 +q 260 +~ 260 +|_ 255 +~_ 250 +Á 241 +A 235 +¼ 234 +_¾ 233 +Ó 233 +¡C_ 226 +¡C 226 +Ó_ 225 +£ 224 +_¡C 224 +_¡C_ 224 +³_ 222 +A_ 218 +Q_ 217 +O 210 +q_ 210 +D 209 +_Ä 206 +ø 202 +H 200 +¤@ 198 +à 197 +¯ 196 +O_ 196 +_» 195 +£_ 192 +H_ 191 +¤@_ 190 +_¤@ 189 +_¤@_ 189 +ø_ 180 +ê 177 +P 176 +D_ 175 +¿ 173 +Î 172 +ê_ 172 +Î_ 170 +_º 168 +É 165 +u 164 +_Á 162 +_¼ 162 +_·| 161 +·| 161 +_·|_ 161 +Ü 161 +L 161 +·|_ 161 +û 157 +p 156 +o 156 +Ç 155 +_¯ 155 +µ_ 153 +Ü_ 151 +¡A 151 +Ç_ 151 +W 151 +¤Q 151 +L_ 150 +û_ 150 +Æ 149 +u_ 149 +ó 147 +Å 147 +¡A_ 146 +_À 145 +p_ 145 +ó_ 143 +_½ 142 +_¡A_ 142 +_¡A 142 +{ 141 +ä 140 + 140 +½_ 140 +P_ 139 +É_ 137 +W_ 136 +{_ 136 +ä_ 135 +T 134 +Ñ 134 +j 134 +× 132 +_à 131 +Ñ_ 131 +d 130 +G 130 +X 130 +o_ 129 +j_ 127 +F 126 +×_ 126 +F_ 125 +é 124 +b 123 +v 122 +÷ 122 +_ 122 +Æ_ 121 +»_ 120 +Ð 120 +d_ 120 +¤_ 119 +b_ 118 +T_ 118 +æ 117 +X_ 116 +n 116 +_¿ 116 +e 115 +Ò 115 +÷_ 115 +v_ 114 +w 114 +a 114 +¤H 114 +æ_ 114 +i 114 +­_ 113 +Ò_ 113 +ï 112 +â 111 +¤H_ 111 +_¤H_ 110 +_¤H 110 +è 109 +°ê 109 +À_ 107 +w_ 107 +_°ê 107 +°ê_ 106 +_°ê_ 106 +è_ 106 +¦³ 105 +ï_ 105 +Õ 105 +¤Q_ 105 +a_ 104 +] 104 +_¦b_ 103 +_¦b 103 +h 103 +_¤Q 103 +¦b 103 +¦b_ 103 +_¤Q_ 103 +¡_ 102 +Ê 102 +­û_ 101 +­û 101 +k 100 +_­û_ 100 +e_ 100 +_­û 100 +k_ 100 +_¦³ 100 +¦³_ 100 +_¦³_ 100 +B 99 +ü 99 +¤é 98 +°_ 98 +s 98 +_Å 98 +â_ 98 +¤j 98 +i_ 97 +]_ 97 +n_ 96 +á 95 +h_ 95 +ü_ 95 +U 95 +á_ 94 +¤£ 94 +¤j_ 94 +Ê_ 94 +_¤j 93 +_¤j_ 93 +¹q 92 +õ 92 +È 92 +Õ_ 92 +§_ 92 +È_ 91 +S 90 +_¤£_ 90 +¤£_ 90 +_¤£ 90 +ì 90 +®É 89 +ú 89 +¤¤ 88 +B_ 88 +Ø 88 +_®É_ 87 +_®É 87 +U_ 87 +í 87 +®É_ 87 +N 87 +¦~ 86 +_¦~_ 86 +ì_ 86 +í_ 86 +ô 86 +_¦~ 86 +¦~_ 86 +Ï 85 +^ 85 +¤Î 84 +¤Î_ 84 +ù 84 +Ø_ 84 +G_ 84 +N_ 83 +_¤Î 83 +_¤Î_ 83 +_¤¤ 83 +E 83 +õ_ 82 +´ä 81 +¤¤_ 81 +±_ 81 +¾Ç 81 +_¤¤_ 81 +ß 80 +ô_ 80 +²_ 79 +¾Ç_ 79 +_¾Ç 79 +_¾Ç_ 79 +Ì 78 +_ªø 78 +_ªø_ 78 +ß_ 78 +ªø 78 +ªø_ 78 +¨_ 77 +S_ 77 +¬O_ 77 +_¬O_ 77 +_¬O 77 +_´ä_ 77 +´ä_ 77 +Ï_ 77 +_´ä 77 +¬O 77 +é_ 77 +Ì_ 76 +¸_ 76 +ù_ 76 +ú_ 75 +ë 74 +©ó 72 +t 72 +©ó_ 72 +_©ó 72 +_©ó_ 72 +s_ 71 +K 71 +¤T 71 +I 71 +Ð_ 71 +¤À 70 +¤è 70 +¬° 70 +Á_ 70 +¬°_ 69 +¤W 69 +«_ 69 +_¬°_ 68 +¬F_ 68 +_¬F 68 +_¤è_ 68 +¹_ 68 +_¬F_ 68 +_¤è 68 +¤è_ 68 +¤­ 68 +¬F 68 +_¬° 68 +¥X 67 +ý 67 +ö 66 +¦Ê_ 66 +¦Ê 66 +J 66 +_¦Ê_ 66 +¥D 66 +_¹q 66 +_¦Ê 66 +_¥D 66 +l 65 +Í 65 +z 65 +_¤W 65 +¥D_ 65 +_¥D_ 65 +ò 65 +Ú 65 +_¤W_ 64 +¤W_ 64 +¹q_ 64 +J_ 64 +ý_ 64 +_¹q_ 64 +_¤T 63 +_¥X_ 63 +¥X_ 63 +_¤À 63 +_¥X 63 +¤À_ 63 +¥» 63 +_¤À_ 63 +«á 62 +Y 62 +«á_ 61 +ò_ 61 +_«á 61 +_«á_ 61 +ĵ 61 +ö_ 61 +ĵ_ 60 +_¤T_ 60 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/chinese-gb2312.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/chinese-gb2312.lm new file mode 100644 index 0000000..3944d0e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/chinese-gb2312.lm @@ -0,0 +1,400 @@ +_ 77350 +£ 7152 +_£ 5428 +µ 3924 +Ä 3063 +¡ 3020 +¹ 2565 +Ö 2491 +Ê 2490 +_¡ 2490 +¬ 2438 +Ð 2424 +» 2394 +_µ 2391 +½ 2384 +Ò 2349 +¬_ 2233 +_£¬_ 2102 +£¬_ 2102 +£¬ 2102 +_£¬ 2102 +¼ 2057 +± 2043 +Ë 2000 +Ô 1999 +È 1936 +Í 1856 +² 1824 +Ó 1824 +° 1796 +· 1780 +¶ 1752 +Î 1728 +Ï 1726 +´ 1696 +Ä_ 1637 +³ 1631 +à 1630 +¸ 1630 +É 1596 +Õ 1571 +£_ 1545 +× 1535 +Á 1520 +µÄ 1505 +µÄ_ 1500 +_µÄ 1470 +_µÄ_ 1466 +º 1450 +¤ 1429 +ú 1425 +Ç 1367 +¾ 1364 +À 1356 +¿ 1335 +Æ 1306 +_Ê 1286 +¢ 1215 +¡£_ 1173 +_¡£_ 1173 +_¡£ 1173 +¡£ 1173 +_Ò 1141 +Ú 1131 +_½ 1124 +¤_ 1105 + 1083 +_Ö 1076 +_¹ 1048 +_È 1038 +_Ô 1026 +ª 1015 +±_ 1008 +Ì 973 +Å 952 +°_ 947 +¢_ 946 +Ú_ 932 +_Î 908 +_Á 904 +Ñ 876 +_× 831 +_¸ 823 +Ë_ 817 +_º 808 +_² 805 +_´ 803 +_· 790 +_Ó 785 +Ð_ 783 +_» 768 +_Í 766 +÷ 759 +_¶ 759 +µ_ 751 +_¼ 749 +¨ 744 +£¤_ 740 +_£¤ 740 +_£¤_ 740 +£¤ 740 +_¾ 738 +ö 733 +ú_ 720 +Ø 708 +« 694 +_Ë 690 +ø 688 +_Ä 686 +_É 685 +¡¢_ 674 +¡¢ 674 +_¡¢_ 674 +_¡¢ 674 +ª_ 663 +»_ 656 +_Õ 651 +ê 643 +¹_ 643 +_Ï 632 +_³ 628 +â 626 +ñ 605 +Í_ 593 +® 586 +_à 585 +¯ 584 +û 578 +_Ð 574 +á 563 +ó 562 +_° 549 +½_ 534 +_± 521 +Äê 515 +¹ú 510 +ö_ 507 +Ö_ 503 +Ç_ 493 +Ò» 493 +_¿ 482 +®_ 481 +ý 476 +ÔÚ 474 +ê_ 470 +£° 468 +_£° 465 +£°_ 465 +_£°_ 465 +ÔÚ_ 464 +ò 455 +ø_ 450 +© 449 +_Æ 449 +þ 448 +_À 448 +à 445 +ÁË 445 +ì 441 +·_ 434 +_Ç 432 +Â_ 430 +ü 428 +ÁË_ 427 +_£± 426 +_£±_ 426 +£±_ 426 +£± 426 +ºÍ 425 +÷_ 424 +_ÔÚ 423 +_Ò» 419 +­ 419 +í 417 +Äê_ 417 +_ÔÚ_ 415 +ï 413 +Ã_ 412 +´_ 411 +ç 411 +â_ 410 +é 409 +Ï_ 402 +²_ 400 +§ 398 +_ÁË 397 +_ºÍ 397 +Ó_ 395 +_Ì 393 +¨_ 392 +ß 390 +¯_ 387 +î 386 +Ü 385 +Ø_ 383 +_ÁË_ 380 +ºÍ_ 379 +ò_ 378 +_Å 372 +Ù 368 +_ºÍ_ 368 +û_ 364 +¸_ 359 +«_ 358 +¿_ 356 +¼_ 355 +ë 355 +¡_ 349 +³_ 346 +Ò_ 343 +Ô_ 343 +Å_ 340 +ã 340 +ÈË 338 +ÖÐ 338 +¶_ 336 +ý_ 331 +ù 329 +ñ_ 324 +Ò»_ 309 +¹ú_ 306 +å 304 +¹¤ 300 +ï_ 298 +ó_ 297 +ÓÐ 296 +È_ 294 +ä 293 +_Ñ 290 +¦ 289 +ë_ 281 +_Äê 276 +ì_ 274 +Òµ 274 +ß_ 273 +»á 272 +á_ 270 +ð 270 +æ 270 +©_ 269 +_Ò»_ 269 +Õ_ 268 +õ 268 +_ÖÐ 267 +ÐÐ 267 +ÉÏ 266 +à_ 265 +ü_ 264 +é_ 264 +_ 262 +¥ 258 +í_ 257 +§_ 256 +Æ_ 248 +Òµ_ 246 +²ú 242 +É_ 242 +Û 242 +ã_ 237 +Ãñ 233 +·¢ 230 +²» 229 +µØ 228 +Ϊ 228 +ÊÇ 226 +_ÓÐ 225 +ç_ 225 +Ê_ 224 +´ó 224 +º_ 224 +ÊÇ_ 223 +¼Ò 223 +Î_ 222 +î_ 222 +þ_ 221 +³ö 221 +_Õâ 220 +Õâ 220 +Ù_ 220 +å_ 219 +£¹ 218 +£¹_ 217 +_£¹_ 217 +_£¹ 217 +ÓÐ_ 217 +_ÈË 214 +¸ö 210 +_ÉÏ 210 +è 209 +·Ö 209 +Éú 208 +²¿ 208 +õ_ 208 +_¹ú 207 +À_ 207 +_¡° 205 +¡±_ 205 +¡°_ 205 +¡± 205 +_¡°_ 205 +_¡±_ 205 +_¡± 205 +¡° 205 +£¸ 204 +¦_ 203 +×÷ 202 +¾_ 202 +_Äê_ 201 +£² 201 +_£²_ 200 +_£² 200 +£²_ 200 +¸ö_ 199 +Ñ_ 197 +_£¸ 197 +£¸_ 197 +_£¸_ 197 +_¹¤ 196 +Ý 193 +_²» 191 +£µ 189 +ð_ 188 +_£µ 186 +_£µ_ 186 +Ü_ 186 +£µ_ 186 +£³ 183 +½ø 183 +¶à 182 +Ϊ_ 182 +¼Ò_ 180 +ÊÐ 179 +ÈÕ 179 +³É 178 +_ÊÇ 178 +æ_ 177 +_ÊÇ_ 177 +ÈË_ 177 +ù_ 176 +Õþ 175 +µ½ 174 +_Ϊ 173 +È« 171 +­_ 171 +¾ü 171 +½¨ 171 +££ 169 +_£³_ 169 +_££ 169 +_££_ 169 +£³_ 169 +££_ 169 +_£³ 169 +_·¢ 168 +_¸ö 168 +Û_ 168 +µ½_ 167 +_¶à 166 +×_ 166 +¶à_ 166 +Òª 165 +Óà 164 +ʱ 164 +_´ó 164 +ÖÐ_ 163 +Ý_ 160 +»á_ 160 +ÉÏ_ 159 +ô 158 +_¸ö_ 157 +ÐÐ_ 157 +¶¯ 156 +_ÓÐ_ 156 +_¶à_ 155 +ÒÔ 155 +³¤ 154 +Р154 +_½¨ 154 +_µØ 154 +¼Ó 152 +_ÈÕ 151 +_ÊÐ 151 +À´ 151 +Ê¡ 149 +¿ª 148 +ä_ 148 +_Ê¡ 148 +Àí 147 +_³ö 146 +µØ_ 145 +_È« 143 +ͬ 143 +Íò 142 +_·Ö 141 +Íò_ 140 +Ö÷ 140 +ѧ 140 +Å© 139 +Òª_ 139 +_½ø 137 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/drents.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/drents.lm new file mode 100644 index 0000000..e69de29 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/esperanto.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/esperanto.lm new file mode 100644 index 0000000..09563f8 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/esperanto.lm @@ -0,0 +1,400 @@ +_ 57050 +a 16035 +i 12706 +e 12227 +o 12102 +n 10393 +s 8344 +l 7707 +r 7492 +t 7134 +k 5376 +u 4558 +j 3946 +a_ 3875 +m 3783 +d 3710 +p 3693 +la 2840 +s_ 2769 +e_ 2751 +. 2706 +_l 2635 +_k 2619 +v 2531 +n_ 2504 +o_ 2444 +i_ 2333 +._ 2278 +on 2238 +, 2193 +,_ 2182 +_la 2100 +en 2080 +j_ 2050 +as 2028 +la_ 2012 +ta 1956 +_la_ 1907 +an 1882 +_p 1850 +g 1831 +_e 1791 +_d 1778 +is 1737 +aj 1658 +st 1635 +_s 1575 +c 1526 +de 1517 +oj 1498 +er 1476 +ti 1456 +f 1443 +_a 1442 +b 1427 +ro 1379 +_m 1351 +ra 1341 +nt 1293 +ka 1270 +ri 1258 +al 1249 +as_ 1248 +aj_ 1213 +to 1209 +_de 1203 +_t 1200 +te 1179 +_n 1176 +is_ 1171 +in 1151 +ko 1145 +or 1114 +es 1083 +re 1034 +ia 1029 +li 1022 +de_ 1016 +_de_ 979 +ar 974 +_v 966 +vi 942 +lo 932 +x 928 +io 917 +ne 855 +no 848 +ni 843 +mi 835 +ma 819 +_ka 816 +el 815 +pr 771 +z 744 +un 734 +l_ 732 +po 730 +_f 725 +ø 724 +est 691 +na 687 +ki 679 +kaj 676 +si 665 +u_ 663 +kaj_ 660 +" 654 +tas 651 +le 650 +oj_ 648 +_i 643 +tr 642 +_pr 630 +_es 628 +jn 626 +pe 618 +_kaj 616 +ig 616 +_kaj_ 611 +do 608 +sta 606 +on_ 602 +ek 602 +ci 597 +r_ 595 +ý 594 +_r 593 +il 592 +_est 587 +di 586 +am 586 +_mi 582 +aý 578 +_vi 577 +mo 575 +ant 565 +_ne 562 +en_ 561 +o. 559 +æ 543 +iu 538 +o, 529 +ur 527 +o._ 527 +om 525 +o,_ 524 +at 521 +va 521 +- 519 +_en 518 +: 513 +:_ 512 +_ti 500 +M 496 +h 488 +nd 484 +me 484 +_al 481 +_ko 479 +ve 478 +ie 478 +_ki 473 +it 473 +L 466 +_b 465 +se 462 +em 452 +ol 450 +nta 449 +tu 448 +ik 444 +ov 443 +da 443 +_M 440 +_po 439 +tas_ 438 +ne_ 437 +et 437 +_ma 436 +_en_ 435 +su 429 +pl 426 +_L 425 +pa 420 +_o 417 +vo 408 +an_ 407 +ro_ 406 +sti 406 +nu 399 +kon 396 +stas 391 +m_ 391 +ir 388 +n. 386 +fa 386 +jn_ 382 +ku 382 +os 376 +ke 375 +n, 375 +esta 374 +n,_ 372 +_su 362 +ta_ 362 +stas_ 359 +xi 359 +Mi 358 +_ne_ 356 +al_ 355 +nk 353 +so 353 +n._ 352 +id 349 +_g 348 +estas 347 +ga 346 +_h 345 +per 345 +_Mi 340 +ok 339 +K 339 +mp 337 +_esta 337 +s,_ 335 +s, 335 +_se 333 +anta 332 +ul 326 +ran 325 +_" 323 +ý_ 322 +te_ 320 +ak 320 +aý_ 320 +ed 320 +rt 319 +ojn 318 +gi 318 +_æ 317 +tis 316 +gx 316 +mal 316 +ia_ 315 +ks 310 +_al_ 310 +mi_ 309 +S 309 +lu 309 +ns 308 +kt 305 +io_ 302 +ent 300 +? 300 +_K 300 +ec 300 +el_ 299 +_- 299 +li_ 299 +E 298 +þ 298 +_li 297 +fo 296 +ter 296 +_re 296 +A 295 +nto 294 +vi_ 292 +La 292 +_mal 290 +nte 288 +sp 287 +sa 287 +_mi_ 279 +ut 278 +op 278 +_ke 277 +bo 277 +ajn 276 +un_ 276 +T 274 +to_ 272 +-_ 272 +bl 272 +_an 271 +_La 271 +øi 269 +_S 268 +_pl 267 +_fa 266 +ni_ 266 +La_ 265 +_E 264 +N 263 +tis_ 263 +_tr 263 +' 262 +! 262 +_-_ 262 +pro 261 +iu_ 261 +iø 261 +nc 260 +_si 259 +du 257 +_kon 256 +ru 255 +_vi_ 254 +_j 253 +ce 251 +ke_ 249 +ap 248 +us 247 +be 247 +im 247 +B 246 +_ku 246 +_La_ 246 +tra 245 +ad 245 +uj 245 +ac 245 +ita 243 +pre 242 +_pro 242 +co 241 +rm 241 +_ni 238 +_pe 236 +?_ 234 +on. 234 +toj 234 +"_ 234 +j. 234 +_ke_ 233 +s. 232 +_A 231 +av 230 +ri_ 230 +_el 229 +por 229 +` 224 +ev 224 +las 223 +P 223 +j._ 221 +eni 220 +_T 220 +_B 219 +j,_ 218 +j, 218 +era 217 +_in 216 +on._ 216 +cx 216 +_N 215 +ion 215 +ab 215 +.. 214 +) 213 +fi 213 +or_ 212 +pri 212 +s._ 212 +_por 210 +ez 210 +in_ 210 +am_ 209 +on,_ 209 +ll 209 +æi 209 +on, 209 +_ve 208 +ris 208 +esti 208 +!_ 207 +men 206 +vas 205 +iel 204 +taj 203 +_c 201 +aro 201 +ank 200 +_pri 200 +jo 200 +ja 200 +ont 200 +lt 199 +_P 199 +igi 199 +_pa 197 +oj. 197 +( 196 +au 195 +oro 195 +ng 195 +_( 194 +sto 194 +ast 194 +ag 193 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/frisian.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/frisian.lm new file mode 100644 index 0000000..f9945ad --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/frisian.lm @@ -0,0 +1,400 @@ +_ 46446 +e 15767 +n 9616 +i 7837 +a 7830 +t 7562 +r 7297 +s 6307 +o 4784 +n_ 4595 +d 4564 +e_ 4213 +l 4032 +k 3951 +t_ 3079 +en 2863 +m 2605 +er 2492 +y 2462 +f 2371 +_d 2253 +de 2124 +h 1943 +in 1899 +w 1898 +en_ 1857 +_i 1815 +u 1769 +g 1738 +an 1690 +j 1678 +p 1651 +r_ 1619 +_f 1602 +. 1601 +ar 1561 +te 1545 +b 1488 +s_ 1476 +._ 1435 +_s 1370 +de_ 1235 +_de 1224 +_w 1181 +it 1172 +ie 1140 +, 1078 +_o 1056 +,_ 1056 +oa 1045 +_e 1040 +st 1038 +an_ 1010 +_b 972 +_de_ 965 +ke 949 +_m 947 +_t 933 +ne 920 +er_ 895 +at 863 +sk 856 +c 850 +it_ 848 +_h 838 +ei 832 +k_ 817 +yn 790 +ch 784 +le 772 +is 769 +je 765 +el 761 +me 758 +ea 754 +_k 740 +fa 736 +in_ 735 +' 733 +_it 733 +_it_ 727 +ge 727 +re 725 +al 724 +_fa 684 +yn_ 640 +aa 628 +fan 626 +_y 618 +ar_ 617 +et 616 +ri 615 +_fan 613 +_n 612 +li 611 +_yn 610 +_en 598 +fan_ 594 +oe 589 +_fan_ 584 +_en_ 583 +at_ 581 +_in 570 +oar 565 +_in_ 560 +y_ 555 +F 549 +es 540 +_a 536 +ng 523 +be 514 +sj 512 +nt 510 +l_ 510 +_F 506 +ns 506 +D 499 +te_ 499 +der 497 +_yn_ 497 +ti 493 +ek 490 +ro 476 +rs 474 +rd 473 +se 470 +fo 470 +ys 462 +op 461 +û 461 +we 456 +ry 451 +da 445 +d_ 443 +is_ 442 +_D 440 +ur 433 +i_ 432 +ha 426 +_me 425 +ear 422 +_l 417 +ed 410 +as 409 +om 407 +ei_ 406 +Fr 405 +nd 404 +_fo 394 +_p 393 +oc 390 +rys 389 +ol 386 +_Fr 386 +och 383 +fe 381 +ik 379 +ma 379 +ra 377 +nn 374 +_g 368 +_da 367 +di 363 +ts 362 +ta 361 +a_ 360 +ko 359 +et_ 358 +ysk 356 +Fry 354 +Frys 354 +z 354 +ll 350 +_be 349 +ke_ 348 +I 347 +ing 346 +_' 345 +m_ 343 +h_ 340 +ske 339 +_ha 338 +sje 336 +_Fry 336 +_Frys 336 +wi 335 +_op 334 +p_ 334 +_is 333 +ch_ 333 +tr 330 +ten 328 +ers 327 +wa 325 +ter 322 +ji 322 +rysk 319 +_ne 319 +je_ 312 +foa 311 +ê 309 +jo 307 +_is_ 307 +ste 307 +_te 306 +â 301 +n. 301 +nne 300 +rt 300 +foar 299 +S 299 +mei 299 +_r 298 +_oa 297 +wu 293 +ak 291 +si 290 +wur 290 +ni 290 +pe 288 +Frysk 287 +oan 286 +n._ 285 +_mei 284 +der_ 281 +_foar 281 +_foa 281 +ht 278 +cht 277 +- 275 +ú 275 +_j 274 +ne_ 273 +ken 273 +fer 271 +ûn 270 +am 270 +on 268 +nde 264 +_S 264 +B 262 +ki 261 +id 261 +le_ 261 +dat 260 +v 259 +_I 256 +oar_ 255 +op_ 254 +lle 252 +la 244 +tt 243 +dat_ 242 +_fe 242 +mm 240 +inn 239 +_wi 239 +_dat 237 +g_ 236 +mei_ 236 +al_ 235 +_B 234 +e. 234 +ld 231 +_al 230 +_wur 230 +urd 230 +_wu 230 +_op_ 230 +De 229 +inne 228 +ng_ 227 +_mei_ 227 +'t 226 +ks 226 +'t_ 224 +_dat_ 224 +_ko 223 +_st 220 +ân 219 +rk 219 +sa 219 +e._ 219 +tte 218 +en. 218 +n, 217 +ier 216 +ten_ 216 +_fer 215 +mi 215 +hi 215 +ien 214 +_wa 213 +n,_ 213 +no 213 +_te_ 212 +ig 212 +_De 212 +ske_ 212 +_der 212 +W 211 +H 211 +_oan 210 +ee 209 +dy 208 +ek_ 207 +en._ 207 +ic 207 +mme 206 +yk 204 +pr 204 +net 203 +foar_ 203 +he 203 +wurd 201 +_der_ 199 +jen 199 +_dy 199 +kr 198 +ka 197 +im 196 +_H 196 +il 196 +ze 196 +_ma 195 +by 194 +oer 194 +kt 193 +us 193 +M 193 +sk_ 192 +wo 192 +_hi 191 +or 190 +ing_ 190 +_W 190 +ich 189 +De_ 187 +rr 186 +int 185 +_ú 184 +: 184 +ij 184 +_ek 183 +eg 182 +:_ 180 +gen 180 +as_ 180 +_se 179 +e, 178 +_net 177 +e,_ 177 +ins 177 +N 177 +ls 176 +st_ 176 +_wurd 176 +ie_ 175 +E 175 +nne_ 175 +_De_ 175 +sy 175 +wer 174 +gr 174 +f_ 173 +nk 172 +och_ 172 +net_ 169 +ad 169 +_we 169 +rde 168 +sl 168 +bi 168 +of 168 +so 168 +_no 167 +_ta 167 +re_ 167 +to 167 +den 167 +J 167 +t. 166 +It 165 +út 165 +inne_ 165 +ysk_ 165 +lik 164 +sp 163 +_ek_ 162 +ou 162 +tsj 162 +It_ 161 +_sa 160 +A 160 +wol 160 +lâ 159 +_wo 159 +ge_ 159 +lân 159 +ige 158 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/greek-iso8859-7.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/greek-iso8859-7.lm new file mode 100644 index 0000000..c4acc8f --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/greek-iso8859-7.lm @@ -0,0 +1,400 @@ +_ 89284 +á 19666 +ô 16086 +ï 15826 +å 14848 +é 12766 +í 12189 +ð 8776 +ó 8653 +ñ 8399 +ê 7761 +ì 7529 +õ 6850 +Ü 6284 +_ô 5918 +ë 5802 +ò 5371 +á_ 5272 +ç 5236 +Ý 4739 +ß 4609 +ü 4489 +ôï 4461 +ò_ 4111 +ïõ 4075 +é_ 4033 +å_ 4019 +. 3916 +_ê 3897 +ï_ 3836 +._ 3810 +í_ 3661 +_ð 3414 +_ó 3333 +" 3247 +_ì 3242 +_ôï 3118 +, 3106 +,_ 3068 +ã 3058 +_á 2912 +ù 2689 +íá 2593 +ä 2455 +ôá 2420 +÷ 2411 +êá 2406 +óô 2406 +_å 2353 +- 2335 +-_ 2192 +ý 2171 +áí 2162 +ôç 2151 +Þ 2141 +õ_ 2133 +áé 2100 +è 2053 +ö 1989 +ïõ_ 1974 +åé 1889 +_êá 1882 +åß 1864 +ôï_ 1802 +ðï 1771 +áé_ 1727 +óå 1709 +_í 1647 +_" 1619 +ç_ 1609 +éá 1602 +íá_ 1518 +ôé 1501 +ïí 1501 +ôïõ 1495 +ìå 1460 +_ôïõ 1407 +_Ý 1405 +_óô 1396 +þ 1364 +ðå 1359 +ôå 1300 +ìá 1298 +â 1274 +ñé 1252 +ü_ 1241 +_ä 1231 +î 1223 +íô 1220 +_ôï_ 1196 +áð 1187 +ñï 1184 +_ã 1183 +_ôç 1177 +æ 1158 +_åß 1150 +Ü_ 1150 +_íá 1124 +Ýí 1115 +êáé 1110 +_êáé 1093 +áí_ 1082 +ñá 1078 +êáé_ 1061 +_íá_ 1060 +_êáé_ 1053 +ìð 1049 +íï 1048 +áô 1036 +éï 1024 +éá_ 1018 +åñ 1003 +ïý 993 +_áð 984 +óå_ 974 +éê 973 +_ï 967 +åí 947 +ïò 936 +åé_ 935 +ðü 901 +ëï 892 +_ìå 890 +íå 884 +ôïõ_ 871 +ïí_ 869 +áò 865 +_ôïõ_ 854 +áó 841 +ìå_ 840 +óá 834 +êï 833 +áñ 832 +ðñ 824 +ßí 820 +êÜ 808 +_ðï 804 +ðé 796 +Ê 796 +ìÝ 783 +ìï 777 +Ýñ 772 +áë 766 +çí 762 +Ì 759 +éó 745 +êå 742 +ôá_ 740 +óôï 738 +ù_ 730 +çí_ 728 +Ï 717 +Ô 714 +_ö 711 +åô 705 +äå 704 +ðá 697 +áò_ 688 +ôÜ 684 +ïò_ 683 +_ü 680 +_Ê 675 +ïé 671 +_÷ 670 +ôçí 663 +ôçí_ 658 +_óôï 647 +Þ_ 645 +ðü_ 638 +_è 633 +_ï_ 631 +", 630 +_ðñ 626 +_Ì 624 +ßð 624 +Üí 623 +",_ 623 +áðü 620 +ðïõ 619 +üô 618 +ëá 617 +ôïí 617 +_áðü 616 +ìé 612 +Ï_ 611 +ñå 607 +õô 604 +ëå 595 +_ë 594 +ñü 590 +_ìå_ 586 +éÜ 580 +ôïí_ 577 +ãé 577 +_Ï 575 +áðü_ 572 +Üñ 570 +ðÜ 570 +_áðü_ 569 +ñÜ 562 +ôáí 554 +Ýíá 553 +õí 552 +ðïõ_ 551 +äé 547 +ôñ 547 +ôü 544 +_â 540 +÷å 536 +åí_ 534 +çó 528 +_Ï_ 525 +çò 520 +". 519 +_ðïõ 516 +_Ô 515 +"._ 513 +ôç_ 512 +ò. 510 +åßð 508 +ôáí_ 504 +_åßð 503 +ò._ 501 +_ôá 500 +îå 497 +óôï_ 496 +ëë 493 +áê 492 +Á 491 +_ðïõ_ 490 +Üë 489 +ßðå 489 +åßðå 485 +_åßðå 483 +_ôçí 483 +ôé_ 482 +_ôçí_ 481 +Üô 480 +ëé 480 +_äå 479 +Üì 477 +_óôï_ 475 +óï 473 +_Ü 468 +"_ 463 +ìÝí 463 +éí 461 +éò 452 +_áí 452 +êü 451 +áõ 451 +_ôïí 450 +_ãé 449 +èá 447 +åò 446 +óç 446 +_ìé 445 +_ôïí_ 443 +å. 441 +å._ 441 +ïõò 439 +ëÜ 439 +õò 439 +ïë 438 +ðéï 437 +ïñ 432 +_ðá 428 +_êÜ 427 +ôå_ 427 +áì 423 +; 423 +_ìï 422 +óê 421 +ôçò 421 +_î 418 +óôç 415 +ÊÜ 411 +íç 408 +ãéá 405 +á. 403 +êñ 402 +êé 402 +ò, 402 +ò,_ 401 +á._ 398 +çê 397 +_ÊÜ 397 +åë 396 +_Ýí 395 +_Þ 393 +_ìá 392 +ßá 391 +ùò 391 +ëç 390 +ßíá 389 +ðß 389 +ìïõ 388 +ìÜ 388 +_áõ 387 +çò_ 386 +óõ 384 +íáé 384 +Ð 383 +áõô 382 +ß_ 376 +ìðé 375 +ßó 372 +_ôçò 370 +_ôá_ 367 +_ãéá 365 +_Ýíá 362 +_ìð 361 +èå 361 +éïí 359 +éò_ 358 +ôÞ 358 +_èá 354 +_áõô 354 +Üìð 352 +ê. 352 +ê._ 351 +åßí 351 +ïì 350 +ßíáé 348 +íôá 348 +íáé_ 348 +ùò_ 347 +÷á 346 +Å 346 +õ. 346 +ãéá_ 346 +õ._ 345 +äåí 345 +Ýíá_ 345 +á, 344 +á,_ 344 +äåí_ 344 +ýñ 343 +üí 343 +á- 342 +ýó 341 +_ê. 340 +óôå 339 +ÊÜì 339 +_ê._ 339 +ôÝ 339 +á-_ 338 +åõ 338 +éë 338 +ñß 338 +ÊÜìð 338 +_ìïõ 338 +_ÊÜì 338 +_ÊÜìð 337 +õì 336 +óåé 336 +ðéïí 336 +ìðéïí 336 +ìðéï 336 +_êï 334 +ÊÜìðé 334 +_ç 334 +Üìðé 334 +èá_ 333 +íé 332 +ôçò_ 331 +ø 331 +üì 330 +çóå 330 +_óá 329 +ìá_ 328 +üò 328 +Ó 326 +_äåí 325 +_äåí_ 325 +óì 324 +åò_ 324 +ðåñ 324 +ß÷ 323 +ßíáé_ 323 +ôéê 322 +_ñ 321 +Üìðéï 321 +õò_ 321 +ïõò_ 321 +_ðå 321 +óù 320 +_ãéá_ 320 +ðñï 320 +ãå 318 +;" 316 +;"_ 316 +Ä 315 +ôõ 314 +ñá_ 313 +_óõ 312 +ñù 312 +_èá_ 310 +üó 309 +ïõ. 309 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/greek-windows1253.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/greek-windows1253.lm new file mode 100644 index 0000000..c4acc8f --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/greek-windows1253.lm @@ -0,0 +1,400 @@ +_ 89284 +á 19666 +ô 16086 +ï 15826 +å 14848 +é 12766 +í 12189 +ð 8776 +ó 8653 +ñ 8399 +ê 7761 +ì 7529 +õ 6850 +Ü 6284 +_ô 5918 +ë 5802 +ò 5371 +á_ 5272 +ç 5236 +Ý 4739 +ß 4609 +ü 4489 +ôï 4461 +ò_ 4111 +ïõ 4075 +é_ 4033 +å_ 4019 +. 3916 +_ê 3897 +ï_ 3836 +._ 3810 +í_ 3661 +_ð 3414 +_ó 3333 +" 3247 +_ì 3242 +_ôï 3118 +, 3106 +,_ 3068 +ã 3058 +_á 2912 +ù 2689 +íá 2593 +ä 2455 +ôá 2420 +÷ 2411 +êá 2406 +óô 2406 +_å 2353 +- 2335 +-_ 2192 +ý 2171 +áí 2162 +ôç 2151 +Þ 2141 +õ_ 2133 +áé 2100 +è 2053 +ö 1989 +ïõ_ 1974 +åé 1889 +_êá 1882 +åß 1864 +ôï_ 1802 +ðï 1771 +áé_ 1727 +óå 1709 +_í 1647 +_" 1619 +ç_ 1609 +éá 1602 +íá_ 1518 +ôé 1501 +ïí 1501 +ôïõ 1495 +ìå 1460 +_ôïõ 1407 +_Ý 1405 +_óô 1396 +þ 1364 +ðå 1359 +ôå 1300 +ìá 1298 +â 1274 +ñé 1252 +ü_ 1241 +_ä 1231 +î 1223 +íô 1220 +_ôï_ 1196 +áð 1187 +ñï 1184 +_ã 1183 +_ôç 1177 +æ 1158 +_åß 1150 +Ü_ 1150 +_íá 1124 +Ýí 1115 +êáé 1110 +_êáé 1093 +áí_ 1082 +ñá 1078 +êáé_ 1061 +_íá_ 1060 +_êáé_ 1053 +ìð 1049 +íï 1048 +áô 1036 +éï 1024 +éá_ 1018 +åñ 1003 +ïý 993 +_áð 984 +óå_ 974 +éê 973 +_ï 967 +åí 947 +ïò 936 +åé_ 935 +ðü 901 +ëï 892 +_ìå 890 +íå 884 +ôïõ_ 871 +ïí_ 869 +áò 865 +_ôïõ_ 854 +áó 841 +ìå_ 840 +óá 834 +êï 833 +áñ 832 +ðñ 824 +ßí 820 +êÜ 808 +_ðï 804 +ðé 796 +Ê 796 +ìÝ 783 +ìï 777 +Ýñ 772 +áë 766 +çí 762 +Ì 759 +éó 745 +êå 742 +ôá_ 740 +óôï 738 +ù_ 730 +çí_ 728 +Ï 717 +Ô 714 +_ö 711 +åô 705 +äå 704 +ðá 697 +áò_ 688 +ôÜ 684 +ïò_ 683 +_ü 680 +_Ê 675 +ïé 671 +_÷ 670 +ôçí 663 +ôçí_ 658 +_óôï 647 +Þ_ 645 +ðü_ 638 +_è 633 +_ï_ 631 +", 630 +_ðñ 626 +_Ì 624 +ßð 624 +Üí 623 +",_ 623 +áðü 620 +ðïõ 619 +üô 618 +ëá 617 +ôïí 617 +_áðü 616 +ìé 612 +Ï_ 611 +ñå 607 +õô 604 +ëå 595 +_ë 594 +ñü 590 +_ìå_ 586 +éÜ 580 +ôïí_ 577 +ãé 577 +_Ï 575 +áðü_ 572 +Üñ 570 +ðÜ 570 +_áðü_ 569 +ñÜ 562 +ôáí 554 +Ýíá 553 +õí 552 +ðïõ_ 551 +äé 547 +ôñ 547 +ôü 544 +_â 540 +÷å 536 +åí_ 534 +çó 528 +_Ï_ 525 +çò 520 +". 519 +_ðïõ 516 +_Ô 515 +"._ 513 +ôç_ 512 +ò. 510 +åßð 508 +ôáí_ 504 +_åßð 503 +ò._ 501 +_ôá 500 +îå 497 +óôï_ 496 +ëë 493 +áê 492 +Á 491 +_ðïõ_ 490 +Üë 489 +ßðå 489 +åßðå 485 +_åßðå 483 +_ôçí 483 +ôé_ 482 +_ôçí_ 481 +Üô 480 +ëé 480 +_äå 479 +Üì 477 +_óôï_ 475 +óï 473 +_Ü 468 +"_ 463 +ìÝí 463 +éí 461 +éò 452 +_áí 452 +êü 451 +áõ 451 +_ôïí 450 +_ãé 449 +èá 447 +åò 446 +óç 446 +_ìé 445 +_ôïí_ 443 +å. 441 +å._ 441 +ïõò 439 +ëÜ 439 +õò 439 +ïë 438 +ðéï 437 +ïñ 432 +_ðá 428 +_êÜ 427 +ôå_ 427 +áì 423 +; 423 +_ìï 422 +óê 421 +ôçò 421 +_î 418 +óôç 415 +ÊÜ 411 +íç 408 +ãéá 405 +á. 403 +êñ 402 +êé 402 +ò, 402 +ò,_ 401 +á._ 398 +çê 397 +_ÊÜ 397 +åë 396 +_Ýí 395 +_Þ 393 +_ìá 392 +ßá 391 +ùò 391 +ëç 390 +ßíá 389 +ðß 389 +ìïõ 388 +ìÜ 388 +_áõ 387 +çò_ 386 +óõ 384 +íáé 384 +Ð 383 +áõô 382 +ß_ 376 +ìðé 375 +ßó 372 +_ôçò 370 +_ôá_ 367 +_ãéá 365 +_Ýíá 362 +_ìð 361 +èå 361 +éïí 359 +éò_ 358 +ôÞ 358 +_èá 354 +_áõô 354 +Üìð 352 +ê. 352 +ê._ 351 +åßí 351 +ïì 350 +ßíáé 348 +íôá 348 +íáé_ 348 +ùò_ 347 +÷á 346 +Å 346 +õ. 346 +ãéá_ 346 +õ._ 345 +äåí 345 +Ýíá_ 345 +á, 344 +á,_ 344 +äåí_ 344 +ýñ 343 +üí 343 +á- 342 +ýó 341 +_ê. 340 +óôå 339 +ÊÜì 339 +_ê._ 339 +ôÝ 339 +á-_ 338 +åõ 338 +éë 338 +ñß 338 +ÊÜìð 338 +_ìïõ 338 +_ÊÜì 338 +_ÊÜìð 337 +õì 336 +óåé 336 +ðéïí 336 +ìðéïí 336 +ìðéï 336 +_êï 334 +ÊÜìðé 334 +_ç 334 +Üìðé 334 +èá_ 333 +íé 332 +ôçò_ 331 +ø 331 +üì 330 +çóå 330 +_óá 329 +ìá_ 328 +üò 328 +Ó 326 +_äåí 325 +_äåí_ 325 +óì 324 +åò_ 324 +ðåñ 324 +ß÷ 323 +ßíáé_ 323 +ôéê 322 +_ñ 321 +Üìðéï 321 +õò_ 321 +ïõò_ 321 +_ðå 321 +óù 320 +_ãéá_ 320 +ðñï 320 +ãå 318 +;" 316 +;"_ 316 +Ä 315 +ôõ 314 +ñá_ 313 +_óõ 312 +ñù 312 +_èá_ 310 +üó 309 +ïõ. 309 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/hebrew-iso8859_8.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/hebrew-iso8859_8.lm new file mode 100644 index 0000000..59ec8c3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/hebrew-iso8859_8.lm @@ -0,0 +1,400 @@ +_ 81560 +é 23072 +å 19215 +ä 15606 +ì 12612 +ø 11293 +ú 11070 +î 10090 +á 9648 +à 9601 +ù 9081 +ä_ 7811 +ð 6685 +ò 6326 +_ú 5878 +í 5542 +ã 5019 +ç 4669 +_í 4570 +á_ 4267 +ë 3984 +_ä 3812 +÷ 3769 +ô 3699 +ì_ 3693 +íé 3535 +î_ 3489 +ñ 3374 +à_ 3362 +úå 3130 +, 3067 +_ì 3037 +_, 3035 +_é 2936 +ù_ 2886 +_íé 2840 +â 2768 +è 2626 +ï 2424 +_ø 2395 +_úå 2291 +. 2256 +ö 2215 +_. 2205 +éð 2144 +ò_ 2003 +_ï 1959 +_å 1913 +" 1815 +éá 1797 +ìù 1742 +éì 1687 +éø 1665 +é_ 1647 +åé 1620 +å_ 1578 +åø 1525 +úà 1475 +ë_ 1469 +øå 1411 +æ 1383 +åð 1353 +îä 1351 +úé 1343 +éé 1343 +ìå 1315 +éã 1285 +øé 1236 +îä_ 1211 +äì 1206 +åî 1192 +ðé 1163 +øù 1155 +éà 1146 +àø 1138 +_úà 1137 +ùé 1134 +éù 1087 +ð_ 1080 +ìà 1074 +åç 1067 +_à 1062 +ùî 1059 +éî 1052 +äé 1047 +- 1024 +ìù_ 1008 +åä 973 +øá 967 +åà 954 +úà_ 951 +åì 948 +_ã 941 +éä 896 +ðå 888 +åò 883 +éë 873 +åù 871 +ìò 867 +àì 850 +òå 843 +_- 830 +ç_ 830 +ãå 824 +ïå 820 +ø_ 806 +åá 805 +_ìù 799 +éè 784 +àä 773 +_ìù_ 748 +éò 746 +ãé 743 +_ù 726 +_úà_ 723 +ê 720 +_úé 719 +-_ 716 +_-_ 713 +áé 709 +áå 706 +åú 699 +àä_ 690 +øî 686 +ùä 683 +åã 678 +éç 675 +ô_ 672 +äð 669 +_á 668 +_ò 659 +_ê 655 +éñ 652 +ïé 649 +_ìò 640 +éå 635 +àî 635 +éá_ 632 +ú_ 631 +îà 628 +ùå 627 +_ïå 624 +ìé 624 +ìò_ 621 +úä 619 +éú 600 +äì_ 599 +åë 599 +éô 596 +ôä 595 +å÷ 586 +äù 578 +òé 575 +_ïé 569 +îå 564 +_ìò_ 561 +÷é 560 +éâ 557 +éä_ 557 +øùé 554 +íå 548 +àì_ 548 +úåé 548 +ìàø 546 +øà 542 +äø 540 +"_ 540 +îá 539 +ùä_ 538 +åô 538 +àøù 535 +øò 534 +çä 533 +åâ 532 +àøùé 530 +ìàøùé 530 +ìàøù 530 +àå 527 +îé 525 +_éë 518 +äî 518 +ôä_ 511 +éë_ 510 +_éð 509 +ìë 506 +úî 502 +îá_ 500 +ñå 498 +çà 497 +é÷ 497 +åå 494 +_÷ 485 +â_ 481 +íéì 477 +_äé 477 +ãî 472 +áä 470 +,ä 470 +_,ä 470 +÷_ 469 +òá 468 +_íå 467 +äá 467 +çä_ 466 +_éë_ 463 +àá 462 +øç 462 +_àì 461 +õ 455 +îì 454 +éðé 454 +ùà 453 +øä 453 +éö 452 +íéø 451 +_äð 447 +èé 443 +ã_ 441 +îò 440 +íéé 439 +åä_ 439 +' 435 +àî_ 430 +.í 429 +úð 429 +_.í 428 +ø÷ 427 +úø 423 +åñ 417 +ðù 417 +_äì 414 +ñì 413 +ðú 408 +ñ_ 405 +ñä 400 +ìô 400 +áù 399 +,í 399 +_,í 399 +îî 397 +ùé_ 396 +ðá 396 +òä 394 +úä_ 393 +úåð 393 +íéð 389 +_øå 385 +øîà 384 +éà_ 384 +ìá 384 +úá 381 +áø 378 +áä_ 377 +èñ 374 +_õ 374 +òî 374 +çé 373 +øô 373 +äå 371 +çå 370 +áì 370 +_ìà 370 +÷å 367 +_äø 366 +_íéø 364 +çî 363 +æ_ 362 +_ç 360 +ðë 360 +_ìå 360 +ëå 359 +,ú 358 +_,ú 357 +îú 356 +éðå 353 +åøé 353 +åà_ 349 +øã 348 +úåø 348 +àé 345 +ó 345 +ìùî 344 +ëé 340 +_íéì 340 +åö 338 +úì 338 +_íéé 336 +øçà 335 +_úåé 335 +îà_ 332 +ìç 331 +_úø 329 +_úåð 325 +âé 325 +òä_ 325 +: 324 +ôì 324 +àá_ 324 +ùø 322 +øè 321 +úù 320 +ö_ 320 +îò_ 319 +åé_ 319 +_: 319 +öî 316 +ùîî 315 +_ñ 315 +úéð 315 +ñî 315 +äã 313 +øä_ 312 +åè 312 +_ó 310 +ùàø 309 +øùé_ 305 +àøùé_ 305 +.íé 305 +_.íé 304 +äú 303 +éèñ 303 +_' 303 +âä 302 +ùî_ 302 +_íéð 301 +ìä 298 +øâ 294 +çè 293 +ãò 293 +íéã 292 +àù 292 +ìùîî 292 +íò 292 +éãé 290 +ùì 289 +ôå 289 +ãá 289 +öå 287 +_íò 286 +,íé 285 +_,íé 285 +ðî 284 +ñé 282 +ùá 282 +_øù 281 +ãø 281 +_úåø 281 +÷ä 280 +úåù 278 +äù_ 276 +îì_ 276 +_àì_ 275 +åäé 274 +_ìàø 274 +ôé 274 +òá_ 271 +ìà_ 271 +áà 270 +çà_ 269 +çì 268 +òô 267 +áò 267 +.ä 266 +_øé 266 +_ìàøù 266 +åðé 266 +_.ä 265 +éèñì 265 +èñì 265 +éìà 265 +úò 264 +ðä 263 +÷ì 262 +ðéè 260 +_.ú 260 +.ú 260 +ôì_ 260 +äå_ 259 +ñìô 258 +èñìô 258 +éèñìô 258 +ðéèñì 257 +ðéèñ 257 +åî_ 256 +ñä_ 256 +îù 255 +éøå 255 +ðù_ 254 +åîú 254 +ää 252 +á÷ 251 +éù_ 251 +_åð 251 +éøá 251 +_øá 249 +_éã 249 +_íéã 249 +ëä 248 +âð 247 +_ãå 247 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/hindi.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/hindi.lm new file mode 100644 index 0000000..189210b --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/hindi.lm @@ -0,0 +1,400 @@ +_ 75620 +æ 19109 +U 16333 +ð 11131 +¤ 11107 +· 10241 +·¤ 7855 +Ú 6993 +ÚU 6598 +ç 6322 +è 6151 +Ù 5887 +_· 5800 +ã 5370 +â 5168 +U_ 5118 +æ_ 4935 +Ì 4508 +× 4467 +Ø 4292 +ð_ 3962 +_·¤ 3937 +è_ 3904 + 3718 +¤_ 3609 +Ü 3563 +ãU 3514 +_ç 3394 +´ 3363 +ß 2962 +¥ 2907 +ÚU_ 2851 +_¥ 2668 +_ã 2632 +_â 2575 +ô 2527 +Î 2513 +´_ 2512 +Á 2451 +Uæ 2336 +Õ 2314 +_ 2280 +_× 2260 +ñ 2187 +¢ 2082 +» 2078 +¤æ 1988 +ð´ 1913 +·¤æ 1886 +·ð 1881 +ð¤ 1877 +·ð¤ 1860 +Ð 1842 +Ð_ 1830 +·¤_ 1746 +é 1714 +æð 1703 +ð¤_ 1695 +·ð¤_ 1694 +æÚ 1631 +ü 1610 +_·ð 1579 +_·ð¤ 1567 +ð´_ 1556 +æÚU 1536 +Øæ 1528 +Ùð 1525 +Uè 1515 +_·ð¤_ 1488 +Ù_ 1411 +Ùð_ 1407 +à 1390 +_ãñ 1357 +ãñ 1357 +Å 1337 +Ì_ 1319 +_Õ 1315 +×ð 1300 +ç· 1279 +Ö 1270 +_Á 1258 +_·¤æ 1209 +ç·¤ 1203 +¤è 1195 +_Ù 1187 +° 1181 +§ 1166 +×ð´ 1163 +àæ 1162 +ý 1157 +¿ 1155 +_×ð 1150 +×ð´_ 1140 +·¤è 1127 +¤è_ 1092 +_×ð´ 1086 +_×ð´_ 1077 +ñU 1075 +_ãU 1071 +·¤è_ 1065 +ãñU 1062 +_ãñU 1062 +æÙ 1053 +¥æ 1052 +Ìæ 1038 +¤Ú 1035 +_ç· 1009 +¤ÚU 972 +âð 970 +_ç·¤ 967 +_·¤è 959 +ÚUæ 936 +ãUæ 930 +_·¤è_ 929 +·¤Ú 928 +Í 926 +_¥æ 904 +ÅU 904 +Ç 904 +© 890 +ê 887 +©U 885 +·¤ÚU 866 +_© 865 +_©U 862 +_Ö 854 +âð_ 850 +_Ú 847 +_Ì 837 +S 834 +UÐ 831 +_Î 830 +UÐ_ 823 +_ß 798 +Ùæ 788 +â_ 783 +_ÚU 773 +Uè_ 770 +ô´ 753 +æØ 752 +Ï 749 +Øæ_ 732 +×æ 732 +ô_ 704 +_§ 704 +Áæ 704 +_âð 697 +Âý 695 +ãUè 693 +¤æ_ 690 +ü_ 688 +æÚU_ 685 +, 684 +_» 682 +·¤æ_ 679 +,_ 674 +_·¤Ú 670 +¹ 665 +ðU 664 +ßæ 648 +_Âý 647 +UÌ 644 +Ü_ 643 +_Ü 641 +ç·¤_ 639 +Ø_ 639 +Üæ 633 +_âð_ 633 +æç 623 +Uô 621 +ô´_ 615 +_·¤ÚU 611 +Uæ_ 599 +ãU_ 595 +Üð 594 +UÙ 589 +ñUÐ 580 +_ãñUÐ 580 +ãñUÐ 580 +_° 576 +_Áæ 573 +ñUÐ_ 572 +ãñUÐ_ 572 +æÜ 569 +_Ø 569 +_Ùð 569 +ÂÚ 561 +_ç·¤_ 557 +‡ 556 +¤ô 552 +ææ 550 +ÂÚU 549 +çß 544 +Õæ 538 +_·¤æ_ 535 +×_ 532 +çÜ 525 +âæ 523 +·¤ô 519 +æð_ 502 +æ¢ 501 +¸ 498 +_Ùð_ 495 +‹ 494 +_ÂÚ 493 +Âæ 493 +Ìæ_ 490 +_ÂÚU 485 +çÙ 484 +õ 481 +È 478 +‡æ 469 +. 459 +ÂÚU_ 458 +Öæ 449 +Øð 449 +_çß 445 +§â 444 +¤ÚU_ 443 +Öè 442 +_§â 440 +_ÂÚU_ 439 +æð´ 437 +Ùæ_ 435 +€ 434 +_¿ 433 +ÚUè 431 +⢠431 +_·¤ô 430 +Îð 427 +æÌ 425 +Î_ 420 +Öè_ 419 +¸U 415 +˜ 412 +˜æ 412 +§ü 410 +´U 405 +ÇU 399 +»æ 399 +·¤ÚU_ 394 +Uã 394 +æÙ_ 393 +çÌ 393 +¤ô_ 392 +·¤ô_ 392 +çÎ 389 +ÚUÌ 385 +æÁ 385 +Ǹ 383 +æð´_ 382 +Ìè 381 +Íæ 379 +çÚ 375 +°_ 374 +ãUô 374 +ÚUã 374 +æÐ 373 +æÐ_ 372 +_·¤ô_ 371 +_Õæ 369 +æè 364 +çÚU 364 +ðU_ 362 +¤æð 358 +Ȥ 357 +Uæð 354 +è´ 353 +â· 352 +ß_ 350 +U· 349 +¤æÚ 346 +Ìð 346 +·¤æð 346 +æü 345 +õÚ 344 +õÚU 342 +·¤æÚ 342 +_×æ 341 +_Öè 341 +_çÜ 340 +ñU_ 337 +_ãñU_ 337 +ÿ 337 +ãñU_ 337 +Ùè 336 +ãUè_ 334 +¿æ 334 +ñ´ 334 +_Öè_ 332 +æ× 327 +¤æÚU 327 +ÿæ 326 +_Í 325 +U·¤ 323 +·¤æÚU 323 +Uè´ 322 +ãUè´ 321 +_âæ 320 +ǸU 319 +_¥õ 319 +¥õ 319 +õÚU_ 319 +_ÚUã 318 +Úð 317 +è´_ 316 +_⢠316 +æ· 313 +Øô 310 +_ãUæ 309 +Øã 309 +À 308 +ØãU 308 +_Øã 308 +_ØãU 307 +_·¤æð 304 +_¥õÚ 304 +¥õÚ 304 +_¥õÚU 304 +_Öæ 304 +¥õÚU 304 +¥õÚU_ 303 +_çÙ 303 +ãUè´_ 300 +Uè´_ 300 +_S 300 +Îæ 300 +UÜ 298 +ÚUè_ 296 +æÎ 296 +æß 294 +ÅU_ 294 +Øð_ 293 +Ùã 292 +âè 291 +_Ùã 290 +æè_ 290 +ðà 290 +Üð_ 289 +UãU 288 +ÙãU 288 +Uâ 288 +_ÙãU 286 +_à 286 +_ÙãUè 285 +_Âæ 285 +ÙãUè 285 +æ·¤ 284 +_àæ 284 +ÙãUè´ 283 +UÌ_ 282 +ãñ´ 280 +_ãñ´ 280 +ñ´U 280 +â× 279 +_çÎ 278 +_ãñ´U 278 +ãñ´U 278 +»_ 277 +_Îð 275 +ðàæ 274 +àæ_ 273 +æñ 272 +·¤ã 272 +¤ã 272 +Ìð_ 272 +_ãUô 272 +‡æ_ 272 +- 271 +¤ãU 271 +·¤ãU 271 +¢_ 271 +_·¤ã 270 +ãUæ_ 270 +_·¤ãU 269 +ÚUãU 268 +ãé 267 +æâ 265 +°· 263 +¤Ø 263 +¤æð_ 262 +·¤æð_ 262 +°·¤ 262 +ÚðU 258 +_°· 258 +Ùè_ 258 +_°·¤ 257 +ÀU 256 +v 253 +ÂÙ 252 +_ÚUæ 252 +Üè 249 +ç× 247 +çâ 246 +_Å 246 +ÚUÙ 246 +×é 245 +._ 245 +UÚ 244 +éU 243 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/indonesian.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/indonesian.lm new file mode 100644 index 0000000..3fa5a09 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/indonesian.lm @@ -0,0 +1,400 @@ +_ 19406 +a 10666 +n 5455 +e 4535 +i 4387 +r 2936 +t 2902 +an 2853 +u 2841 +k 2761 +s 2311 +m 2178 +d 2134 +g 2105 +l 1780 +a_ 1506 +n_ 1476 +ng 1449 +p 1397 +b 1275 +an_ 1270 +o 1246 +h 1130 +i_ 1108 +er 1038 +ka 1032 +_d 1006 +y 997 +, 951 +en 941 +ar 914 +,_ 900 +_m 880 +ya 842 +ta 838 +ang 797 +di 787 +da 773 +. 754 +la 742 +._ 738 +me 732 +ak 728 +_s 718 +at 690 +ra 688 +ga 683 +_k 671 +_me 650 +in 628 +ah 601 +_t 583 +_p 570 +g_ 551 +_b 551 +_di 548 +ng_ 544 +ma 536 +se 526 +tu 511 +na 506 +al 500 +ri 490 +as 483 +k_ 482 +j 480 +si 470 +ny 467 +h_ 457 +sa 452 +ang_ 439 +it 424 +kan 423 +ti 418 +_se 417 +pe 412 +S 409 +ba 407 +ke 407 +em 405 +men 405 +be 403 +un 401 +te 401 +am 396 +pa 395 +nya 390 +_men 374 +el 374 +t_ 371 +_a 360 +_i 356 +u_ 355 +kan_ 345 +_ke 339 +is 335 +ah_ 324 +_S 324 +eng 321 +nga 320 +ia 318 +_pe 316 +ha 313 +ap 311 +r_ 308 +w 305 +li 301 +_da 300 +s_ 299 +P 296 +nd 290 +_be 287 +ik 283 +ja 281 +yan 281 +ad 275 +ek 273 +uk 272 +di_ 270 +bu 269 +ya_ 268 +yang 268 +ak_ 266 +ber 265 +_y 265 +_ya 264 +_P 263 +ru 260 +K 259 +yang_ 256 +_yang 256 +_yan 256 +nt 255 +de 253 +_te 250 +wa 249 +et 247 +at_ 246 +ara 245 +gan 243 +A 237 +ari 235 +ala 230 +itu 229 +c 225 +ol 225 +ni 225 +us 225 +dan 224 +_K 224 +M 224 +B 223 +ata 222 +ai 221 +ur 219 +nya_ 217 +ua 215 +_ka 214 +_ber 210 +eb 209 +ran 206 +D 206 +ela 206 +_di_ 205 +_l 204 +ngan 204 +ter 203 +re 201 +- 199 +aka 198 +l_ 194 +_A 191 +era 191 +a, 191 +e_ 190 +ir 187 +I 186 +tan 185 +_B 184 +ut 184 +ku 183 +a,_ 183 +il 182 +J 181 +um 180 +_it 180 +_itu 180 +_ta 179 +su 179 +dan_ 177 +es 177 +on 177 +or 177 +_dan 176 +lu 174 +_M 172 +tu_ 172 +_dan_ 172 +enga 171 +mb 169 +R 169 +si_ 168 +per 168 +gan_ 168 +ngan_ 165 +" 162 +_ter 162 +a. 161 +man 161 +gk 160 +a._ 160 +asi 160 +ngk 160 +ep 160 +ag 159 +ul 158 +da_ 157 +m_ 155 +du 155 +ada 153 +ki 153 +rt 150 +mp 150 +T 150 +ama 148 +ing 148 +na_ 147 +_J 147 +_D 145 +ung 145 +ana 145 +n, 144 +ju 144 +ud 144 +rin 143 +gi 143 +aw 141 +lah 138 +lan 138 +_sa 136 +ri_ 136 +meng 136 +_meng 135 +_ma 134 +n,_ 134 +awa 134 +st 134 +eka 133 +mi 133 +mu 132 +_T 132 +po 131 +ge 131 +ar_ 130 +id 129 +ko 129 +le 128 +_h 128 +ena 127 +_j 126 +emb 126 +ina 125 +_r 124 +itu_ 124 +ay 123 +ngg 123 +gg 123 +rang 123 +pi 120 +nan 120 +_ba 119 +_la 119 +apa 119 +_I 118 +p_ 118 +bi 117 +ai_ 117 +ta_ 116 +san 116 +Ke 116 +ro 115 +eri 114 +kar 113 +lah_ 113 +_itu_ 112 +aya 111 +i, 110 +an, 110 +ra_ 110 +_per 110 +im 110 +ika 109 +isi 109 +mem 109 +tah 108 +_Ke 108 +ian 108 +_mem 108 +akan 108 +Se 108 +to 107 +ab 107 +ngka 106 +rs 106 +gka 106 +uk_ 105 +seb 104 +_de 104 +pu 104 +i,_ 104 +ita 104 +nda 103 +_ti 103 +ni_ 103 +ca 103 +_Se 103 +ers 103 +pen 103 +ini 102 +an,_ 102 +angk 101 +uh 101 +han 101 +nta 100 +_in 99 +f 99 +nj 99 +ok 99 +aga 99 +_R 98 +as_ 98 +tr 98 +mer 97 +lam 97 +and 97 +end 96 +anga 96 +ne 96 +Sa 96 +ka_ 96 +arin 95 +gu 95 +_ha 94 +Z 94 +al_ 94 +ga_ 94 +_Z 93 +_pen 93 +dar 93 +Ad 93 +i._ 93 +ada_ 93 +atan 93 +tak 93 +i. 93 +ia_ 92 +asa 92 +ap_ 92 +ari_ 92 +kat 92 +_seb 92 +_Za 91 +Za 91 +den 91 +n. 90 +_u 90 +_Ad 90 +engan 89 +ib 89 +any 89 +n._ 89 +o_ 89 +Zar 88 +Zari 88 +rina 88 +_Zar 88 +_Zari 88 +Zarin 88 +arina 88 +ks 88 +angka 87 +oli 87 +eg 87 +kt 86 +_Sa 86 +hu 85 +ih 85 +us_ 85 +adi 85 +om 85 +eba 85 +anya 85 +_bu 84 +denga 83 +L 83 +ed 83 +dak 83 +deng 83 +ma_ 82 +asi_ 82 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/irish.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/irish.lm new file mode 100644 index 0000000..a16a027 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/irish.lm @@ -0,0 +1,400 @@ +_ 8010 +a 2622 +i 1573 +h 1334 +n 1247 +r 968 +_a 847 +e 830 +s 817 +t 747 +l 639 +c 636 +g 598 +o 590 +d 554 +n_ 501 +a_ 487 +m 432 +an 415 +u 413 +b 379 +h_ 352 +ai 350 +ch 350 +ea 346 +r_ 346 +í 334 +é 321 +_s 309 +á 306 +in 281 +ar 277 +. 269 +_d 266 +s_ 254 +ir 253 +_b 250 +f 250 +an_ 246 +, 241 +,_ 226 +ag 225 +_an 221 +bh 218 +_c 216 +._ 212 +ac 210 +ha 208 +_a_ 201 +" 199 +_m 199 +th 198 +_t 190 +ach 182 +_ag 180 +_an_ 179 +í_ 176 +_l 168 +na 168 +nn 160 +e_ 159 +ar_ 158 +_g 157 +ú 156 +_i 152 +il 150 +le 150 +is 143 +ó 142 +_bh 138 +ei 138 +g_ 135 +_f 135 +dh 135 +l_ 126 +t_ 125 +ig 123 +é_ 122 +_n 120 +gu 120 +á_ 120 +mh 118 +id 117 +ch_ 117 +ad 116 +he 114 +ir_ 114 +ra 109 +o_ 109 +ach_ 107 +ia 105 +_ar 105 +us 104 +ui 104 +_" 101 +us_ 100 +T 99 +am 99 +ta 98 +gus 98 +gus_ 98 +_le 97 +gh 97 +_ch 97 +agus 94 +agus_ 94 +agu 94 +éa 93 +_agus 93 +_agu 93 +ean 93 +na_ 92 +d_ 92 +ái 91 +p 89 +it 89 +A 89 +_ar_ 88 +rt 86 +al 85 +oi 84 +sa 84 +"_ 82 +hai 81 +_r 79 +nn_ 79 +hu 79 +as 79 +éi 78 +_T 78 +ma 77 +air 77 +at 77 +ann 76 +B 76 +sé 76 +hí 75 +igh 74 +st 74 +ga 73 +go 71 +ua 71 +ne 71 +la 71 +- 71 +de 71 +te 71 +re 70 +inn 70 +ith 69 +eac 69 +_sé 69 +in_ 68 +_go 68 +hi 68 +each 68 +dh_ 68 +si 67 +ag_ 67 +_go_ 66 +hea 66 +go_ 66 +tha 64 +om 64 +_sé_ 63 +sé_ 63 +hí_ 63 +on 62 +se 61 +úi 60 +nt 60 +C 60 +D 59 +i_ 58 +_ag_ 58 +is_ 58 +ío 58 +_de 57 +_B 56 +il_ 56 +or 56 +_th 54 +ca 53 +fa 53 +amh 53 +_A 53 +le_ 52 +? 52 +S 51 +io 51 +_in 51 +sí 51 +li 51 +rai 50 +hf 50 +ht 50 +eo 50 +sc 50 +ri 49 +: 49 +igh_ 49 +gh_ 49 +_sí 49 +:_ 49 +há 49 +_D 49 +be 49 +aig 49 +hé 48 +oc 48 +idh 48 +rt_ 48 +ho 47 +os 47 +ann_ 47 +_C 46 +! 46 +Bh 46 +bhf 45 +_si 45 +lt 45 +_bhf 45 +irt 45 +ear 44 +_na 44 +ta_ 44 +air_ 44 +_p 44 +im 44 +aga 44 +_ma 44 +_S 44 +aigh 43 +án 43 +_dh 43 +uai 43 +ao 43 +cht 43 +ain 42 +bhe 42 +ait 42 +fh 42 +sa_ 41 +m_ 41 +adh 41 +ile 41 +_é 41 +ail 41 +eir 41 +ói 41 +_Bh 40 +as_ 40 +cha 40 +idh_ 40 +hái 39 +_i_ 39 +bh_ 39 +th_ 39 +ad_ 39 +och 39 +mh_ 39 +tr 39 +rea 38 +_se 38 +ro 38 +rí 38 +hair 38 +_is 38 +uil 37 +iú 37 +áin 37 +I 37 +ll 37 +mé 37 +_be 36 +ba 36 +eann 36 +tá 36 +_o 36 +M 36 +aid 36 +aith 36 +ib 36 +' 36 +tea 36 +_mé 35 +chu 35 +ibh 35 +each_ 35 +ean_ 34 +irt_ 34 +_na_ 34 +N 34 +ist 34 +fu 34 +mha 34 +bea 34 +h. 34 +_bhe 34 +lá 34 +ic 34 +_sí_ 33 +eis 33 +bhí 33 +ni 33 +héa 33 +_sa 33 +ith_ 33 +sí_ 33 +har 33 +_bhí 33 +ig_ 32 +ur 32 +aí 32 +hr 32 +_am 32 +_bhí_ 31 +da 31 +úir 31 +hfu 31 +_chu 31 +ol 31 +ne_ 31 +_fa 31 +An 31 +Bhí_ 31 +Bhí 31 +n, 31 +_ac 31 +bhí_ 31 +_bhfu 30 +_ó 30 +ana 30 +_M 30 +mé_ 30 +_fh 30 +aigh_ 30 +bhfu 30 +_mé_ 30 +tú 29 +_le_ 29 +tá_ 29 +hean 29 +háin 29 +sin 29 +eir_ 29 +nne 29 +cé 29 +_aga 29 +h._ 29 +Tá 29 +ibh_ 29 +iste 28 +An_ 28 +do 28 +hui 28 +fui 28 +ní 28 +ste 28 +acht 28 +n,_ 28 +co 28 +dea 28 +ng 28 +nach 28 +id_ 28 +hfui 28 +.. 28 +lei 28 +nac 28 +ce 27 +a. 27 +c_ 27 +lea 27 +hfuil 27 +_Bhí_ 27 +_bea 27 +adh_ 27 +di 27 +fuil 27 +." 27 +Tá_ 27 +ha_ 27 +ú_ 27 +uil_ 27 +."_ 27 +bhfui 27 +_Bhí 27 +éan 27 +_do 27 +lta 27 +aoi 27 +_lei 27 +_mh 26 +dú 26 +fuil_ 26 +eat 26 +-_ 26 +teac 26 +ath 26 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/japanese-euc_jp.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/japanese-euc_jp.lm new file mode 100644 index 0000000..18ba671 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/japanese-euc_jp.lm @@ -0,0 +1,400 @@ +¤ 78988 +¥ 57258 +_ 34456 +¡ 22280 +£ 18223 +¼ 11290 +¹ 11237 +Î 10621 +¬ 9502 +ë 8859 +¿ 8812 +¤Î 8266 +È 8180 +Í 7520 +Ë 7325 +à 6982 +Ê 6930 +Ç 6929 +µ 6896 +Æ 6865 +¤ë 6858 +ì 6261 +¡¼ 6067 +¼¥ 5926 +¡¼¥ 5888 +Ï 5878 +¸ 5806 +Ä 5562 +Á 5426 +½ 5314 +¤Ë 5228 +» 5011 +· 4836 +¤¤ 4775 +É 4385 +£_ 4323 +¤Ï 4310 +¡£ 4305 +¡£_ 4294 + 4253 +¥¹ 4090 +¹¤ 4075 +ê 4032 +§ 4029 +Ì 3975 +ó 3947 +¾ 3923 +° 3853 +´ 3845 +ò 3759 +³ 3583 +¡¤ 3485 +¤ì 3475 +® 3367 +À 3366 +ì¤ 3366 +¤ò 3314 +ë¡ 3313 +Å 3282 +¯ 3273 +¤ì¤ 3255 +Ó 3207 +Ã¥ 3188 +¥Ã 3182 +¬¥ 3175 +¥Ã¥ 3170 +¬§ 3131 +á 3058 +¤ë¡ 3035 +¥¬ 3024 +¬¥¬ 3000 +ë¡£ 2952 +ë¡£_ 2948 +¤ë¡£ 2947 +¤ë¡£_ 2943 +¢ 2905 +Ô 2893 +¤¹ 2865 +¤È 2848 +² 2819 +Ȥ 2791 +¿® 2776 +¥¬¥ 2749 +¬¥¬¥ 2730 +¥¬¥¬ 2729 +¬¥¬¥¬ 2729 +ª 2697 +è 2689 +Ð 2545 +¤Æ 2543 +¥È 2525 +¤¹¤ 2473 +¥¬¥¬¥ 2459 +¤Ç 2399 +. 2395 +Ñ 2381 +, 2380 +µ¤ 2357 +¥ó 2346 +Ö 2340 +± 2328 +¥£ 2326 +¡¥ 2316 +× 2314 +Õ 2293 +¤¹¤ë 2283 +¹¤ë 2283 +¤µ 2253 +._ 2251 +¤Ê 2227 +¤µ¤ 2222 +¥¸ 2200 +_¤ 2189 +Ǥ 2172 +¥» 2145 +Ó¥ 2137 +¤¿ 2112 +¤µ¤ì 2110 +µ¤ì 2110 +« 2100 +µ¡ 2061 +¥¯ 2027 +ë¤ 2017 +¤· 2011 +¥Ó 2007 +¥Ó¥ 2002 +ˤ 1995 +µ¤ì¤ 1983 +¤µ¤ì¤ 1983 +é 1947 +ó¥ 1913 +è¤ 1861 +¤¥ 1847 +¥ó¥ 1834 +¤¬ 1834 +¥ì 1826 +­ 1795 +¤¤¤ 1791 +ç 1782 +Þ 1782 +¤Ë¤ 1763 +¤È¤ 1760 +¥á 1716 +¥ë 1713 +¨ 1709 +ᥠ1696 +ʤ 1691 +·¤ 1688 +_¥ 1686 +¯¥ 1679 +¥¯¥ 1669 +¥á¥ 1668 +Ý 1666 +¤ë¤ 1659 +¤Ç¤ 1655 +¢¤ 1638 +â 1637 +¿¤ 1612 +¤·¤ 1598 +¼¥¸ 1584 +¡¼¥¸ 1584 +¤Ê¤ 1570 +¥µ 1568 +¤è 1565 +¤è¤ 1562 +ÍÑ 1554 +Ø 1544 +Ƥ 1541 +Æ¥ 1538 +¥¿ 1526 +³¤ 1525 +ì¤ë 1523 +¤ì¤ë 1523 +ð 1517 +¤¢ 1510 +¤¢¤ 1509 +- 1490 +»¡ 1476 +¥ê 1465 +¥¤ 1465 +¶ 1464 +¥á¥Ã 1454 +á¥Ã 1454 +¥á¥Ã¥ 1453 +¥Ã¥»¡ 1453 +¥»¡¼¥ 1453 +á¥Ã¥» 1453 +Ã¥»¡ 1453 +¥»¡¼ 1453 +¥Ã¥» 1453 +»¡¼¥ 1453 +¥»¡ 1453 +á¥Ã¥ 1453 +Ã¥» 1453 +Ã¥»¡¼ 1453 +»¡¼ 1453 +»¡¼¥¸ 1452 +º 1450 +ì¥ 1445 +õ 1441 +¥· 1420 +à 1419 +ý 1418 +¥µ¡ 1415 +µ¡¼¥ 1413 +¥µ¡¼ 1413 +¥µ¡¼¥ 1413 +µ¡¼ 1413 +·¥ 1413 +¥Æ 1411 +Ó¥¹ 1406 +¼¥Ó¥ 1406 +¡¼¥Ó¥ 1406 +¥Ó¥¹ 1406 +¡¼¥Ó 1406 +¼¥Ó 1406 +¥ì¥ 1403 +µ¡¼¥Ó 1403 +¼¥Ó¥¹ 1403 +¥Æ¥ 1396 +¥·¥ 1392 +¥¤¥ 1383 +æ 1378 +½¤ 1372 +_£ 1368 +Î¥ 1358 +T 1354 +Ï¡ 1341 +ª¤ 1338 +¤é 1337 +¤³ 1325 +¦ 1323 +Τ 1314 +¤Î¥ 1312 +¢¤ë 1311 +¤¢¤ë 1311 +Ô¤ 1308 +) 1302 +_. 1297 +Ü 1294 +£Í 1294 +¤³¤ 1292 +¼Ô 1289 +¥¹¤ 1284 +¤Æ¤ 1284 +¿¥ 1273 +¹¥ 1260 +_._ 1244 +÷ 1244 +þ 1238 +¥¹¥ 1211 +¥Õ 1190 +ë¥ 1182 +_¡ 1182 +¤¿¤ 1152 +È¥ 1151 +Í× 1145 +µ¤ì¤ë 1130 +ǽ 1129 +Õ¥ 1126 +Û 1120 +¥Õ¥ 1113 +¤Ï¡ 1105 +¥Ç 1103 +ß 1101 +é¤ 1084 +¥¢ 1080 +¸¤ 1062 +ï 1060 +Á÷ 1051 +£Á 1050 +¡¥£ 1043 +ÄÌ 1033 +§¬ 1033 +§¬§ 1033 +¬§¬ 1032 +¬§¬§ 1032 +Ï¡¤ 1030 +¤Ï¡¤ 1030 +Ǥ¢ 1022 +¤Ç¤¢ 1021 +Ǥ¢¤ 1021 +¤Ç¤¢¤ 1020 +Ç¥ 1012 +í 1006 +Äê 997 +¢¥ 995 +¤é¤ 991 +Í£ 988 +¥¢¥ 985 +£¥ 984 +£Í£ 983 +¡Ê 981 +¤ª 976 +¥£¥ 974 +¤Î¤ 971 +¤ª¤ 971 +¨¤ 962 +¥¿¥ 955 +ê¥ 955 +ê¤ 954 +¥È¥ 953 +¥Ç¥ 951 +¥É 942 +®¤ 929 +Íý 920 +ᤠ918 +ä 909 +¤« 904 +ø 904 +¼Ô¤ 903 +¤¢¤ë¡ 900 +¢¤ë¡ 900 +¥_ 894 +«¤ 893 +-_ 892 +Ï, 887 +¥È¤ 886 +¤Ï, 886 +¡¥_ 884 +¥× 881 +¤ê 881 +( 878 +C 877 +Ǥ¢¤ë 877 +I 877 +¤â 875 +¢¤ë¡£ 875 +i 872 +¥ê¥ 865 +¡Ë 860 +Ö¤ 857 +⤠856 +¥à 855 +§£ 855 +­¤ 846 +ÇÛ 841 +Þ¤ 834 +¬§£ 834 +e 825 +¤«¤ 825 +£Ð 819 +¤·¤Æ 818 +·¤Æ 818 +£Ô 808 +¼¨ 802 +¥Ç¥£ 796 +Ç¥£ 796 +_¬ 792 +a 776 +¥Ã¥È 771 +Ã¥È 771 +¤¹¤ë¤ 770 +¹¤ë¤ 770 +¸¥ 767 +Ѥ 748 +¤ì¤ë¡ 743 +ì¤ë¡ 743 +¥Ç¥£¥ 741 +Ç¥£¥ 741 +§_ 738 +¥¸¥ 732 +N 729 +¹ð 728 +¥ë¥ 728 +Á¤ 727 +¼õ 724 +ì¤ë¡£ 722 +¥¸¤ 718 +ˤè 716 +Ë¤è¤ 716 +¤Ë¤è¤ 715 +¡¼¥¸¤ 715 +¼¥¸¤ 715 +¤Ë¤è 715 +×¥ 715 +¥×¥ 711 +§¬§¬§ 710 +§¬§¬ 710 +¬§¬§¬ 710 +Ĥ 705 +Ò 702 +© 701 +_¬§ 699 +³¤È 696 +¬§_ 694 +»¥ 694 +¹¤ë¡ 692 +¤¹¤ë¡ 692 +¤³¤È 692 +¥»¥ 686 +ÍѤ 685 +¤Ê¤¤ 685 +ʤ¤ 685 +«¹ 684 +Ƥ¤ 684 +n 682 +ó¤ 682 +£Ä 681 +´« 681 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/japanese-shift_jis.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/japanese-shift_jis.lm new file mode 100644 index 0000000..eaf7d39 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/japanese-shift_jis.lm @@ -0,0 +1,400 @@ +‚ 9970 + 2204 +_ 1555 +ƒ 1214 +Ž 891 +A 885 +“ 846 +Ì 836 +A 831 + 818 + 815 +‚Ì 790 +Œ 739 +‘ 729 +Š 618 +‰ 607 +‹ 589 +— 568 +ð 566 +– 555 +É 552 +’ 528 +‚É 527 +‚ð 500 +• 489 + 481 +µ 461 +¢ 460 +½ 453 +” 449 +‚µ 449 +Æ 445 +Í 440 +B 419 +Å 411 +B 405 +ª 404 +‚½ 404 +‚¢ 401 +Ä 396 +È 389 +‚Æ 387 +é 368 +· 366 +µ‚ 363 +‚Å 361 +‚µ‚ 357 +‚é 352 +‚Í 352 +‚Ä 349 +‚È 345 +è 330 +‚ª 321 +ˆ 320 +¢‚ 320 +‚¢‚ 306 +‚· 305 +Ü 292 +© 284 +@ 282 +_‚ 281 +Ü‚ 275 +‚Ü 268 +v 263 +‚Ü‚ 258 +È‚ 256 +ê 251 +‚È‚ 240 +‚è 239 +­ 238 +Ä‚ 234 +à 232 +Æ‚ 231 +Å‚ 226 +@ 220 +½‚ 217 +‚Æ‚ 214 +‚Å‚ 211 +_ 210 +‚Ä‚ 205 +‚© 204 +©‚ 203 +‚½‚ 199 +³ 198 +Ì‚ 195 +ç 194 +¯ 194 +‚©‚ 182 +Á 182 +è‚ 181 +ß 180 +É‚ 180 +A‚ 176 +¤ 176 +± 173 +‚É‚ 172 +‚Ì‚ 172 +v‚ 169 +» 169 +·‚ 167 +ñ 167 +B_ 166 +N 166 +B_ 166 +O 165 +« 165 +A‚ 165 +· 164 +P 163 +ê‚ 163 +Á‚ 159 +æ 159 +_@ 157 +‚ê 156 +‚· 155 +[ 153 +‚ç 153 +X 153 +é‚ 148 +i 148 +‚é‚ 148 +‚Á 147 +·B 146 +±‚ 146 +‚·B 145 +j 142 +‚Á‚ 142 +‚P 141 +µ‚Ä 141 +‚µ‚Ä 141 +Í‚ 141 +‚à 141 +‚·‚ 137 +V 137 +‚ß 135 +‚ê‚ 135 +ú 134 +u 133 +[ 132 +‚¤ 131 +l 129 +å 129 +s 128 +¾ 128 +  125 +‚± 125 +S 125 +g 124 +ª‚ 123 +³‚ 123 +ü 123 +‚±‚ 122 +‘ 122 +Ç 120 +‚³ 120 +‚è‚ 120 +¦ 120 +\ 119 +Í 119 +u 119 +v 119 +½ 119 +ß‚ 118 +W 118 +‚Í 117 +‚Ü‚· 117 +R 117 +‚½ 117 +Ü‚· 117 +æ‚ 114 +â 114 +ã 113 +˜ 113 +{ 113 +”N 112 + ‚ 111 +í 111 +‚³‚ 111 +o 108 +‚Ü‚· 107 +Ü‚· 107 +Q 106 +ž 106 +‚« 105 +Ü‚·B 104 +à‚ 103 +«‚ 103 +ç‚ 103 +ƒ“ 103 +ì 102 +»‚ 102 +‚ ‚ 100 +“ú 100 +‚  100 +‚ß‚ 99 +‚µ‚½ 98 +µ‚½ 98 +Ê 97 +¯‚ 96 +¶ 96 +ð‚ 96 +I 95 +[ƒ 95 +[ƒ 95 +‚ÍA 94 +‘å 94 +ÍA 94 +¤‚ 93 +‚Ä‚¢ 92 + 92 +Ä‚¢ 92 +‚­ 92 +E 92 +‚Q 91 +¨ 90 +w 90 +‚Ä‚¢‚ 89 +Ä‚¢‚ 89 +Î 89 +¼ 88 +‚ç‚ 87 +x 87 +­‚ 86 +P‚ 86 +§ 86 +‚ª‚ 86 +n 86 + 85 +·‚é 85 +‚·‚é 85 +‚¤‚ 84 +‚ñ 84 +¿ 84 +‚Í‚ 84 +À 84 +¾‚ 83 +‚½B 83 +½B 83 +† 83 +‚¯ 83 +ï 82 +² 82 +v‚ 80 +‚¾ 80 +‚P‚ 80 +©‚ç 79 +¡ 79 +Aƒ 77 +Ý 77 +¬ 77 +‚Ç 77 +‚µ‚Ä‚ 77 +µ‚Ä‚ 77 +ñ‚ 76 +B‚ 75 +ƒX 75 +‚©‚ç 75 +‚«‚ 74 +c 74 +Ù 74 +‚O 73 +‚¦ 73 +¨‚ 72 +i‚ 72 +‚ð‚ 71 +¦‚ 71 +B‚ 71 +‚æ 70 +‰ï 70 +Û 70 +y 70 +Ç‚ 69 +T 69 +p 69 +è 68 +“ƒ 68 +ƒ“ƒ 68 +‚·B_ 67 +l 67 +Z 67 +‚æ‚ 67 +’† 67 +‰ü 67 +® 67 +·B_ 67 +Ï 67 +X‚ 66 +Ð 66 +‚à‚ 66 +¹ 66 +—Í 66 +A 66 +‚â 65 +‚¯‚ 65 +Aƒ 65 +U 65 +‚¨ 64 +í‚ 64 +‚í 63 +‚è‚Ü 62 +C 62 +‚Á‚½ 62 +è‚Ü 62 +‚R 62 +µ 62 +Á‚Ä 62 +‚Á‚Ä 62 +Á‚½ 62 +_ƒ 61 +è‚Ü‚ 61 +‚µ 61 +üŠ 61 +^ 61 +Ž– 61 +‚è‚Ü‚ 61 +é 61 +l‚ 61 +‚é 61 +‚» 60 +‰üŠv 60 +‚è 60 +‰üŠ 60 +Šv 60 +üŠv 60 +Ô 60 +‚í‚ 60 +±‚Æ 60 +Ÿ 60 +A 60 +û 59 +Žž 59 +‚È‚Ç 59 +È‚Ç 59 +‚ 59 +“¯ 59 +W‚ 59 +ðŽ 58 +i 58 +‚±‚Æ 58 +Q‚ 58 +j 58 +­ 58 +N‚ 58 +–{ 57 +‚»‚ 57 +•ª 57 +„ 57 +‚ðŽ 57 +Ì 56 +É 56 +‚µA 56 +e 56 +ƒg 56 +µA 56 +Ê‚ 56 +@‚ 56 +‚ 55 +z 55 +“I 55 +Y 55 +Å‚· 55 +¿‚ 55 +èA 55 +A 55 +‚¨‚ 54 +¹‚ 54 +‚X 54 +‚¾‚ 54 +t 54 +‚Å‚· 54 +ƒj 54 +‚¦‚ 53 +‚É 53 +±‚Æ‚ 53 +ã‚ 53 +‚±‚Æ‚ 53 +º 53 +I‚ 53 +‘‚ 53 +ª 53 +A 53 +‚U 53 +~ 53 +‚¹ 52 +A“ 52 +x‚ 52 +‚èA 52 +‚Ì 52 +’n 52 +S‚ 51 +A“ 51 +b 51 +j‚ 51 +‚Ç‚ 51 +‚Q‚ 51 +¢‚½ 51 +E 51 +î 51 +A‘ 51 +ž‚ 51 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/korean.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/korean.lm new file mode 100644 index 0000000..77ea730 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/korean.lm @@ -0,0 +1,400 @@ +_ 11636 +À 2659 +° 1629 +Ç 1578 +¸ 1458 +¿ 1397 +´ 1299 +µ 1118 +Á 1005 +± 928 +» 849 +¼ 840 +_À 809 +¹ 808 +º 780 +¡ 773 +à 764 +³ 674 +¾ 640 +Ì 591 +Î 580 +ÀÌ 538 +½ 526 +Ï 519 + 518 +_° 518 +Ù 506 +· 483 +È 464 +ö 463 +­ 454 +´Ù 451 +ø 404 +Æ 395 +ë 384 +_¿ 382 +í 377 +. 374 +Å 373 +ç 358 +._ 347 +_Ç 344 +´Â 338 +¡_ 333 +Â_ 329 +¿¡ 327 +_Á 319 +´Â_ 317 +´Ù. 313 +Ù. 313 +â 308 +¶ 308 +´Ù._ 301 +Ù._ 301 +»_ 299 +_¹ 291 +î 288 +® 282 +À» 279 +Ö 278 +¦ 274 +À»_ 271 +Î_ 269 +, 266 +Ñ 266 +°í 261 +Áö 258 +,_ 258 +°¡ 250 +ß 248 +_¼ 246 +Ä 245 +ÀÇ 244 +Ì_ 243 +_¸ 243 +_µ 242 +ü 238 +é 235 +¼­ 234 +ÀÌ_ 234 +ÇÏ 234 +_± 233 +´ë 228 +·Î 227 +ÇÑ 222 +½Ã 222 +_³ 215 +±â 212 +_à 210 +í_ 208 +_´ 206 +¦_ 206 +Ç_ 205 +_¾ 205 +º_ 204 +÷ 198 +Àº 198 +°í_ 194 +·Î_ 193 +ó 193 +¿¡_ 193 +¸¦_ 192 +¸¦ 192 +_ÀÌ 190 +­_ 189 +Àº_ 189 +_½ 189 +µµ 188 +ÀÏ 188 +ÀÇ_ 188 +_º 186 +Í 177 +Ú 175 +ú 171 +»ç 161 +Ô 154 +_ÀÏ 153 +Ø 152 +¿ø 151 +±¸ 150 +µ¿ 147 +Ò 147 +¸¸ 145 +¼ö 143 +¤ 142 +ºÎ 142 +_» 141 +ÀÖ 140 +æ 139 +Ð 138 +ù 138 +ª 137 +µé 136 +è 134 +À¸ 134 +_ÀÖ 133 +² 132 +Ñ_ 127 +ÀÎ 125 +°¡_ 123 +ÀÚ 122 +ÇÑ_ 121 +Àü 121 +¾Æ 118 +ý 117 +å 116 +Ï_ 115 +¾î 115 +µ_ 115 +¢ 114 +Ö´ 113 +°ú 112 +¸· 111 +¯ 109 +ÇØ 109 +§ 108 +à 108 +_È 108 +±¹ 107 +¼­_ 107 +× 107 +£ 106 +ÀÖ´ 105 +ȸ 103 +¸® 101 +ö_ 101 +û 100 +_ÀÖ´ 100 +õ 100 +¸·Î 100 +" 98 +À¸·Î 97 +ÁÖ 97 +À¸· 97 +Àå 95 +_´ë 94 +¡¼ 94 +³ª 94 +_½Ã 94 +¥ 94 +µî 94 +Á¤ 92 +°ø 92 +_Å 91 +á 91 +Ï° 90 +ÇÐ 90 +¸·Î_ 90 +Ê 89 +© 89 +Í_ 89 +¸_ 89 +À¸·Î_ 89 +éÀ 89 +Þ 88 +¡¼­ 88 +¿¡¼ 88 +¿¡¼­ 88 +ê 87 +µµ_ 87 +±³ 85 +_Æ 85 +î_ 84 +°æ 84 +µéÀ 84 +¸í 84 +ëÇ 83 +¿ù 83 +_Áö 82 +ÇÏ° 82 +¿À 81 +¶ó 80 +¿¡¼­_ 79 +¡¼­_ 79 +ÀÏ_ 78 +Ý 78 +Á¦ 78 +ç_ 78 +øÀ 78 +' 77 +Çß 77 +ì 77 +Ü 77 +Áß 77 +ú_ 76 +Áö_ 76 +Ó 76 +â_ 75 +( 74 +) 74 +»ó 74 +°ü 74 +»ý 73 +_¿ù 72 +_°¡ 72 +_¼ö 72 +- 72 +¿© 72 +Ö´Ù 72 +º¸ 71 +ÀÖ´Ù 71 +»ê 70 +°³ 70 +½º 70 +¼± 69 +¿ë 69 +°ú_ 69 +_ÀÖ´Ù 69 +_µî 69 +ø_ 69 +ß´ 69 +°Í 68 +³» 68 +_¡ 68 +_ÇÑ 68 +ù_ 67 +ü 67 +¸¿ 66 +_ÀÏ_ 66 +Çß´ 66 +°Ô 65 +ñ 65 +_¶ 65 +_°Í 65 +Çß´Ù 64 +ß´Ù 64 +_ÇÏ 63 +¹Î 62 +« 62 +Ï´ 62 +¼Ò 62 +¿ù_ 62 +Á¶ 61 +³â 61 +Ï°í 61 +Ì´ 60 +¾È 60 +ÇÏ°í 60 +õ 59 +_¿ù_ 59 +_¼­ 59 +Åë 59 +ÆÄ 58 +®_ 58 +_¸¸ 58 +Ø_ 58 +´ç 57 +ß´Ù. 57 +¬ 57 +Õ 57 +Çß´Ù. 57 +¹° 57 +¾÷ 57 +Ö´Ù. 56 +ß_ 56 +ÀÖ´Ù. 56 +¿Í 56 +ß´Ù._ 56 +Áø 56 +Àç 55 +¸° 55 +ÍÀ 55 +Æ® 55 +¹é 55 +ÀÌ´ 55 +Ö´Ù._ 54 +_¹é 54 +¿Í_ 53 +Àû 53 +ð 53 +¹® 53 +_ÁÖ 53 +´Ü 53 +¼º 53 +ÇØ_ 53 +°Ç 53 +íÀ 52 +_Àü 52 +Ô_ 52 +¿¬ 52 +_°æ 51 +°ÍÀ 51 +°£ 51 +¿ì 51 +È­ 51 +ä 50 +_¾Æ 50 +´ëÇ 50 +Ä¡ 50 +Ï°í_ 49 +ÇÏ°í_ 49 +_ÀÎ 49 +Û 49 +É 49 +_" 48 +öµ 48 +À§ 48 +ÀÌ´Ù 48 +ÀÔ 48 +_°ÍÀ 48 +Ì´Ù 48 +¡­ 47 +Ì´Ù. 47 +_°ø 47 +ÀÌ´Ù. 47 +°Ô_ 47 +_»ç 47 +¸ç 47 +½Å 47 +Ã_ 46 +ÅÍ 46 +é_ 46 +Ò_ 46 +ï 46 +ÇÏ´ 46 +_°³ 45 +_´Ù 45 +_ÀÚ 45 +¸¶ 45 +°è 45 +Çà 45 +Ì´Ù._ 45 +÷À 44 +îÁ 44 +ÈÄ 44 +±â_ 43 +(_ 43 +¸é 43 +­¿ 43 +ü_ 43 +ºñ 42 +­´ 42 +ë_ 42 +ÀÎ_ 42 +_ÀÌ_ 42 +µî_ 42 +°­ 42 +Îà 41 +µÇ 41 +¿øÀ 41 +¿µ 41 +À½ 40 +Îõ 40 +±× 40 +Ë 40 +¿¹ 40 +_¿À 40 +øÇ 40 +¸» 40 +_ÇÐ 40 +¡­_ 39 +_³â 39 +³² 39 +ÇÒ 39 +¿_ 39 +_³ª 39 +³­ 38 +¸íÀ 38 +âÀ 38 +ª_ 38 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/malay.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/malay.lm new file mode 100644 index 0000000..911d0cf --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/malay.lm @@ -0,0 +1,400 @@ +_ 87128 +a 50232 +n 25424 +e 18746 +i 18605 +an 14419 +u 12470 +k 11955 +t 11875 +r 11007 +d 9856 +g 9545 +m 9390 +s 8926 +l 8631 +n_ 8004 +an_ 7095 +p 6890 +a_ 6739 +b 6645 +ng 6630 +h 5964 +da 5153 +_d 5107 +er 4625 +ka 4448 +la 4339 +y 4323 +i_ 4295 +en 4159 +ya 3800 +ang 3778 +_m 3750 +o 3593 +. 3539 +._ 3310 +at 3288 +ah 3216 +_b 3199 +_s 3177 +ta 3076 +ra 3036 +_k 2949 +g_ 2939 +ng_ 2933 +ar 2915 +_p 2906 +me 2884 +ga 2781 +di 2778 +ak 2727 +al 2705 +_me 2671 +ang_ 2524 +h_ 2509 +ba 2508 +pa 2454 +kan 2449 +in 2437 +tu 2411 +_t 2376 +sa 2338 +_da 2276 +j 2276 +pe 2225 +, 2150 +k_ 2147 +ma 2143 +se 2138 +am 2131 +kan_ 2117 +_di 2082 +,_ 2079 +ke 2048 +un 2004 +be 1947 +_a 1925 +na 1871 +ti 1868 +ri 1861 +u_ 1857 +as 1854 +ny 1827 +ha 1789 +te 1788 +_pe 1768 +em 1750 +it 1737 +_i 1732 +_ke 1711 +yan 1706 +ad 1698 +ia 1673 +yang 1673 +_y 1668 +_ya 1655 +yang_ 1653 +_se 1648 +ah_ 1646 +_yan 1639 +_yang 1639 +ala 1612 +nya 1587 +el 1576 +ik 1571 +t_ 1568 +ai 1549 +men 1531 +eng 1522 +_men 1464 +nga 1441 +dan 1366 +_be 1365 +si 1343 +uk 1328 +ada 1299 +nt 1291 +__ 1287 +ap 1276 +ua 1265 +___ 1238 +- 1213 +ja 1211 +ber 1204 +gan 1203 +_ba 1193 +____ 1189 +ni 1181 +_te 1169 +c 1143 +ran 1141 +_____ 1140 +m_ 1127 +ara 1118 +per 1099 +le 1084 +_dan 1083 +dan_ 1079 +ngan 1060 +_dan_ 1050 +ya_ 1046 +at_ 1044 +da_ 1021 +li 1016 +aka 1013 +A 999 +r_ 999 +w 997 +eb 995 +lah 980 +ata 980 +ak_ 978 +nd 974 +_ber 955 +gi 936 +is 933 +il 931 +tu_ 923 +s_ 920 +gan_ 915 +mb 913 +wa 904 +ag 903 +ngan_ 898 +ter 887 +nya_ 877 +S 873 +ek 853 +ru 852 +_l 838 +ela 828 +itu 824 +ol 822 +aha 822 +ada_ 820 +pu 812 +di_ 807 +bu 807 +am_ 804 +ur 801 +tan 790 +mp 790 +_per 786 +_sa 784 +M 782 +ut 781 +us 779 +era 779 +lam 778 +lah_ 775 +asa 767 +ki 761 +ir 759 +de 756 +enga 750 +su 748 +du 741 +id 739 +" 733 +akan 732 +apa 728 +_S 724 +ul 721 +lu 717 +ari 717 +dal 704 +et 698 +es 698 +pad 688 +_ma 688 +_M 685 +ana 684 +bi 679 +pada 673 +dala 673 +l_ 671 +ep 664 +f 662 +_di_ 658 +B 655 +ing 655 +_j 654 +ika 653 +ku 650 +_. 644 +akan_ 642 +ama 637 +pen 636 +alam 634 +eh 634 +pada_ 633 +ai_ 632 +_ter 632 +K 631 +mu 628 +ju 628 +P 626 +mem 625 +au 622 +_mem 614 +lan 612 +_._ 611 +ntu 608 +lam_ 605 +um 601 +on 600 +gk 597 +_in 597 +ngk 597 +a. 584 +meng 582 +_meng 578 +alam_ 577 +_A 576 +aa 575 +uk_ 572 +_pen 569 +ban 569 +or 569 +st 566 +ay 566 +dar 565 +_pa 564 +a._ 564 +_h 562 +bah 562 +_P 560 +D 559 +ri_ 558 +ini 552 +_de 551 +rt 550 +aan 545 +_it 542 +_itu 542 +nda 540 +eri 540 +dalam 537 +_B 533 +_dal 532 +ip 532 +_dala 532 +ta_ 528 +_u 527 +ung 525 +ih 524 +aw 520 +_n 519 +atu 517 +ila 513 +mi 513 +leh 513 +ian 512 +tuk 509 +awa 508 +gu 506 +ert 506 +engan 505 +ole 504 +_K 501 +seb 497 +ca 496 +gg 493 +_ta 489 +ra_ 488 +ngg 488 +itu_ 487 +emb 482 +ni_ 482 +ida 482 +nj 482 +_ti 479 +man 478 +den 477 +_D 474 +_ka 473 +aj 470 +oleh 468 +n. 468 +n._ 464 +ngka 464 +gka 464 +dak 464 +anga 461 +ena 459 +san 458 +pat 458 +rk 458 +( 455 +ent 454 +agi 453 +) 451 +ia_ 450 +ge 450 +ab 449 +im 447 +_ini 446 +ntuk 445 +I 445 +ar_ 440 +N 439 +aan_ 436 +_la 433 +pi 432 +baha 431 +deng 430 +han 430 +bag 429 +eh_ 429 +hu 429 +denga 428 +_o 427 +na_ 427 +T 425 +leh_ 422 +_den 422 +ka_ 419 +any 415 +ud 415 +rang 414 +anya 413 +gi_ 412 +angan 412 +a, 411 +_deng 410 +ita 409 +kat 408 +re 408 +_( 406 +tuk_ 403 +aga 401 +ne 400 +and 399 +aya 398 +_dar 397 +a,_ 396 +ro 396 +ntuk_ 393 +eba 392 +aran 390 +_" 387 +ed 385 +end 384 +ko 383 +sa_ 381 +p_ 381 +ara_ 380 +_seb 379 +alah 379 +oleh_ 379 +an. 378 +dak_ 378 +eg 378 +hi 376 +dari 375 +an._ 375 +au_ 373 +bo 373 +ti_ 371 +ula 371 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/manx.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/manx.lm new file mode 100644 index 0000000..e6eceeb --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/manx.lm @@ -0,0 +1,400 @@ +_ 36004 +e 9455 +a 8302 +y 6395 +n 6395 +h 5736 +r 4939 +s 4799 +o 4429 +i 4129 +l 3462 +y_ 2896 +g 2731 +n_ 2549 +d 2232 +t 2160 +_a 1836 +m 1823 +sh 1774 +e_ 1746 +h_ 1645 +yn 1550 +c 1531 +ee 1515 +gh 1461 +s_ 1460 +_s 1388 +ey 1345 +_e 1316 +ag 1312 +a_ 1201 +r_ 1173 +agh 1165 +in 1148 +as 1136 +_d 1136 +u 1124 +he 1060 +yn_ 1025 +oo 1012 +ey_ 1005 +_m 1002 +er 965 +v 949 +_y 941 +_v 895 +_c 891 +_as 880 +' 869 +, 866 +_n 832 +ll 828 +,_ 827 +_sh 818 +. 802 +hi 797 +as_ 770 +ee_ 768 +ne 767 +_as_ 764 +b 762 +re 735 +ay 730 +._ 730 +an 726 +ar 725 +gh_ 722 +ny 709 +en 703 +_r 697 +ch 688 +agh_ 687 +dy 686 +t_ 677 +le 667 +k 658 +er_ 616 +oi 612 +ea 607 +_t 601 +yr 596 +_er 585 +ra 574 +_dy 572 +in_ 570 +l_ 564 +f 557 +_l 556 +ha 551 +_g 548 +_ny 534 +nn 530 +" 528 +_ch 527 +_y_ 524 +ie 514 +dy_ 514 +_dy_ 513 +aa 510 +_f 509 +j 504 +sh_ 487 +oa 480 +is 478 +_h 470 +rr 468 +ny_ 467 +_ny_ 463 +_er_ 454 +ish 445 +ho 442 +ai 441 +d_ 435 +ro 423 +ht 418 +ei 417 +shi 416 +il 409 +me 408 +_ay 403 +_b 403 +la 400 +_j 400 +my 394 +va 391 +ns 386 +on 385 +_o 381 +ys 380 +_shi 379 +ia 377 +ayn 373 +_va 371 +hen 362 +she 356 +ri 345 +lle 342 +ooi 342 +mee 340 +ley 335 +_me 331 +el 330 +rt 328 +ie_ 327 +eh 324 +w 316 +_ayn 313 +al 311 +g_ 309 +ish_ 308 +lley 307 +mee_ 305 +_mee 304 +ill 301 +es 299 +na 299 +je 298 +yns 296 +C 294 +_my 291 +_she 290 +ley_ 282 +V 280 +_yn 278 +_" 278 +_mee_ 277 +ta 272 +_V 271 +ys_ 268 +- 268 +lley_ 265 +hin 264 +_ro 259 +shin 256 +_yn_ 255 +_je 255 +do 253 +va_ 253 +ne_ 253 +_va_ 252 +ns_ 252 +_shin 251 +yns_ 250 +ayns 248 +en_ 247 +che 246 +_ayns 246 +eh_ 246 +_do 242 +ad 241 +ney 240 +o_ 240 +ym 240 +ed 239 +yr_ 239 +ayns_ 237 +ur 237 +st 234 +_C 234 +rt_ 234 +'n 232 +m_ 232 +p 231 +li 231 +or 230 +ow 228 +hin_ 225 +da 225 +shen 223 +"_ 223 +'n_ 223 +Va 221 +ght 220 +shin_ 219 +tr 217 +_Va 217 +ry 216 +ve 216 +_shen 215 +ty 214 +mo 206 +_' 205 +_ve 205 +ma 203 +be 203 +te 203 +hie 203 +hey 203 +nag 202 +ll_ 201 +yl 200 +w_ 200 +ss 200 +aa_ 198 +nagh 198 +an_ 197 +io 195 +ow_ 194 +it 194 +sy 193 +ayr 193 +ney_ 192 +E 192 +sht 192 +ni 191 +_k 190 +ha_ 190 +ain 189 +u_ 189 +hy 189 +aght 188 +oo_ 188 +ree 188 +lh 187 +_tr 186 +esh 186 +_che 183 +yrt 182 +_da 182 +oar 182 +doo 181 +k_ 181 +se 180 +au 180 +ille 179 +ar_ 179 +_lh 179 +ki 177 +arr 176 +ec 176 +ol 175 +_doo 175 +T 175 +row 175 +_row 174 +ge 173 +so 172 +oy 171 +oil 170 +_re 170 +_ag 170 +'e 169 +rey 169 +illey 169 +ck 168 +ad_ 168 +ann 168 +n, 166 +eea 166 +_ta 166 +ht_ 165 +ae 162 +_row_ 162 +! 162 +row_ 162 +ane 161 +fe 161 +dd 160 +go 159 +tyn 159 +oin 158 +ooa 158 +n. 158 +eg 156 +_ec 156 +_ma 156 +_agh 155 +n,_ 154 +_fe 154 +Ch 154 +nyn 153 +fo 152 +eay 152 +nagh_ 152 +n._ 152 +_go 151 +S 150 +ke 150 +hey_ 150 +enn 150 +cha 149 +rre 149 +_fo 149 +ghe 149 +raa 149 +G 148 +lan 148 +mm 147 +ym_ 147 +A 146 +c_ 146 +oill 145 +hee 144 +ooar 144 +_E 144 +nne 143 +tey 142 +ir 141 +de 141 +hyn 140 +_he 140 +nyn_ 140 +'s 139 +_gh 139 +_cha 138 +L 138 +yrt_ 138 +_Ch 137 +e, 137 +lla 136 +Va_ 136 +ooin 136 +ell 135 +a' 135 +os 135 +_oo 134 +am 134 +rish 133 +th 133 +_mo 133 +ris 133 +iag 133 +gg 133 +_Va_ 132 +iagh 132 +_G 132 +e,_ 132 +ass 132 +!_ 132 +my_ 132 +hoo 131 +_T 131 +nee 130 +a'n_ 129 +rag 129 +a'n 129 +_'s 129 +_so 128 +co 128 +rey_ 128 +_eh 126 +_my_ 126 +nni 126 +ou 126 +_'sy 125 +'sy 125 +_p 125 +vo 125 +_S 125 +H 125 +_agh_ 125 +tra 124 +moo 124 +hu 123 +ooy 123 +ragh 123 +al_ 123 +it_ 123 +hia 122 +id 122 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/marathi.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/marathi.lm new file mode 100644 index 0000000..479f4fd --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/marathi.lm @@ -0,0 +1,400 @@ +þ 17815 +_ 14534 +þþ 4035 +þ_ 3087 +· 2180 +ø 1762 +·þ 1669 +ú 1654 +¡ 1534 +¥ 1480 +¡þ 1433 +Å 1342 +£ 1289 +ˆ 1237 +› 1163 +­ 1158 +¬ 1153 +þþ_ 1133 +¿ 1099 +¨ 1084 +Ÿ 1062 + 1059 +ú_ 1054 +¥þ 1054 +ˆÅ 1050 +¡þþ 1039 +þú 989 +œ 983 +›þ 968 +‚ 965 +¹ 949 +_‚ 936 +. 936 +¨þ 915 +þ¿ 859 +þ£ 842 +¬þ 838 +Ÿþ 836 +þ· 769 +þ 764 +µ 710 +þ¥ 710 +œþ 684 +þ·þ 681 +._ 670 +þú_ 637 +½ 609 +‚þ 578 +_Ÿ 578 +_‚þ 569 +_ˆ 543 +þ 530 +_· 530 +µþ 524 +_œ 523 +Š 511 + 504 +ø_ 495 +·þ_ 477 +þ¥þ 476 +þ­ 474 +_¹ 474 +_¬ 457 +_ˆÅ 447 +_Ÿþ 447 +¡þþ_ 446 +þø 444 +¸ 438 +Šþ 423 +¥þþ 422 +þ 409 +þ¨ 388 +Åþ 387 +þþ 381 +£_ 366 +ˆÅþ 359 +é 339 +þ¨þ 334 +_¬þ 332 +þµ 331 +þ› 324 +›þþ 320 +_œþ 320 +Ÿþþ 318 +ª 315 +_­ 315 +›þ_ 314 +Û 313 +þ¹ 306 +þ£_ 303 +þ¬ 301 +þˆ 297 + 297 +þþ 295 +ªþ 284 +þ¡ 280 +§ 274 +¿_ 272 +þþ· 270 +þ¡þ 268 +¥þþ_ 268 +£þ 264 +þ 264 +­ú 263 +, 258 +þþ·þ 256 +þ¥þþ 256 +þ·þ_ 256 +,_ 255 +þˆÅ 255 +Ù 249 +¬þþ 247 +þþ¿ 243 +þþ£ 241 +_› 234 +_·þ 233 +·þþ 232 +þœ 232 +·¡ 231 +þ¿_ 231 +þ›þ 230 +þ¬þ 228 +Ä 227 +š 226 +þµþ 225 +½_ 223 +·¡þ 221 +­½ 220 +_ 220 +¥ø 219 +µþ_ 218 +¨þþ 217 +þ. 216 +þŸ 215 +_›þ 213 +.. 209 +_Ÿþþ 209 +þþþ 205 +þþ 205 +·¡þþ 204 +‰ 204 +·þú 203 +þ¥þþ_ 202 +Å_ 202 +þþ¥ 201 +ê 198 +_¨ 198 +þŠ 193 +_¡ 191 +þœþ 190 +þ._ 189 +¡þ 188 +¡ 188 +¡þþ 187 +Ï 186 +ø· 186 +ž 185 +­ú_ 180 +þ_ 180 +_þ 180 +‰þ 179 +Ú 178 +_ˆÅþ 176 +_·¡þ 175 +_·¡þþ 175 +­þ 175 +_·¡ 175 +þŠþ 174 +þ­ú 171 +¥¡ 170 +_ 170 +... 168 +¥¡þ 167 +þú 166 +_¥ 164 +þŸþ 164 +‚þ­ 163 +¥¡þþ 163 +žþ 162 +ø·þ 162 +_‚þ­ 162 +¡þþ_ 161 +­ø 160 +ˆÅ_ 159 +þþ¥þ 159 +þ­½ 157 +œþþ 154 +þ 154 +_þ 154 +_¸ 154 +ø¥ 153 +þþ 153 +šþ 151 +þ£þ 151 +_Š 151 +‚þ­½ 150 +þ§ 150 +·ø 150 +ø. 149 +_‚þ­½ 149 +‚¬ 148 +¥þú 148 +£ú 147 +œÏ 147 +Å£ 146 +þú_ 146 +_‚¬ 145 +ø._ 145 +þþ¨ 144 +þÄ 143 +‹ 142 + 140 +¡þþ 140 +¹¨þ 139 +¹¨ 139 +þþ­ 137 +þþ› 136 +_­ø 136 +Ÿ­ 136 +_¡þ 135 +ú. 135 +·þø 135 +' 135 +ˆÅ£ 134 +_¥þ 132 +þþ¨þ 131 +þþ·þ_ 131 +µþþ 129 +'_ 129 +_›þþ 129 +ú._ 128 +þÛ 127 +.... 127 +˜ 127 +¿ 126 +þþ¬ 125 +_¨þ 124 +¡þ_ 123 +þ·þþ 123 +« 122 +; 122 +_œÏ 121 +_¡þþ 119 +» 118 +¬þ¿ 115 +¥þ¿ 114 +¥þ_ 114 +þþŠ 113 +þ¥¡þ 113 +þ¥¡ 113 +b 113 +þ£ú 112 +_' 112 +s 111 +& 111 +þþ 111 +‚¬þ 111 +þþú 111 +p 111 +ê› 111 +_£ 110 +þ¥¡þþ 110 +bs 109 +ê›þ 109 +n 109 +º 109 +_‚¬þ 108 +&n 107 +bsp; 107 +nbsp; 107 +sp; 107 +nb 107 +bsp 107 +nbs 107 +sp 107 +nbsp 107 +&nb 107 +  107 +p; 107 +&nbs 107 +þþþ 106 +_'_ 106 +þ¥ø 106 +·þ£ 106 +ø¥þ 106 +þþ_ 105 +¨þ£ 104 +þ¿ 104 +˜þ 104 +þ¸ 104 +_Šþ 103 +þ¬þþ 103 +›ø 103 +­ø· 102 +þþŠþ 101 +þþ­ú 100 +þ›þþ 99 +þ, 99 +_ 98 +þ,_ 98 +_ˆÅ£ 98 +‚þœ 98 +þþú_ 98 +_þþ 97 +;& 97 +_‚þœ 97 +‚þœþ 97 +_‚þœþ 96 +þ 96 +¡þþþ 96 +¬þ· 96 +‡ 96 +;&nb 95 +p;&nb 95 +;&n 95 +p;& 95 +;&nbs 95 +bsp;& 95 +..... 95 +ê›þ_ 95 +sp;&n 95 +sp;& 95 +p;&n 95 +° 94 +_‡ 94 +ƒ 94 +¥¡þþ_ 94 +þþ¬þ 93 +Ÿþú 93 +þµþ_ 93 +£ú_ 93 +œþµ 93 +_ž 92 +µ¡ 92 +_­ø· 92 +þ­ú_ 92 +µ¡þ 92 +·þú_ 91 +¹­ 91 +­½_ 90 +_¬þþ 90 +_œþþ 90 +þþ¥þþ 90 +„ 90 +µ¡þþ 90 +‹þ 89 +¹· 89 +þ¡þ 89 +þ£ú_ 89 +þÚ 89 +þ¡ 89 +þˆÅþ 89 +¿Š 89 +Šþþ 89 +_Ÿ­ 88 +½Å 88 +þ¡þþ 88 +_¹¨ 88 +_¹¨þ 88 +­ø·þ 87 +ø 87 +ˆ½ 87 +›þþ­ú 87 +_‹ 87 +­µ 87 +›þþ­ 87 +œþµþ 86 +¥þú_ 86 +_‚þ¹ 85 +‚þ¹ 85 +£· 85 +_„ 85 +¹·þ 85 +_›þþ­ 84 +¡ø 84 +þ¹µþ 83 +þþµ 83 +¹µþ 83 +¹µ 83 +þ¹µ 83 +þþ_ 83 +_ª 82 +_‚þ¹µ 82 +þ¹µþ_ 82 +›þþ_ 82 +‚þ¹µþ 82 +‚þ¹µ 82 +Ÿþú_ 82 +_þ 82 +¹µþ_ 82 +þþ£_ 81 +øˆ 81 +½._ 80 +¿Šþ 80 +_·þ£ 80 +½. 80 +ú 79 +_žþ 79 +œþµþ_ 79 +² 79 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/middle_frisian.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/middle_frisian.lm new file mode 100644 index 0000000..b94ea1d --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/middle_frisian.lm @@ -0,0 +1,400 @@ +_ 60524 +e 20138 +n 10664 +t 8674 +i 7833 +a 7549 +o 7278 +r 6963 +n_ 5391 +s 5087 +d 4731 +t_ 4327 +l 4306 +e_ 4271 +en 4068 +k 3483 +m 3346 +g 2990 +er 2965 +en_ 2835 +y 2597 +w 2481 +h 2475 +j 2441 +_d 2375 +r_ 2250 +u 2059 +s_ 1921 +ie 1780 +_h 1725 +z 1710 +de 1666 +_m 1652 +_w 1629 +_i 1611 +et 1550 +te 1540 +b 1538 +. 1517 +er_ 1481 +in 1420 +an 1408 +p 1392 +f 1311 +, 1280 +,_ 1273 +k_ 1266 +._ 1258 +y_ 1238 +_z 1230 +oe 1162 +v 1144 +et_ 1138 +ne 1131 +ee 1125 +st 1120 +_o 1107 +_s 1107 +_e 1076 +_n 1068 +_b 989 +_t 988 +l_ 983 +oo 981 +ge 975 +je 963 +_g 952 +at 949 +me 946 +ij 943 +is 913 +he 899 +' 892 +aa 882 +el 870 +_v 864 +re 843 +ar 837 +_de 805 +on 800 +ke 796 +de_ 788 +ei 782 +_a 776 +_' 770 +le 744 +at_ 742 +it 741 +_k 738 +or 734 +an_ 729 +in_ 723 +da 715 +te_ 703 +_he 680 +_l 664 +H 661 +al 652 +_H 652 +a_ 650 +_da 648 +D 648 +d_ 646 +_D 643 +es 617 +g_ 608 +is_ 606 +æ 596 +_f 594 +'t 591 +_'t 584 +'t_ 583 +_me 580 +c 576 +_'t_ 576 +ri 571 +_en 564 +yn 563 +_en_ 559 +ze 538 +m_ 535 +om 535 +ik 522 +_de_ 522 +ed 521 +be 517 +wi 509 +ch 509 +ol 498 +ar_ 498 +ha 496 +_ne 495 +we 494 +ou 486 +nd 474 +ma 474 +ik_ 470 +J 459 +_ik 456 +_ik_ 451 +_J 451 +ll 450 +M 446 +li 443 +wa 442 +_M 442 +ien 435 +ro 432 +di 421 +nn 418 +ste 415 +wo 415 +yn_ 415 +_r 413 +_ha 411 +it_ 409 +tt 408 +ve 407 +S 404 +_j 399 +_S 398 +_in 395 +as 395 +der 395 +hi 389 +_al 388 +uw 384 +tte 384 +ng 381 +_wi 381 +nne 381 +het 380 +_het 378 +lle 376 +nt 374 +ns 373 +op 373 +je_ 367 +E 366 +ek 363 +B 363 +dat 362 +_B 362 +_ma 362 +_in_ 361 +_dat 359 +_wo 359 +ier 358 +og 357 +_E 354 +_ge 352 +dat_ 349 +ne_ 349 +eer 349 +het_ 348 +_het_ 348 +_is 348 +_dat_ 348 +ey 347 +W 346 +_W 343 +_te 339 +eg 337 +ra 335 +rs 335 +! 332 +zi 332 +gt 329 +_He 327 +He 327 +_be 324 +j_ 320 +ij_ 320 +u_ 319 +f_ 317 +_di 316 +; 315 +_we 315 +_is_ 314 +rt 313 +!_ 313 +;_ 312 +n. 311 +p_ 310 +la 310 +_wa 310 +ea 308 +_u 308 +pe 304 +ta 304 +il 301 +my 300 +ig 300 +n, 300 +n,_ 298 +iet 297 +sc 297 +ter 296 +sch 296 +oor 295 +no 294 +_my 293 +n._ 291 +ti 290 +_zi 289 +st_ 288 +el_ 283 +gen 282 +se 280 +K 279 +_oo 278 +ui 278 +e, 275 +ten 274 +net 274 +oon 274 +ho 274 +jn 273 +e,_ 273 +ijn 272 +ien_ 272 +ko 272 +N 271 +ni 271 +_N 269 +den 269 +za 268 +_net 267 +i_ 266 +wol 266 +een 264 +va 264 +am 264 +do 263 +ol_ 262 +le_ 261 +_te_ 260 +rd 260 +ke_ 259 +ey_ 259 +ers 258 +_K 255 +_ie 255 +ver 254 +to 254 +_hi 253 +nde 253 +: 253 +der_ 252 +jo 251 +net_ 251 +al_ 250 +_wol 250 +_p 250 +_no 250 +aar 248 +_za 245 +_net_ 245 +nk 242 +est 241 +om_ 241 +_va 241 +ak 241 +tj 239 +ae 238 +_op 237 +mo 236 +tr 236 +_st 233 +ier_ 233 +_ve 233 +mm 232 +T 231 +eu 229 +_ze 228 +:_ 228 +mi 228 +ag 227 +zo 227 +_ko 226 +vo 225 +_T 225 +nne_ 225 +F 224 +.. 224 +fo 224 +_F 223 +en, 223 +oe_ 222 +wie 222 +en,_ 221 +kk 221 +_ien 220 +on_ 218 +wol_ 218 +_fo 218 +I 217 +_do 216 +eit 214 +ei_ 214 +mme 214 +G 213 +_I 213 +as_ 213 +or_ 211 +A 211 +_G 210 +_A 210 +lle_ 209 +Da 208 +_Da 207 +_wol_ 207 +ren 206 +_ee 206 +e. 205 +van 205 +jen 205 +een_ 205 +_van 204 +kke 204 +en. 204 +O 204 +_vo 204 +V 203 +_O 203 +_V 203 +ken 203 +_mo 203 +ot 202 +ie_ 201 +ou_ 201 +ur 201 +tte_ 200 +em 200 +_van_ 199 +L 199 +van_ 199 +_zo 199 +op_ 199 +_L 197 +iet_ 196 +of 194 +ten_ 194 +oer 193 +_ien_ 193 +e._ 193 +oed 192 +hie 192 +zy 191 +en._ 191 +De 191 +_ver 191 +_ho 189 +_De 189 +oa 189 +den_ 188 +_zy 188 +lo 187 +dan 187 +nt_ 186 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/mingo.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/mingo.lm new file mode 100644 index 0000000..c18ce84 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/mingo.lm @@ -0,0 +1,400 @@ +_ 3156 +' 991 +a 829 +t 788 +k 788 +n 752 +e 640 +h 602 +ë 551 +s 495 +w 466 +ö 422 +y 403 +u 397 +'_ 368 +_n 330 +i 269 +. 269 +._ 240 +e' 238 +ô 219 +a' 209 +ne 209 +e_ 194 +_ne 184 +wa 172 +_k 164 +kw 162 +á 154 +e'_ 146 +_t 145 +'t 141 +" 141 +ë' 134 +ê 132 +_h 131 +é 129 +ak 129 +ne_ 126 +ta 123 +_ne_ 123 +at 121 +u' 121 +hu 118 +_u 108 +ka 107 +í 106 +nö 105 +N 103 +ö' 100 +hs 95 +ha 95 +te 94 +ya 93 +_ë 92 +kh 90 +'k 86 +ú 85 +æ 84 +ni 84 +'. 84 +wë 83 +ny 83 +sh 80 +_N 80 +'._ 76 +ö_ 76 +kë 72 +_" 71 +ën 70 +th 69 +yu 66 +_w 66 +ëh 66 +t_ 66 +ô_ 66 +Ne 65 +Ne' 65 +'s 64 +ne' 64 +"_ 64 +_. 63 +_._ 61 +Ne'_ 61 +, 60 +ne'_ 58 +në 58 +kwa 57 +_ne' 57 +öt 57 +a't 57 +ek 56 +s_ 56 +ët 55 +i' 55 +_hu 54 +T 54 +ë_ 54 +_s 54 +_Ne 53 +të 53 +tö 53 +_Ne' 53 +_ne'_ 53 +ht 53 +- 53 +ts 52 +ya' 52 +ë'_ 51 +_wa 51 +_Ne'_ 51 +'ö 50 +íy 50 +_ka 50 +as 50 +ní 49 +un 49 +ê_ 49 +ty 48 +hu_ 48 +ke 48 +u_ 48 +,_ 47 +yô 46 +he 46 +ye 46 +kê 45 +si 45 +nô 44 +khu 44 +a'k 44 +_a 43 +ák 43 +wat 42 +'ë 42 +nö' 42 +wá 42 +aw 41 +an 41 +we 41 +ôt 41 +i_ 41 +_kh 41 +tak 41 +_te 41 +ik 41 +_khu 40 +ës 40 +yö 40 +k_ 39 +khu_ 39 +yu' 38 +hö 38 +wën 38 +n- 38 +ëhs 38 +_ha 38 +wa' 38 +_n- 37 +sa 37 +? 37 +_T 37 +æ' 37 +_un 36 +hô 36 +wé 36 +ah 36 +_khu_ 35 +iy 35 +ëk 35 +ut 35 +ök 35 +öh 35 +te' 35 +u'_ 35 +_kë 34 +yô_ 34 +ha' 34 +st 34 +ti 34 +ta' 34 +u't 33 +ya't 33 +'t_ 33 +'ö_ 33 +akw 33 +ôk 33 +níy 32 +'ta 32 +ku 32 +ui 32 +_sh 32 +aa 31 +én 31 +ay 31 +ënö 31 +â 30 +se 30 +tw 30 +yë 30 +(_ 29 +_(_ 29 +_)_ 29 +us 29 +_ëhs 29 +( 29 +kö 29 +_ëh 29 +ae 29 +hë 29 +_) 29 +)_ 29 +_( 29 +sy 29 +) 29 +ëë 28 +ôn 28 +sk 28 +tá 28 +té 28 +tk 28 +ên 28 +kê_ 28 +a_ 28 +án 27 +_huik 27 +ön 27 +_hui 27 +kwé 27 +huik 27 +ék 27 +hui 27 +uik 27 +_na 27 +na 27 +a'_ 26 +uikê 26 +_ni 26 +." 26 +ææ 26 +wi 26 +huikê 26 +ikê 26 +nya 25 +."_ 25 +?" 25 +të' 25 +íyu 25 +awë 25 +sn 25 +në_ 24 +ö'_ 24 +ikê_ 24 +ekh 24 +'ke 24 +uikê_ 24 +?"_ 24 +tek 24 +êt 24 +', 24 +"N 23 +_ta 23 +'a 23 +hk 23 +tê 23 +tsi 23 +wö 23 +yu'_ 23 +_"N 23 +íyu' 23 +níyu 23 +a'ta 23 +é' 23 +níyu' 23 +shô 22 +wëní 22 +kwa' 22 +ëní 22 +kwë 22 +_u' 22 +ey 22 +ëníyu 22 +K 22 +ai 22 +_shô 22 +úw 22 +aö 22 +ëht 22 +ëníy 22 +kwe 22 +wëníy 22 +_he 22 +_te' 21 +ún 21 +s. 21 +nöh 21 +ëö 21 +_ëk 21 +'sh 21 +kë' 21 +htö 21 +H 21 +ata 21 +U 20 +'h 20 +_ha' 20 +ææ' 20 +ae_ 20 +a'ke 20 +ény 20 +unö 20 +we' 20 +wë' 20 +i'_ 20 +kës 20 +ya'ta 19 +es 19 +awëní 19 +hô_ 19 +uk 19 +awën 19 +hw 19 +ë'. 19 +ô' 19 +tö' 19 +sé 19 +ë'ë 19 +ë'._ 19 +'ëë 19 +hkw 19 +-a 19 +twa 19 +'kw 18 +he_ 18 +_K 18 +nöt 18 +hsa 18 +hsi 18 +ôni 18 +aya 18 +is 18 +ëë' 18 +kæ 18 +skw 18 +uw 18 +',_ 18 +e't 18 +kææ 18 +ka' 18 +nae 17 +shô_ 17 +sat 17 +niy 17 +ëts 17 +ath 17 +ye' 17 +í_ 17 +'ëë' 17 +'u 17 +_ët 17 +ës_ 17 +_kës 17 +_y 17 +kak 17 +ö'ö 17 +kat 17 +_th 17 +'ë_ 17 +út 17 +u'k 17 +_H 17 +tekh 17 +s._ 17 +wê 17 +_nae 17 +kwá 17 +_shô_ 17 +yê 17 +öte 16 +sha 16 +ke_ 16 +k. 16 +si' 16 +hö' 16 +yá 16 +hta 16 +kn 16 +_nae_ 16 +hse 16 +ké 16 +ë'ë_ 16 +unë 16 +nya' 16 +nae_ 16 +nê 16 +á' 16 +ás 16 +tô 16 +a's 16 +a'u 16 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/nepali.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/nepali.lm new file mode 100644 index 0000000..5d35076 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/nepali.lm @@ -0,0 +1,400 @@ +_ 7044 +f 2698 +] 1196 +g 933 +s 815 +l 781 +/ 698 +; 662 +k 645 +d 635 +]_ 630 +f_ 611 +sf 549 +f] 541 +n 526 +t 460 +o 412 +j 399 +f]_ 374 +L 365 +_; 364 +x 356 +_k 353 +{ 337 +b 323 +u 321 +' 303 +df 299 +sf] 290 +_l 283 +sf]_ 265 +g] 245 +G 232 +e 231 +| 227 +a 222 +/_ 222 +L_ 211 +_g 210 +c 207 +df_ 207 +{_ 207 +_c 201 +g_ 201 +kf 184 +f/ 177 +_u 171 +/f 168 +P 163 +_/ 162 +k| 161 +_s 161 +} 159 ++ 158 +h 151 +fn 150 +n] 145 +of 141 +tf 140 +: 136 +p 136 +t_ 134 +. 133 +_k| 133 +._ 133 +_e 131 +_d 131 +_f 129 +_._ 127 +_. 127 +n]_ 123 +;f 119 +lj 118 +O 118 +? 118 +q 118 +nf 118 +y 116 +_a 113 +m 111 +Ps 110 +r 110 +fg 106 +w 105 +sf_ 103 +lg 102 +g]_ 100 +gf 94 +_g] 91 +Psf 90 +x? 89 +fd 88 +fO 88 +_lj 85 +]s 85 +z 85 +s_ 84 +_p 82 +_sf 80 +D 79 +kl 78 +_;f 78 +f/_ 77 +cf 77 +}_ 76 +Psf] 76 +jf 76 +, 75 +fl 75 +\ 75 +_x 74 +kfn 74 +f{ 74 +_/f 74 +]k 73 +of] 73 +,_ 72 +v 72 +lt 72 +_cf 72 +_b 71 +O{ 70 +i 69 +xf 68 +]kf 68 +_/_ 68 +Psf]_ 68 +_h 67 +g]kfn 67 +g]k 67 +d_ 67 +g]kf 67 +O{_ 67 +]kfn 67 +_g]k 66 +g' 66 +_g]kf 66 +o_ 64 +" 64 +;b 63 +Gq 63 +f+ 63 +n_ 63 +fk 62 +sf/ 62 +/L 62 +_kl 62 +I 61 +T 61 +/s 61 +If 61 +dG 60 +_j 60 +]sf 60 +;_ 59 +u_ 59 +yf 59 +dGq 58 +fO{ 58 +af 57 +eP 57 +fs 57 +fO{_ 57 +fj 56 +f; 56 +qL 56 +l/ 55 +\_ 55 +;D 54 +dGqL 54 +GqL 54 +;+ 53 +g\ 53 +/sf 52 +nfO 51 +_kf 51 +ug 51 +pg 51 +:t 51 +fp 50 +_ug 50 +u/ 50 +lg_ 49 +ePs 49 +fdf 48 +cl 48 +nfO{_ 48 +nfO{ 48 +;/ 48 +_cl 47 +F 47 +'/ 47 +g\_ 47 +_r 47 +fo 47 +_eP 47 +]{ 46 +Z 46 +/L_ 46 +_f_ 45 +ePsf 45 +gd 45 +_;D 45 +if 45 +Gb 44 +lb 44 +Q 44 +_n 44 +fsf 44 +]sf] 43 ++; 43 +nL 43 +lx 43 +_t 43 +_: 42 ++;b 42 +_o 42 +fdf_ 42 +bf 42 +hf 42 +_lg 42 +ePsf] 41 +j_ 41 +ln 41 +ef 41 +/] 41 +_df 41 +To 40 +klg_ 40 +_klg_ 40 +]sf]_ 40 +klg 40 +_klg 40 +_u/ 40 +f{_ 40 +_ePs 40 +'g 40 +Gg 39 +:y 39 +_g\ 39 +f} 39 +kf_ 39 +:tf 38 +]{_ 38 +fpg 38 +b' 38 +hg 38 +g]{ 38 +jZ 38 +_;+ 37 +gs 37 +wf 37 +o{ 37 +GqL_ 37 +l_ 37 +qL_ 37 +dGqL_ 37 +gf_ 37 +]; 37 +_ePsf 36 +x' 36 +?_ 36 +! 36 +fx 35 +u| 34 +;d 34 +_lb 34 +fn_ 34 +_P 34 +fg_ 34 += 34 +bn 34 +Zj 34 +o; 34 +g]{_ 34 +_g\_ 34 +kIf 33 +dl 33 +kI 33 +ljZj 33 +jZj 33 +rf 33 ++u 33 +]d 33 +ljZ 33 +nL_ 32 +f+; 32 +fnL 32 +gL 32 +;/sf 32 +tf_ 32 +wfg 32 +_;/ 32 +Qm 32 +fb 32 +f;_ 32 +ld 32 +;/sf/ 32 +/sf/ 32 +_x' 32 +;/s 32 +;f+ 32 +_;f+ 32 +fu 32 +x?_ 32 +;f+; 31 +_k|:t 31 +s' 31 +_kI 31 +_k|: 31 +of]_ 31 +_kIf 31 +_;f+; 31 +]l 31 +k|: 31 +bg 31 +_;/s 31 +|: 31 +f+;b 31 +_;/sf 31 +|:t 31 +|] 31 +k|:t 31 +m_ 31 +;f+;b 31 +Jo 30 +k|wf 30 +|w 30 +|wf 30 +k|w 30 +km 30 +J 30 +k|wfg 30 +|wfg 30 +]t 30 +@ 30 +;f] 30 +b_ 29 +> 29 +kfn_ 29 +fn] 29 +gsf 29 +sf+ 29 +Zjf 29 +]kfn_ 29 +jif 29 +ji 29 +jf; 29 +_k|w 29 +fgd 29 +_k|wf 29 +Zjf; 29 +ljZjf 28 +jZjf; 28 +]n 28 +_z 28 +_s' 28 +_dG 28 +|]; 28 +_;d 28 +jZjf 28 +u|] 27 +gdGq 27 +gdG 27 +?n 27 +x'g 27 +|wfgd 27 +wfgd 27 +gdGqL 27 ++u|] 27 +f+u 27 +fgdG 27 +u|]; 27 ++u|]; 27 +wfgdG 27 +dfg 27 +a} 27 +_dGq 27 +f+u| 27 +fgdGq 27 +sf+u| 27 +_sf+u 27 +f+u|] 27 ++u| 27 +sf+u 27 +_sf+ 27 +x?n 27 +S 26 +_To 26 +]kfnL 26 +_! 26 +_T 26 +ul 26 +/f] 26 +fsf] 26 +af_ 26 +;s 26 +kfnL 26 +|:tf 26 +k|:tf 26 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/persian.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/persian.lm new file mode 100644 index 0000000..925ae28 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/persian.lm @@ -0,0 +1,400 @@ +_ 12318 +? 5938 +¤ 2613 +?_ 1815 +¢ 1745 +þ 1569 +ø 1546 +õ 1422 +- 1333 +÷ 1155 +ù 991 +¨ 841 +_ù 778 +ö 761 +î 693 +ü 664 +_ö 663 +ª 660 +¤? 631 +õ_ 624 +_? 601 +?¤ 598 +¥ 589 +_¤ 565 +?? 564 +ý 513 +¢_ 486 +_ü 473 +_ý 469 +þ? 459 +û 428 +ø_ 427 +_¢ 398 +î_ 392 +ó 390 +ê 384 +ö? 379 +÷? 361 +_ø 337 +_- 334 +> 327 +ú 324 +_ö? 319 +ù? 313 +_ø_ 308 +ð 305 +¤¢ 303 +¤_ 297 +?õ 290 +¨? 285 +¢÷ 272 +-_ 271 +S 266 +_ù? 265 +ô 259 +-¨ 255 +¡ 255 +??_ 255 +ý? 254 +¥? 250 +Y 246 +¤¢_ 245 +ì 243 +_ý? 238 +?¢ 234 +_¥ 229 +ò 229 +_S 228 +¤ø 216 +ø¤ 215 +?þ 215 +?¨ 214 +_¤¢ 214 +ñ 208 +þ?_ 207 +¢¤ 203 +?- 202 +_ô 199 +ù?_ 199 +öþ 195 +¨_ 190 +¨?_ 190 +_?? 189 +õ? 188 +. 188 +_¤¢_ 185 +_ñ 183 +?ø 181 +_öþ 180 +¢? 177 +* 176 +÷_ 176 +_ù?_ 174 +?û 173 +¤þ 172 +ª_ 170 +þõ 164 +ä 161 +¯ 158 +-¨? 156 +û_ 155 +¤?_ 155 +_¥? 152 +üõ 151 +ý¤ 150 +_¤? 146 +¥?_ 144 +þ¤ 143 +¢ø 141 +?¤_ 140 +*_ 138 +ü÷ 137 +?÷ 136 +¬ 133 +ùî 132 +_ý¤ 131 +-ª 131 +ø? 130 +?ú 129 +_. 129 +þó 129 +¡_ 128 +ù¢ 124 +¤õ 121 +¤- 120 +ùî_ 120 +_ùî 120 +_??_ 119 +ª? 119 +-¨?_ 119 +ã 118 +-? 118 +>_ 116 +öþ? 114 +ê_ 111 +¢þ 109 +_¥?_ 109 +_ü÷ 109 +_ùî_ 108 +_öþ? 107 +ö?¤ 107 +© 106 +_¢÷ 106 +.¢ 104 +?¥ 103 +_?¤ 103 +¤ê 103 +ó? 103 +þ¢ 103 +ñ? 102 +ªî 100 +?î 100 +?¤? 98 +ð_ 98 +ý?û 96 +¤ú 95 +öþ?_ 95 +_© 94 +§ 94 +Y_ 94 +_ö?¤ 93 +_ý?û 93 +¥ø 92 +øª 91 +_ñ? 91 +_öþ?_ 91 +?¨_ 90 +÷?_ 90 +óþ 90 +õ?_ 90 +ü- 90 +øõ 89 +: 89 +ªî_ 88 +ü÷? 88 +öø 88 +_ù¢ 87 +-ê 86 +þ÷ 85 +_öø 83 +, 82 +þõ_ 82 +þ¨ 82 +?¢_ 80 +® 80 +?¤þ 79 +_ü÷? 79 +¢ª 77 +??? 77 +øþ 76 +_-? 75 +÷î 75 +?ª 75 +?ì 75 +¤î 74 +_¤ø 73 +ä_ 73 +þóþ 73 +û? 73 +óþõ 72 +þóþõ 71 +ù¤ 71 +?> 71 +ê? 70 +_?¤_ 70 +_.¢ 70 +ø¡ 69 +à 69 +_§ 68 +¥ø¤ 68 +þóþõ_ 67 +_ü- 67 +¤øª 67 +óþõ_ 67 +õû 67 +¤ê_ 67 +¨õ 67 +¤õ_ 66 +?-_ 65 +ù÷ 65 +ý?¤ 65 +öøþ 64 +¤þ? 64 +¬_ 64 +?ð 63 +?-¨ 63 +ø- 63 +_ý?¤ 62 +ø?_ 62 +ø¤_ 62 +_-¨ 61 +õþ 61 +øþóþõ 60 +øþóþ 60 +øþó 60 +?ù 60 +øªî 60 +_¢ø 60 +¤øªî 60 +_öøþ 60 +-ª? 60 +ì_ 60 +¨¤ 60 +ý¤? 60 +÷þ 59 +öøþóþ 59 +¯? 59 +_¢? 59 +öøþó 59 +¢ª_ 59 +¤?? 58 +¤?¥ 58 +_üõ 58 +.- 58 +?¡ 58 +ø÷ 57 +í 57 +¢¤î 57 +?¤?_ 57 +þ?¤ 57 +ù- 57 +üõ_ 56 +ñ?¨ 56 +øõ_ 56 +?¤þ? 56 +ú? 56 +î¤ 56 +¤?¢ 56 +õû_ 55 +ô? 55 +ª?¢ 55 +_öøþó 55 +-ª?¢ 55 +þ_ 55 +ö?¤þ 55 +¤î_ 55 +S¤ 55 +üþ 54 +_S¤ 53 +øªî_ 53 +_ù¤ 53 +ò¢ 53 +¤ò 53 +¤øªî_ 53 +ø¡_ 52 +¢÷? 52 +û¤ 52 +üþ? 52 +õ> 52 +-õ 52 +¢¤? 52 +üð 52 +ì? 52 +_í 52 +î? 52 +üó 52 +??¤ 52 +ð÷ 51 +¤ò¢ 51 +-þ 51 +_ý¤? 51 +¡? 50 +_¢¤ 50 +¢¤î_ 50 +.-¨ 50 +ö?õ 50 +ë 50 +_ô? 50 +ø¢ 50 +_ñ?¨ 49 +.¢÷ 49 +÷¤ 49 +ý?¤? 49 +ú- 48 +_üð 48 +_ö?¤þ 48 +¤þ?_ 48 +ò¢_ 48 +ûù 48 +ú?_ 48 +¤ò¢_ 47 +ê¤ 47 +â 47 +.-¨? 47 +_¢þ 47 +>÷ 47 +úª 47 +÷?õ 47 +£ 47 +?¤þ?_ 47 +?ûù 47 +¤¯ 46 +_.- 46 +_ý?¤? 46 +õ¤ 46 +õó 46 +-¤ 46 +_üþ 46 +¥þ 46 +¤ð 45 +ôþ 45 +_üó 45 +ö?- 45 +§þ 45 +_ë 45 +f 45 +õ- 44 +_ù- 44 +úõ 44 +_üþ? 44 +ü-ª 44 +-î 44 +ð¢ 44 +ö?¤þ? 44 +õª 44 +.-¨?_ 44 +¨õ_ 44 +¤ª 44 +_-¨? 44 +¤?î 43 +ä? 43 +é 43 +?õ_ 43 +_¤øªî 43 +þª 43 +?ê 43 +?î_ 43 +_¤øª 43 +¯_ 43 +¤¨ 43 +þ?? 42 +Y? 42 +¥_ 42 +÷÷ 42 +÷õ 42 +_¥ø 42 +þ¨? 42 +¢õ 42 +/ 42 +_â 42 +???_ 42 +_¥ø¤ 42 +_ù÷ 42 +s 42 +¢÷÷ 42 +ö?-¨ 41 +÷ø 41 +ù÷? 41 +?* 41 +S¤ò¢ 41 +_ö?õ 41 +ñþ 41 +_.-¨ 41 +îþ 41 +÷¢ 41 +ùõ 41 +S¤ò 41 +ªø 41 +ý?¤?_ 40 +¤úª 40 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/quechua.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/quechua.lm new file mode 100644 index 0000000..0a08735 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/quechua.lm @@ -0,0 +1,400 @@ +_ 5766 +a 4900 +n 1941 +i 1666 +u 1384 +s 1032 +t 995 +y 939 +h 929 +k 915 +q 909 +p 882 +a_ 847 +an 821 +r 783 +m 740 +c 705 +l 695 +ta 637 +ch 613 +ay 587 +qa 557 +pa 490 +ha 486 +e 474 +ma 457 +o 441 +na 434 +ku 411 +j 409 +un 367 +w 358 +in 353 +, 345 +,_ 344 +cha 318 +ar 317 +n_ 315 +as 291 +wa 289 +ta_ 269 +ll 259 +man 255 +_k 248 +._ 243 +. 243 +nt 227 +am 224 +pi 222 +la 222 +ka 217 +ac 214 +ni 214 +at 213 +aq 213 +i_ 208 +ri 207 +qa_ 204 +una 204 +y_ 192 +aj 192 +_p 192 +is 188 +_m 181 +lla 175 +ach 174 +rq 173 +us 172 +an_ 171 +_ka 171 +ata 169 +rqa 165 +sq 163 +hu 162 +sp 161 +_w 157 +nk 157 +hay 157 +_s 156 +sqa 155 +ki 153 +kun 152 +_c 152 +al 150 +nta 149 +ap 147 +ant 146 +yk 146 +ay_ 144 +spa 141 +hi 137 +_ch 136 +_n 136 +ya 135 +' 134 +j_ 133 +uy 132 +ra 132 +a,_ 132 +a, 132 +ti 130 +_a 125 +nc 125 +kuna 122 +s_ 121 +su 121 +ak 121 +_ma 118 +ana 118 +ari 115 +_t 114 +ama 114 +chi 114 +ñ 113 +a._ 111 +a. 111 +nch 111 +iy 111 +all 110 +aw 110 +_r 110 +anta 109 +ayk 109 +na_ 109 +chay 108 +sa 104 +_wa 104 +si 103 +chu 102 +pa_ 101 +acha 101 +_cha 101 +pi_ 101 +qan 100 +_pa 99 +_q 97 +aj_ 97 +awa 97 +ank 95 +nku 95 +im 94 +q_ 92 +uk 92 +C 92 +mu 90 +tu 89 +J 89 +_ni 88 +taj 87 +_J 87 +nin 86 +_chay 86 +u_ 86 +_C 84 +wan 83 +nta_ 81 +_j 81 +mant 80 +ut 79 +in_ 79 +ik 79 +manta 79 +asq 79 +yt 78 +n, 78 +asqa 78 +n,_ 78 +pay 78 +li 77 +yn 77 +nq 76 +yta 76 +ic 76 +up 76 +_Ch 75 +yku 75 +Ch 75 +he 75 +hay_ 74 +nan 74 +ina 74 +ur 73 +er 72 +S 72 +arq 72 +or 72 +_l 71 +_u 71 +aq_ 70 +os 70 +yp 70 +anc 69 +man_ 69 +mi 69 +ich 68 +_i 68 +st 67 +_S 67 +arqa 66 +it 66 +anch 66 +ru 66 +aku 65 +pu 65 +ña 65 +alla 64 +mp 64 +sqa_ 64 +'a 64 +ayku 63 +es 63 +A 63 +ia 63 +_man 63 +_Cha 61 +Cha 61 +taj_ 60 +api 60 +_ll 60 +wi 60 +ayp 60 +aman 59 +g 58 +anku 58 +yki 57 +ima 57 +yni 57 +oj 57 +mana 57 +anta_ 57 +_su 57 +uc 56 +isp 56 +ispa 56 +uch 56 +M 56 +ir 56 +_h 55 +nqa 55 +kuy 55 +ayt 54 +_M 54 +b 54 +_y 53 +_mana 53 +: 53 +uku 53 +:_ 53 +nm 53 +au 52 +ayta 52 +io 52 +qo 51 +an,_ 51 +apa 51 +spa_ 51 +erq 51 +_wi 51 +erqa 51 +_sa 51 +an, 51 +el 50 +um 50 +ana_ 50 +han 50 +il 50 +on 49 +chay_ 49 +sta 49 +_D 49 +D 49 +iku 49 +aqa 49 +che 48 +en 48 +yta_ 48 +Ma 47 +P 47 +_lla 47 +_Je 47 +yq 47 +Je 47 +ita 47 +rqan 47 +ypi 46 +har 46 +Jes 46 +_Jes 46 +ios 46 +ayq 46 +Dio 46 +un_ 46 +kus 46 +_Dio 46 +taq 46 +_Dios 46 +_Ma 46 +_Di 46 +Dios 46 +Di 46 +d 46 +kan 45 +Chay 45 +oq 45 +_Chay 45 +_pay 45 +upa 45 +mun 45 +ata_ 44 +_tu 44 +nis 44 +re 44 +paq 44 +yo 44 +ej 44 +qay 43 +ncha 43 +ha_ 43 +_A 43 +I 43 +_kan 43 +_nis 43 +_P 43 +nman 43 +nma 43 +ataj 42 +ara 42 +ku_ 42 +nata 42 +nat 42 +i, 41 +tin 41 +qh 41 +t' 41 +orq 41 +nki 41 +_ru 41 +_ku 41 +i,_ 41 +ip 40 +ham 40 +usq 40 +_ya 40 +qank 39 +orqa 39 +ayn 39 +mana_ 39 +ray 39 +ym 39 +uma 39 +_pu 39 +par 39 +kay 39 +n. 38 +qa,_ 38 +n._ 38 +sus 38 +aypi 38 +usqa 38 +qanku 38 +ill 38 +qa, 38 +was 38 +pa, 38 +pa,_ 38 +asp 38 +qa._ 37 +_mu 37 +paj 37 +amp 37 +hin 37 +uti 37 +rin 37 +_im 37 +_ima 37 +ja 37 +_ri 37 +rqa_ 37 +taq_ 37 +qa. 37 +sh 36 +spa,_ 36 +cha_ 36 +spa, 36 +achi 36 +una_ 36 +rqank 36 +jt 36 +K 36 +amu 36 +aspa 35 +_Jesu 35 +Jesus 35 +nispa 35 +ki_ 35 +waw 35 +ko 35 +ne 35 +esus 35 +int 35 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/rumantsch.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/rumantsch.lm new file mode 100644 index 0000000..75fece2 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/rumantsch.lm @@ -0,0 +1,400 @@ +_ 10888 +a 3490 +e 2268 +i 2196 +s 2169 +n 1961 +t 1555 +r 1510 +l 1281 +u 1249 +a_ 1155 +c 1060 +d 954 +o 815 +s_ 744 +g 726 +m 686 +h 620 +p 617 +n_ 559 +v 493 +_s 480 +er 476 +ch 469 +_d 457 +in 455 +da 418 +_c 404 +r_ 388 +_e 377 +. 358 +_p 340 +as 333 +l_ 328 +, 327 +._ 320 +_i 320 +,_ 315 +la 313 +en 312 +sc 310 +an 301 +ta 300 +_da 285 +f 282 +_t 268 +_a 262 +nt 259 +_m 252 +un 248 +ra 247 +i_ 247 +na 245 +ma 245 +ia 241 +ar 234 +sch 228 +b 228 +da_ 217 +es 214 +ai 213 +st 212 +' 209 +e_ 208 +as_ 208 +er_ 200 +t_ 199 +re 199 +_l 195 +al 193 +_n 193 +el 192 +tg 192 +te 188 +z 187 +ha 180 +_f 180 +sa 174 +_da_ 172 +ve 169 +ei 168 +_v 165 +at 165 +ss 161 +is 161 +_ch 161 +on 160 +la_ 158 +cu 158 +ad 158 +he 156 +in_ 147 +va 147 +_in 146 +gl 145 +ns 141 +ur 140 +ü 140 +u_ 138 +ts 138 +pe 136 +li 134 +gi 133 +et 133 +de 132 +ig 132 +or 130 +ti 129 +il 127 +d_ 126 +che 123 +ut 122 +us 122 +cha 121 +di 120 +ia_ 120 +_b 118 +_la 117 +na_ 116 +ain 115 +per 115 +to 115 +_cu 113 +_sc 112 +se 111 +ls 109 +- 108 +iu 108 +ca 107 +si 104 +ir 102 +rt 102 +ie 102 +_g 102 +un_ 102 +nd 101 +av 101 +ni 100 +q 99 +au 97 +ls_ 97 +ll 96 +qu 96 +_pe 96 +le 96 +rs 95 +pa 95 +ri 95 +_ma 94 +_per 93 +am 93 +eg 92 +_r 92 +gn 92 +me 92 +pi 91 +an_ 91 +en_ 91 +ga 91 +ent 90 +hi 90 +_e_ 90 +it 89 +ta_ 88 +ter 87 +ns_ 86 +iv 86 +igl 86 +a. 85 +em 85 +I 85 +chi 84 +_en 84 +int 84 +ue 83 +su 82 +tt 82 +a, 82 +a,_ 82 +o_ 82 +_ve 82 +a._ 82 +_q 81 +_qu 80 +ge 80 +" 80 +_la_ 80 +ar_ 80 +vi 79 +gl_ 79 +tu 78 +ng 78 +ro 76 +mi 76 +sta 75 +ed 75 +lla 74 +ei_ 73 +_o 73 +ic 73 +el_ 73 +_il 73 +_in_ 72 +g_ 72 +pr 71 +nu 70 +ina 70 +_h 69 +scha 68 +mai 68 +pl 68 +il_ 68 +os 68 +ha_ 68 +be 67 +uo 67 +cun 67 +ra_ 67 +_pa 65 +ts_ 64 +s. 64 +co 64 +_u 64 +fi 64 +_I 63 +sa_ 63 +s._ 63 +_re 62 +ün 62 +_nu 62 +? 62 +S 62 +_se 61 +no 61 +nt_ 61 +E 61 +tr 61 +mp 60 +igl_ 60 +_su 60 +_st 60 +ess 60 +im 60 +zi 59 +?_ 59 +nc 59 +_E 58 +_- 58 +_cun 58 +_te 58 +_sa 58 +ant 58 +main 58 +eu 57 +ssa 57 +-_ 57 +iun 57 +_-_ 57 +aint 56 +op 56 +al_ 56 +dal 56 +j 56 +ama 55 +_tg 55 +ua 55 +M 55 +per_ 55 +tsc 54 +nta 54 +tsch 54 +um 54 +fa 54 +za 54 +_di 54 +pia 54 +_per_ 54 +T 54 +_M 53 +ne 53 +era 53 +A 53 +que 53 +_dal 53 +cr 53 +_de 53 +lla_ 53 +_che 52 +h' 52 +_me 51 +ot 51 +_pr 51 +_pl 51 +_sch 51 +ch' 50 +_S 50 +opi 50 +ou 50 +tta 50 +mo 50 +ada 50 +ba 50 +_an 49 +top 49 +id 49 +è 49 +he_ 49 +C 49 +va_ 49 +uto 49 +ins 48 +topi 48 +L 48 +ir_ 48 +ist 48 +c_ 48 +_il_ 48 +P 48 +ss_ 48 +ag 47 +_no 47 +res 47 +las 47 +_vi 46 +s, 46 +schi 46 +_en_ 46 +tg_ 46 +s,_ 46 +_si 46 +_que 45 +_T 45 +az 45 +'i 45 +cun_ 44 +_fa 44 +_mi 44 +utop 44 +utopi 44 +sche 44 +_C 44 +ur_ 44 +tge 44 +po 44 +es_ 44 +x 44 +nz 44 +_L 44 +_cun_ 44 +man 44 +_ch' 43 +_fi 43 +pu 43 +ell 43 +opia 43 +_igl 43 +_ig 43 +sp 43 +topia 43 +ava 42 +egn 42 +che_ 42 +on_ 42 +ci 42 +_P 42 +ev 42 +ond 41 +_" 41 +à 41 +us_ 41 +_ha 41 +D 40 +_co 40 +etg 40 +'e 40 +las_ 40 +est 40 +ura 40 +uel 39 +ed_ 39 +vo 39 +gia 39 +bu 39 +mu 39 +nn 39 +gli 39 +_A 39 +lu 39 +cha_ 39 +ul 38 +mal 38 +_ün 38 +ina_ 38 +_bu 38 +_ca 38 +_ü 38 +uc 38 +nts 38 +tra 38 +_tu 37 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/sanskrit.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/sanskrit.lm new file mode 100644 index 0000000..e21b871 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/sanskrit.lm @@ -0,0 +1,400 @@ +a 15017 +_ 14975 +h 5028 +i 3820 +t 2976 +s 2788 +r 2599 +| 2437 +n 2432 +aa 2276 +ha 2007 +m 1982 +a_ 1802 +v 1799 +d 1768 +u 1629 +y 1599 +_| 1470 +|_ 1470 +e 1403 +k 1371 +sh 1330 +ra 1243 +p 1213 +va 1152 +A 1134 +ya 1120 +ma 1097 +na 1091 +ar 1080 +ta 1054 +M 1050 +. 1047 +am 1037 +an 1006 +|| 967 +||_ 965 +_|| 965 +_||_ 963 +at 962 +M_ 946 +as 910 +_s 882 +o 848 +b 844 +i_ 827 +aM 764 +aM_ 685 +c 630 +ch 629 +sa 623 +N 616 +ad 612 +H 601 +pa 595 +H_ 584 +g 580 +_n 579 +l 554 +bh 552 +hi 547 +ka 542 +it 536 +ii 535 +ama 519 +_|_ 505 +e_ 477 +_p 475 +dh 475 +av 469 +ak 445 +aH 444 +da 440 +aH_ 439 +ay 437 +j 437 +_na 432 +ana 430 +hh 428 +ti 426 +ara 425 +aa_ 410 +_k 394 +shh 389 +_v 388 +_sa 381 +.h 379 +ah 369 +_b 368 +h_ 363 +.h_ 363 +cha 362 +haa 361 +_t 358 +ri 352 +sha 345 +ap 333 +vi 330 +is 329 +^ 321 +o_ 321 +_m 320 +ai 311 +_d 311 +la 302 +na_ 301 +.n 298 +ava 295 +al 294 +_sh 291 +ja 288 +a. 280 +aan 277 +ish 274 +aN 273 +aya 273 +ash 266 +ha_ 265 +ga 264 +st 255 +ni 255 +ii_ 254 +hu 253 +Na 253 +R 248 +R^ 248 +^i 247 +R^i 247 +a.n 243 +th 241 +_c 240 +_ch 239 +maa 238 +bha 237 +vaa 233 +ab 228 +ir 226 +\ 226 +ita 223 +uu 222 +dha 220 +har 218 +_a 216 +_bh 216 +nam 212 +u_ 212 +he 212 +m.h_ 211 +m. 211 +m.h 211 +ur 210 +es 209 +ata 208 +te 206 +yaa 205 +_ma 204 +esh 202 +aka 200 +id 199 +pr 199 +aha 198 +hy 198 +T 197 +aat 197 +_OM_ 196 +OM 196 +_O 196 +_OM 196 +OM_ 196 +O 196 +ti_ 195 +ari 194 +raa 193 +ag 192 +_y 192 +aas 190 +_ta 190 +_j 189 +I 189 +_na_ 187 +am.h_ 185 +am.h 185 +am. 185 +_pa 183 +iv 182 +de 182 +ada 178 +nd 178 +_cha 177 +_h 176 +ati 175 +taa 173 +ev 172 +nt 171 +rii 171 +ishh 170 +ya_ 168 +_vi 166 +ast 165 +tr 164 +abh 164 +kh 162 +ala 160 +tha 160 +apa 160 +asa 158 +naa 158 +_nam 156 +ru 156 +A_ 155 +_ka 154 +aar 153 +_pr 152 +_g 151 +pra 150 +ham 150 +hha 149 +aana 149 +di 149 +ra_ 147 +ik 146 +.a 144 +yat 143 +ks 143 +hA 143 +hya 143 +ksh 143 +ut 142 +sy 141 +nama 140 +_va 140 +.\ 140 +paa 140 +han 139 +eva 138 +U 138 +mi 138 +_r 136 +_ja 136 +asy 135 +hr 135 +sya 134 +cha_ 132 +rv 132 +tv 130 +asya 130 +kar 130 +ho 129 +yo 129 +in 128 +adh 127 +yA 127 +va_ 126 +su 125 +_ya 125 +shha 124 +pu 124 +R^it 123 +sta 123 +mu 123 +^it 123 +ty 123 +_nama 121 +ac 120 +rii_ 120 +ach 120 +aNa 119 +tas 119 +shi 119 +iva 119 +hav 119 +tra 118 +var 118 +par 118 +haM 117 +aad 117 +kaa 117 +hch 117 +mas 117 +ai_ 117 +hc 117 +sar 116 +aam 116 +_bha 115 +_pra 114 +et 114 +haM_ 113 +aay 113 +aj 113 +ye 113 +o. 113 +An 111 +arii 111 +t.h 110 +t. 110 +ath 110 +t.h_ 109 +man 109 +te_ 108 +o.a 108 +hara 108 +rA 108 +rva 108 +tva 108 +asta 108 +up 108 +shr 107 +daa 104 +me 104 +dr 104 +ram 104 +arii_ 102 +_ni 102 +arv 102 +iH 102 +hit 101 +ras 101 +aga 101 +Am 101 +mA 101 +ba 101 +amas 100 +tu 100 +yaM 100 +ant 99 +ud 99 +uk 98 +iH_ 98 +yaM_ 98 +kha 98 +au 98 +ira 97 +shhT 97 +rah 97 +hT 97 +hhT 97 +D 96 +_sar 96 +re 96 +eshh 95 +sarv 94 +amaa 94 +and 94 +arva 94 +_ra 93 +_dh 93 +tt 92 +tad 92 +hm 92 +raM_ 91 +dev 91 +raM 91 +C 91 +ani 91 +_sarv 90 +atha 89 +Ad 89 +chi 89 +tA 88 +sarva 88 +avi 88 +taM 87 +hava 87 +anaa 86 +vA 86 +dd 86 +nA 85 +Ar 85 +hv 85 +taM_ 85 +dhi 84 +ksha 84 +ip 84 +ma_ 84 +_sha 84 +ati_ 83 +yai 83 +vat 83 +At 83 +kR 82 +kR^ 82 +bhi 82 +_shr 82 +to 82 +ta_ 82 +br 82 +ek 82 +kR^i 82 +tat 81 +nta 81 +hma 81 +aaya 80 +tam 80 +en 80 +us 79 +bra 79 +ke 79 +kt 79 +ddh 79 +mo 79 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/scots.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/scots.lm new file mode 100644 index 0000000..7aac457 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/scots.lm @@ -0,0 +1,400 @@ +_ 11688 +e 3223 +a 2469 +t 2269 +i 1928 +n 1903 +r 1414 +o 1406 +h 1369 +s 1249 +l 929 +n_ 890 +_t 862 +_a 843 +d 818 +e_ 798 +th 704 +w 661 +he 625 +an 612 +t_ 606 +u 592 +_th 575 +c 508 +s_ 471 +the 470 +, 469 +- 458 +in 455 +m 445 +,_ 440 +b 434 +g 429 +er 409 +ee 408 +_the 407 +k 402 +an_ 402 +f 385 +_w 378 +he_ 376 +the_ 364 +_an 362 +_o 360 +y 358 +_the_ 354 +_s 353 +_an_ 342 +a_ 335 +r_ 327 +_b 316 +d_ 303 +i_ 278 +en 277 +p 270 +ei 245 +A 236 +wa 232 +_A 231 +re 229 +in_ 229 +ui 218 +oo 217 +le 217 +ai 216 +et 212 +ti 209 +it 209 +_f 206 +te 204 +_a_ 203 +_m 202 +ha 200 +as 193 +on 188 +at 184 +_i 183 +_wa 183 +_c 182 +o_ 180 +or 178 +_h 176 +_g 169 +ch 165 +A_ 159 +_l 158 +_A_ 157 +st 156 +_d 155 +_ti 148 +. 148 +._ 146 +ke 144 +ti_ 143 +-- 143 +_o_ 142 +ow 142 +--- 140 +ed 138 +---- 138 +_r 137 +as_ 137 +y_ 136 +er_ 136 +----- 136 +ir 135 +aa 135 +la 131 +een 130 +ae 129 +_ti_ 128 +ra 126 +es 125 +nd 124 +de 120 +h_ 120 +ie 120 +ar 119 +ll 119 +nt 118 +ot 118 +en_ 115 +ma 115 +eet 113 +her 112 +el 112 +is 112 +' 112 +at_ 111 +ic 109 +se 108 +or_ 106 +wu 104 +me 104 +ne 103 +fo 102 +on_ 101 +was 99 +_was 98 +et_ 98 +ri 98 +_e 97 +_ma 97 +v 97 +_n 97 +! 97 +li 97 +ht 93 +hi 92 +_wu 92 +ng 91 +ro 91 +it_ 90 +ck 90 +_fo 90 +tha 90 +k_ 89 +il 89 +cht 86 +eet_ 86 +_p 86 +we 86 +_was_ 85 +was_ 85 +rt 84 +ed_ 83 +ter 83 +id 83 +ga 82 +; 82 +;_ 81 +ther 79 +tt 76 +air 76 +e, 75 +un 75 +ho 75 +for 74 +ge 74 +_st 73 +_y 72 +_he 72 +wh 71 +_on 71 +sh 70 +z 70 +e,_ 69 +bi 68 +_tha 68 +wui 67 +!_ 67 +ad 67 +een_ 66 +l_ 66 +ts 66 +_for 66 +n, 66 +_wh 65 +re_ 65 +be 65 +eh 64 +hat 64 +ns 64 +br 64 +g_ 64 +ui_ 64 +rr 64 +wui_ 63 +ni 63 +_wui 62 +ay 62 +s, 62 +pe 61 +n,_ 61 +bo 61 +al 61 +ye 61 +_bi 60 +oot 60 +na 60 +ang 60 +s,_ 59 +es_ 59 +ill 58 +that 58 +_wui_ 58 +nn 58 +eh_ 58 +oa 57 +han 57 +_that 56 +_br 56 +ca 56 +_ga 56 +ng_ 56 +um 55 +hat_ 55 +oon 55 +od 55 +for_ 55 +no 55 +ree 55 +_for_ 54 +_le 54 +ht_ 54 +ot_ 54 +_k 53 +rd 53 +ki 53 +aw 53 +nd_ 53 +_on_ 53 +_it 53 +ik 53 +t, 53 +_be 52 +that_ 52 +ve 52 +rn 52 +'s 51 +au 51 +co 51 +ich 51 +to 51 +lo 51 +t,_ 51 +ea 51 +tee 51 +lan 50 +fi 50 +_at 50 +am 50 +_in 50 +ere 50 +ur 50 +le_ 50 +nt_ 49 +'s_ 49 +hin 49 +yi 49 +hr 49 +ts_ 49 +_ca 48 +" 48 +ta 48 +cht_ 48 +-_ 48 +_as 47 +T 47 +ang_ 47 +lei 46 +_ma_ 46 +tr 46 +_ro 46 +fe 46 +ma_ 46 +icht 46 +_as_ 46 +der 46 +cl 46 +e- 45 +n- 45 +thr 45 +ba 45 +m_ 45 +st_ 45 +rt_ 45 +_u 45 +do 45 +_T 45 +im 44 +_se 44 +sk 44 +_la 44 +eik 44 +bit 43 +ike 43 +B 43 +kee 43 +tte 43 +di 43 +eed 43 +_B 42 +_aa 42 +her_ 42 +da 42 +ff 42 +tu 42 +ie_ 42 +_cl 42 +_ba 42 +oot_ 42 +bu 41 +eike 41 +oc 41 +hu 41 +_thr 41 +ther_ 41 +_co 41 +aa_ 41 +so 41 +_me 41 +H 41 +_H 40 +ke_ 40 +ert 40 +lu 40 +ist 40 +si 40 +iz 40 +ar_ 39 +uc 39 +thi 39 +ad_ 39 +ru 39 +owe 39 +gi 38 +_bit 38 +_do 38 +int 38 +bl 38 +ld 38 +_at_ 38 +lt 38 +ac 38 +_ha 38 +ae_ 38 +rs 37 +here 37 +ei_ 37 +han_ 37 +p_ 37 +is_ 37 +eth 37 +fa 37 +_sk 37 +ll_ 37 +ss 36 +bra 36 +wha 36 +gl 36 +ck_ 36 +pl 36 +lin 36 +ir_ 36 +ab 36 +_ther 36 +_da 35 +ce 35 +rin 35 +_oo 35 +rl 35 +wee 35 +and 35 +sa 35 +_yi 35 +_bra 35 +'d 35 +ds 35 +_bo 35 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/scots_gaelic.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/scots_gaelic.lm new file mode 100644 index 0000000..3008957 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/scots_gaelic.lm @@ -0,0 +1,400 @@ +_ 12634 +a 5353 +h 3268 +i 2898 +n 2792 +e 1651 +r 1563 +d 1455 +_a 1425 +c 1245 +n_ 1236 +s 1165 +l 1152 +an 1121 +t 980 +ai 979 +g 962 +u 905 +ch 902 +ha 836 +h_ 833 +a_ 829 +ea 821 +o 794 +dh 726 +an_ 711 +b 639 +m 585 +na 514 +nn 506 +ac 498 +r_ 495 +s_ 482 +ir 480 +ach 466 +id 458 +_an 450 +_c 427 +th 403 +à 388 +he 383 +in 379 +bh 367 +idh 358 +ad 342 +_n 341 +il 332 +nn_ 323 +_t 322 +_d 319 +ar 317 +e_ 311 +dh_ 307 +_an_ 303 +_b 302 +_na 294 +air 289 +ig 279 +. 275 +ir_ 272 +ag 272 +_ai 272 +, 270 +gu 269 +,_ 269 +._ 265 +ean 264 +ch_ 261 +f 259 +? 258 +_s 255 +ann 250 +ra 241 +ei 241 +_a_ 241 +ha_ 241 +d_ 238 +- 235 +_m 231 +gh 230 +hea 228 +le 226 +_f 224 +ui 223 +is 223 +as 218 +adh 218 +l_ 216 +g_ 208 +ài 207 +ò 207 +hai 205 +cha 205 +air_ 204 +na_ 201 +inn 198 +tha 190 +C 189 +G 188 +ann_ 187 +_ag 186 +_air 186 +eac 185 +_g 185 +_na_ 184 +ach_ 184 +_C 183 +us 183 +_ch 183 +la 182 +_G 182 +each 181 +us_ 178 +al 178 +gus 176 +gus_ 176 +_th 169 +_air_ 168 +_agus 167 +agus_ 167 +_agu 167 +agus 167 +agu 167 +ta 164 +aid 163 +hi 163 +hd 163 +chd 160 +T 157 +A 156 +ic 152 +_T 152 +adh_ 150 +idh_ 148 +mh 147 +?_ 146 +ar_ 145 +oi 144 +da 143 +aidh 143 +_bh 139 +ean_ 138 +sa 138 +ig_ 138 +_r 136 +_A 134 +ì 134 +te 134 +achd 131 +hu 131 +_e 130 +aig 130 +_l 130 +_ann 129 +ain 127 +ne 127 +dhe 125 +_dh 125 +àid 123 +o_ 121 +hl 119 +acha 119 +ga 118 +àidh 118 +on 118 +it 117 +aidh_ 116 +de 115 +nan 115 +ua 115 +_ann_ 115 +ich 115 +il_ 114 +m_ 114 +eil 114 +ri 112 +at 112 +ma 111 +li 109 +ao 109 +re 109 +inn_ 108 +_tha 107 +fh 106 +as_ 106 +bh_ 106 +nan_ 103 +lea 103 +lt 103 +S 103 +a? 103 +a?_ 102 +io 102 +E 101 +am 101 +' 100 +_a? 100 +igh 100 +_a?_ 99 +_gu 99 +idhe 99 +t_ 99 +se 99 +si 98 +ba 97 +ù 97 +tha_ 96 +bha 95 +B 94 +is_ 94 +u_ 94 +_B 94 +_i 93 +ile 92 +aic 91 +hei 91 +ia 90 +ho 89 +Th 88 +ath 88 +_Th 88 +rt 87 +ib 87 +Gàid 86 +_Gài 86 +_Gà 86 +Gài 86 +òr 86 +Gà 86 +Gàidh 86 +_Gàid 86 +had 85 +ibh 85 +_fh 85 +p 84 +ad_ 83 +_? 83 +_E 83 +hd_ 82 +dhea 82 +chd_ 82 +ear 81 +ith 81 +_tha_ 80 +h- 79 +eal 78 +hean 78 +sg 77 +rea 77 +_S 76 +ais 75 +ll 75 +han 74 +hà 74 +achd_ 74 +ead 74 +idhea 73 +am_ 72 +dha 72 +_nan 71 +_nan_ 71 +hadh 71 +gh_ 71 +ail 70 +hui 70 +Ch 69 +eachd 69 +h. 69 +aich 69 +hli 69 +chai 69 +om 68 +fa 68 +chad 68 +I 67 +h._ 67 +_Ch 67 +tea 67 +nea 66 +chadh 66 +achad 66 +rai 66 +lig 66 +haid 66 +dea 66 +rt_ 65 +àr 65 +dhl 65 +ana 64 +eann 64 +Ei 64 +le_ 64 +hn 64 +ilt 64 +uid 64 +_fa 63 +_Tha 63 +Tha 63 +ob 63 +_si 62 +ro 62 +cu 62 +ainn 62 +un 62 +dhli 61 +idhli 61 +lean 61 +idhl 61 +àidhl 61 +hlig 61 +dhlig 61 +in_ 60 +_à 60 +st 60 +rr 60 +_cu 60 +hr 60 +_aig 60 +bhe 59 +i_ 59 +aigh 59 +Tha_ 59 +è 59 +_ri 59 +_Tha_ 59 +lb 58 +che 58 +ran 58 +nac 58 +haidh 58 +hadh_ 58 +aig_ 58 +Gh 58 +ilea 58 +_Gh 58 +lte 58 +_le 58 +ru 58 +àidhe 57 +_I 57 +ilte 57 +eadh 57 +M 56 +hlig_ 56 +L 56 +chu 56 +nach 56 +_ma 56 +lig_ 56 +h,_ 55 +th_ 55 +ibh_ 55 +_aig_ 55 +D 55 +atha 55 +_Ei 55 +h, 55 +gu_ 54 +_gu_ 54 +im 54 +eil_ 54 +eu 53 +_M 53 +Al 53 +irt 53 +_L 53 +iad 53 +sea 52 +lba 52 +Alba 52 +F 52 +Alb 52 +uai 52 +ich_ 52 +_F 51 +ilean 51 +has 51 +tai 51 +each_ 50 +eacha 50 +har 50 +ni 50 +_de 50 +irt_ 50 +n,_ 50 +mha 50 +n, 50 +_e_ 50 +ide 49 +neach 49 +neac 49 +ur 49 +rd 49 +_h 49 +hean_ 49 +oc 49 +eò 49 +te_ 49 +han_ 49 +on_ 49 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/swahili.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/swahili.lm new file mode 100644 index 0000000..56090b4 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/swahili.lm @@ -0,0 +1,400 @@ +_ 16483 +a 9342 +i 5293 +a_ 4071 +u 2730 +k 2609 +n 2351 +w 2076 +m 1928 +e 1866 +h 1800 +o 1775 +wa 1743 +l 1486 +s 1419 +i_ 1401 +t 1399 +_k 1306 +y 1100 +_w 969 +li 945 +wa_ 911 +z 891 +_wa 890 +ka 834 +ku 799 +r 770 +b 733 +an 727 +ma 723 +o_ 711 +_m 707 +na 698 +ya 675 +ha 672 +g 602 +al 580 +d 570 +at 560 +am 554 +_n 549 +_ku 549 +ik 543 +_h 515 +ya_ 514 +A 494 +is 487 +_y 485 +hi 474 +na_ 471 +_ya 471 +ta 468 +sh 456 +ali 449 +j 426 +u_ 423 +ki 418 +e_ 402 +p 401 +ti 401 +_wa_ 399 +f 392 +_ya_ 390 +ba 390 +ri 385 +ng 385 +il 380 +c 358 +hu 356 +_na 356 +ni 355 +za 354 +zi 351 +ia 344 +_na_ 343 +_a 336 +in 327 +_ma 326 +ch 322 +mb 317 +ika 314 +. 311 +._ 309 +_ka 307 +as 306 +ak 306 +ati 301 +, 300 +ka_ 296 +,_ 294 +_u 292 +kw 286 +ili 278 +K 274 +en 271 +si 266 +_kw 262 +la 261 +ni_ 261 +ma_ 261 +_s 258 +kwa 258 +ar 256 +ut 245 +za_ 245 +nd 242 +mba 241 +_kwa 239 +_z 234 +li_ 233 +un 233 +ny 230 +it 229 +se 229 +yo 227 +ia_ 222 +M 221 +sa 221 +kat 217 +_K 214 +_i 213 +ika_ 213 +ana 212 +ish 212 +kati 206 +_ha 204 +on 201 +ai 200 +I 198 +aa 196 +um 195 +im 190 +v 188 +mu 187 +amb 187 +sha 185 +em 183 +fa 181 +zi_ 180 +di 179 +mi 178 +_M 178 +us 176 +_ki 176 +ha_ 175 +iw 172 +ama 172 +_kat 168 +_kati 168 +_hi 166 +_l 166 +ra 166 +kwa_ 165 +la_ 164 +W 164 +ja 163 +U 163 +N 163 +amba 161 +ao 161 +_za 160 +ji 160 +B 157 +iwa 155 +tik 155 +wal 155 +le 155 +tika 154 +ge 153 +lis 153 +tu 152 +atika 152 +to 152 +atik 152 +uw 152 +_kwa_ 151 +A_ 151 +ke 150 +S 147 +tika_ 145 +aj 145 +we 144 +cha 144 +bi 141 +az 140 +er 139 +ek 138 +katik 138 +ez 138 +uwa 137 +kut 135 +_al 134 +_B 134 +ad 134 +mu_ 133 +_ali 133 +rik 132 +_W 131 +ba_ 131 +kuw 131 +me 130 +ali_ 128 +kuwa 128 +ema 127 +wan 127 +bu 126 +sem 126 +_A 125 +ir 125 +ata 125 +iz 124 +_hu 124 +ay 124 +ul 124 +af 123 +iki 122 +ema_ 121 +da 120 +ti_ 120 +sema 119 +aka 118 +sema_ 118 +te 118 +uz 117 +yo_ 117 +_v 117 +io 116 +iy 115 +uta 115 +ani 115 +_wal 115 +he 115 +if 114 +_la 114 +ab 114 +go 112 +_za_ 111 +ama_ 111 +sa_ 111 +pa 110 +_t 110 +zo 110 +nge 110 +wam 109 +wali 108 +ua 107 +ur 106 +_c 106 +ise 105 +_ch 105 +isem 105 +ho 105 +ye 104 +iyo 104 +E 104 +el 104 +mo 103 +ung 103 +eri 103 +_wali 103 +_b 102 +mba_ 102 +ari 101 +ita 101 +isema 100 +ot 99 +_la_ 99 +uk 99 +ao_ 99 +di_ 99 +sha_ 99 +ini 99 +kuwa_ 98 +uwa_ 98 +ana_ 98 +lise 98 +lisem 98 +uli 97 +shi 97 +ga 96 +iwa_ 96 +fu 96 +T 96 +R 95 +_il 95 +wak 94 +aw 94 +isha 94 +ri_ 93 +_am 93 +ara 92 +_cha 92 +aji 92 +_ili 91 +ifa 91 +O 90 +_p 90 +uh 90 +iri 90 +chi 90 +asi 89 +po 89 +a. 89 +ong 89 +azi 88 +_j 88 +_kut 88 +eny 88 +nc 88 +a._ 88 +ko 87 +uu 87 +id 87 +w_ 87 +no 87 +P 86 +ah 86 +ina 86 +rika 86 +_Bw 85 +H 85 +gu 85 +uo 85 +Bw_ 85 +_Bw_ 85 +_se 85 +Bw 85 +ib 84 +_S 84 +kam 84 +hi_ 84 +nya 84 +si_ 83 +a, 82 +no_ 81 +pi 81 +ok 81 +i. 81 +ip 81 +kwam 81 +i._ 81 +amba_ 80 +dh 80 +end 80 +ani_ 80 +a,_ 79 +wamb 79 +kwamb 79 +_sh 79 +eza 79 +nz 79 +wi 79 +_kwam 79 +wamba 79 +alis 78 +_kuw 78 +ngo 78 +ap 77 +_N 77 +any 77 +ili_ 77 +C 77 +WA 76 +vy 76 +wana 76 +_hiy 75 +Wa 75 +hiyo 75 +nch 75 +_hiyo 75 +de 75 +_kuwa 75 +ing 75 +hiy 75 +vi 75 +isha_ 74 +es 74 +atu 74 +_Wa 74 +nchi 74 +aki 74 +lim 73 +da_ 73 +ini_ 73 +ash 73 +ala 73 +i, 73 +ano 73 +i,_ 72 +_kam 71 +_wan 71 +ano_ 71 +mw 71 +nde 71 +ji_ 71 +ion 70 +_amb 70 +ndi 70 +_Ka 70 +eza_ 70 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/tagalog.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/tagalog.lm new file mode 100644 index 0000000..bc87d38 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/tagalog.lm @@ -0,0 +1,400 @@ +_ 10664 +a 6092 +n 3421 +i 2332 +g 2149 +ng 1488 +an 1332 +g_ 1308 +ng_ 1243 +t 1155 +a_ 1138 +o 1137 +l 1105 +s 1067 +k 1035 +_n 957 +m 909 +y 801 +ang 787 +u 767 +ang_ 683 +p 682 +na 670 +_a 634 +la 596 +. 572 +in 561 +r 559 +sa 545 +_s 502 +._ 487 +ma 476 +ka 473 +_na 464 +b 462 +_m 458 +al 448 +d 445 +pa 414 +n_ 412 +at 394 +ak 393 +h 378 +ya 358 +_k 356 +ag 350 +ni 344 +_p 339 +_sa 335 +o_ 328 +ta 308 +_an 307 +iy 300 +sa_ 296 +_ang 294 +_ang_ 293 +t_ 290 +ay 286 +ga 283 +on 280 +it 275 +_sa_ 265 +ala 258 +_ng 256 +am 252 +_i 248 +_pa 248 +i_ 243 +na_ 243 +an_ 240 +e 239 +_ma 237 +_ka 235 +iya 231 +y_ 229 +il 228 +li 228 +w 226 +_ni 225 +_na_ 224 +_ng_ 220 +as 214 +ba 207 +si 206 +" 195 +ti 195 +ha 186 +, 179 +ar 178 +ing 173 +ra 173 +A 172 +ki 168 +ong 167 +_b 167 +ap 166 +,_ 162 +ong_ 161 +ko 159 +ay_ 159 +un 157 +ul 155 +yo 154 +to 152 +_l 150 +ah 148 +is 147 +hi 147 +_t 146 +lan 145 +ama 142 +niy 139 +at_ 138 +_niy 138 +aka 136 +wa 136 +niya 135 +_niya 135 +ab 134 +- 134 +di 133 +_si 132 +"_ 131 +aw 129 +_d 126 +_A 126 +yan 123 +ya_ 122 +ata 120 +a. 120 +gi 120 +P 120 +ing_ 118 +um 115 +o. 113 +aki 113 +ri 113 +ik 112 +nd 112 +ila 111 +mo 110 +da 110 +a._ 110 +in_ 109 +la_ 107 +ali 106 +S 106 +man 105 +ig 105 +iya_ 105 +s_ 104 +_ak 104 +_at 103 +_h 102 +yon 102 +asa 101 +ina 101 +_P 101 +n. 99 +N 98 +aa 98 +ga_ 97 +_mo 97 +_ba 97 +_" 95 +ito 94 +bi 94 +yang 94 +n._ 93 +pag 92 +lang 92 +yang_ 92 +_la 92 +o._ 90 +K 90 +_at_ 90 +tu 88 +_S 88 +ara 87 +nga 87 +ro 85 +apa 83 +rr 82 +lam 82 +lo 81 +nan 81 +_N 80 +aman 79 +aha 78 +mg 78 +mga 78 +mga_ 78 +_mga_ 78 +_mg 78 +_mga 78 +_K 78 +siy 77 +kan 76 +it_ 76 +san 76 +d_ 75 +ad 75 +di_ 74 +tin 74 +' 74 +ati 73 +siya 73 +kin 72 +M 72 +lang_ 71 +mo_ 70 +_mo_ 70 +ako 70 +uma 70 +_pag 69 +pi 69 +l_ 68 +_siy 68 +rrr 68 +_siya 67 +ula 67 +_M 66 +Pa 66 +iyo 66 +mi 66 +bu 66 +mu 65 +no 65 +pu 65 +nag 65 +ung 65 +Na 65 +ot 64 +_Na 64 +niya_ 64 +iyan 64 +ku 64 +k_ 63 +go 62 +awa 62 +ip 61 +_Pa 61 +lu 61 +_di 60 +pan 60 +_ta 60 +ini 60 +isa 60 +nt 60 +iyang 60 +_iyo 59 +_iy 59 +on_ 59 +tan 59 +mang 59 +aba 59 +gan 59 +ut 58 +I 58 +hin 58 +nak 58 +an. 57 +akin 57 +_r 57 +han 57 +Ka 57 +_ay 57 +_ako 56 +may 56 +iyon 56 +rrrr 55 +Sa 55 +aga 55 +to_ 55 +nit 55 +_ko 54 +er 54 +ib 54 +ari 54 +ana 54 +ili 54 +an._ 54 +ahi 54 +au 54 +ala_ 54 +gk 53 +pa_ 53 +_is 53 +rin 53 +ilan 52 +_kan 52 +_Ka 52 +_it 52 +_Sa 51 +king 51 +ko_ 51 +_nak 51 +gin 51 +_ay_ 50 +bo 50 +_iyon 50 +amang 50 +'y 49 +os 49 +mang_ 49 +_pa_ 49 +kat 49 +a, 49 +An 48 +Ma 48 +ny 48 +mag 48 +_ku 48 +_ito 48 +_ha 47 +yong 47 +? 47 +aking 47 +T 47 +ni_ 47 +yong_ 47 +_An 47 +king_ 47 +_akin 46 +sang 46 +_nag 46 +kas 46 +_aki 46 +_ni_ 46 +ayo 45 +kit 45 +'y_ 45 +mat 45 +_Ma 45 +lal 45 +ot_ 45 +nya 44 +ban 44 +ndi 44 +oo 44 +_u 44 +ngi 44 +_hi 44 +sang_ 44 +B 43 +su 43 +may_ 43 +rrrrr 43 +p_ 43 +ita 43 +wal 43 +ika 43 +abi 43 +aan 43 +_may 43 +lama 42 +naka 42 +mal 42 +_I 42 +_ri 42 +alan 42 +any 42 +im 42 +_pu 42 +ai 42 +wala 41 +anya 41 +a,_ 41 +_B 41 +ndi_ 41 +as_ 41 +pat 41 +po 41 +nang 41 +_mag 41 +laman 40 +lala 40 +kal 40 +g- 40 +.. 40 +ir 40 +! 40 +uk 40 +gu 39 +ito_ 39 +ro_ 39 +_g 39 +_da 39 +_isa 39 +_lam 39 +ilang 39 +kanya 39 +w_ 39 +kany 39 +agk 38 +pal 38 +ka_ 38 +_naka 38 +siya_ 38 +isan 38 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/tamil.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/tamil.lm new file mode 100644 index 0000000..977cd1b --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/tamil.lm @@ -0,0 +1,400 @@ +_ 11468 +Õ 2697 +Ô 2533 +´ 1960 +» 1786 +½ 1249 + 1103 +Ù 990 +£ 976 +Ø 849 +¡ 847 +¨ 831 +¿ 821 +À 794 +¾ 758 +§ 750 +Á 721 +¹ 715 +¶ 713 +. 702 +£_ 671 +× 655 +â 648 +Æ 625 +._ 611 +ç 601 +Å 571 +¯ 557 +»Õ 556 +É 524 +_É 520 +¢ 518 +_½ 492 +Ç 489 +_× 488 +Þ 484 +_Ç 482 +¤ 461 +Ä 442 +¼ 418 +ÿ 416 +¥ 403 +§_ 398 +½Ô 373 +_Ø 368 +ª 360 +Í 359 +_Í 349 +»Ô 348 +´Õ 342 +à 337 +_ 331 +õ 331 +¨_ 323 +_¼ 321 +¡´ 320 +_´ 310 +Õ¿ 308 +Ü 299 +¢» 294 +Ó 292 +´Ô 292 +ÿ» 290 +Õ§ 288 +¡Þ 284 +â_ 279 +ý 271 +õ´ 266 +ÂÕ 265 +_» 265 +¾Ô 241 +_¾ 234 +´ª 232 += 231 +± 229 +¤½ 227 +== 221 +¶Õ 218 +»_ 218 +Õ§_ 213 +=== 211 +Õ_ 210 +==== 201 +ª_ 199 +´_ 198 +ÀÕ 197 +===== 191 +, 188 +ؽ 188 +¿Õ 187 +º 186 +_¶ 184 +,_ 184 +à 183 +Ô¯ 181 +¿_ 179 +Ô¨ 178 +å 172 +´ª_ 171 +ì 169 +ÙÁ 168 +¢»Õ 165 +¿Ô 165 +Ô_ 165 +ç¡ 164 +È 161 +Þ_ 160 +ͨ 160 +_ͨ 157 +« 156 +_È 156 +§Á 152 +Ô´ 152 +Ù» 151 +Ð 150 +_Ð 149 +ä 149 +ö 146 +ÕÅ 146 +Ø½Ô 145 +¯´ 143 +Ö 142 +׶ 142 +ÁÔ 142 +½Õ 140 +Á_ 139 +Ô§ 138 +_Éç 138 +Éç 138 +¶Ô 137 +Õ¨ 137 +Æ_ 136 +¢â 133 +_׶ 132 +ÔÆ 128 +¡´Õ 128 +ÀÔ 127 +¥¹ 127 +_Ë 127 +Ë 127 +_ؽ 127 +ÕÀ 125 +öÓ 125 +ÄÕ 124 +ÆÔ 122 +ÅÕ 121 +Þ£ 120 +Õç 119 +¼Ô 119 +×½ 119 +´Ù 119 +_å 118 +¯_ 118 +£. 117 +´ÕÅ 116 +»Õ¿ 115 +ÂÔ 115 +_ÂÕ 113 +â. 113 +×» 113 +£._ 112 +¡Þ_ 112 +ÕÙ 111 +Õ¡ 111 +ÙÄ 109 +×´ 109 +é 109 +â._ 108 +_½Ô 107 +Õ´ 106 +¤_ 105 +ÆÕ 104 +' 104 +½¹ 103 +ç_ 102 +¹Ô 102 +Ø´ 101 +¼Õ 100 +Éÿ 100 +_Éÿ 99 +_×» 99 +ÔÀ 98 +Éÿ» 98 +æ 98 +_×½ 97 +Å_ 97 +Ô» 97 +_Éÿ» 97 +Ô¨_ 97 +¹_ 97 +ß 96 +±Å 96 +×´Ô 96 +»Ô¨ 95 +¡Þ£ 94 +Õ¿_ 94 +Ø» 94 +ø 94 +Ø 93 +í 93 +_Ø½Ô 93 +¾Õ 93 +Õ¨_ 92 +ÿ»_ 91 +ÁÕ 91 +_Éç¡ 90 +Éç¡ 90 +Ðç 90 +ÕÆ 90 +_Ðç 90 +ÿ»Õ 90 +Ù¹ 89 +_´Ô 89 +_Ðç_ 88 +_¼Ô 88 +Ðç_ 88 +ì_ 86 +ç¡´ 86 +ÅÔ 86 +ÿâ 85 +¥à 85 +¯´ª 84 +¨Æ 84 +¨ì 83 +Ô¥ 83 +÷ 83 +_Þ 83 +´Ä 82 +à_ 81 +Ô´_ 81 +¨. 80 +_¾Ô 80 +¿Õ§ 80 +² 80 +ÕÁ 80 +Ä_ 79 +´ÙÄ 79 +_½¹ 79 +¨Å 79 +Ô£ 79 +«¶ 78 +¡_ 78 +¨._ 77 +_¶Õ 77 +§ÁÔ 77 +_¼Õ 77 +ë 77 +Åâ 76 +Þ£_ 75 +ÔÆ_ 75 +Ù¾ 75 +¯ 75 +Ù 74 +çÿ 73 +ýà 72 +è 72 +¨ì_ 71 +Ô§_ 71 +´ë 71 +¥Ü 71 +§Ù 70 +»Õ§ 70 +§ÙÁ 70 +£½ 69 +Ù»_ 69 +ªÄ 69 +ç¡Þ 69 +Ó_ 68 +Ôõ 68 +ؾ 67 +_Ø´ 67 +Õ¢ 66 +ÄÔ 66 +»Ô¨_ 66 +࣠66 +_Ç» 66 +Ç» 66 +Ô¹ 66 +Î 66 +¿Õ§_ 65 +Ôâ 65 +_»Õ 64 +¯. 64 +¹¢ 63 +Õ¥ 63 +Ô¡ 63 +_×´ 63 +_Î 63 +Ù´ 62 +´ÄÕ 62 +Õ¿Ô 62 +¯._ 61 +Éÿ»Õ 61 +_½Õ 61 +_×»Ô 61 +×»Ô 61 +Ôõ´ 61 +½¥ 60 +ÿ»Õ¿ 60 +_ä 60 +_Éÿ»Õ 60 +Ô¾ 60 +Ôç 59 +×¶Ô 59 +¡Þ£_ 59 +¤ä 59 +_ÇÙ 58 +ÿâ_ 58 +ÙÅ 58 +Ç 58 +ÇÙ 58 +Éÿ»Õ¿ 58 +ºÕ 58 +»À 57 +½Ô¯ 57 +¹£ 57 +ýº 57 +_Ç 57 +æ£ 56 +ÔÁ 56 +_×¶Ô 55 +? 55 +ý¹ 54 +ÃÕ 54 +ÙÆ 54 +»Õç 54 +_×´Ô 54 +´ÕÅâ 53 +»Õ¿_ 53 +_À 53 +ÕÅâ 53 +¡´ÕÅ 53 +ç¡´Õ 52 +ÇÀ 52 +ÙÄ_ 52 +× 51 +Ü_ 51 +'_ 51 +_ÇÀ 51 +Ô 51 +ͨì 51 +Âç 51 +î 51 +â¡ 51 +_ͨì 51 +À_ 51 +Õ¿Õ 51 +ÙÀ 51 +_ɧ 50 +ɧ 50 +½ý 50 +»Õ§_ 50 +×½Ô 50 +±ÅÕ 50 +»¾ 49 +à£_ 49 +Ôà 49 +õ´ª 49 +´¥ 49 +»Õ_ 49 +»ÕÀ 48 +¶Ô§ 48 +ç£ 48 +Õ¡´ 48 +Õ¤ 48 +ÕØ 48 +À£ 48 +ÀÕ¿ 48 +_Éç¡´ 47 +æ£_ 47 +ê 47 +ͨì_ 47 +׶ԧ 47 +Éç¡´ 47 +Â_ 47 +_ͨì_ 47 +?_ 46 +Ø¿ 46 +Ô¿ 46 +_Ø» 46 +¹õ 46 +_Ù 46 +õ´ª_ 46 +è£ 45 +´ÙÄ_ 45 +¢Ù» 45 +¢Ù 45 +»Ù 45 +_×½Ô 44 +½Ü 44 +Ô£_ 44 +ÕÆÕ 44 +´Ø 44 +á 44 +´£ 44 +½Ôâ 44 +ÁÔ£ 44 +Á. 44 +_׶ԧ 43 +´ë¡ 43 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/thai.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/thai.lm new file mode 100644 index 0000000..f10fedc --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/thai.lm @@ -0,0 +1,400 @@ +_ 6290 +Ò 5252 +à 4377 +¹ 3920 +¡ 3050 +è 2984 +Í 2657 +§ 2522 +Ñ 2454 +Á 2369 +é 2304 +à 2158 + 1981 +Ç 1908 +Õ 1693 +Å 1543 +Ô 1443 +´ 1422 +· 1398 +µ 1398 +» 1301 +Ë 1245 +Ð 1239 +¤ 1210 +º 1181 +Ê 1081 +¨ 1045 +ä 978 +Òà 951 +¾ 907 +ª 892 +èÒ 829 +á 795 +¡Ò 735 +ã 722 +¡Òà 710 +¢ 691 +Ò 688 +× 668 +ͧ 595 +. 588 +ç 553 +Ø 543 +ÃÑ 532 +Õè 528 +ÃÐ 522 +»Ã 522 +·Õ 477 +Ù 452 +·Õè 451 +èÍ 443 +¹Ò 441 +Ó 422 +Ò§ 419 +éÒ 414 +ì 388 +¹_ 378 +Ãà 367 +ÒÁ 360 +° 354 +Ѻ 349 +Ò_ 347 +éÍ 345 +»ÃÐ 340 +Çè 337 +ÃÒ 337 +Áè 336 +ÇèÒ 336 +à» 334 +Ò¹ 333 +Ñé 332 +¡Ã 328 +´é 325 +Ö 322 +_à 320 +ç¹ 314 +À 313 +ÁÒ 299 +ѧ 297 +Ò¡ 297 +×Í 296 +äÁ 295 +Ñ° 293 +ÃÑ° 293 +×è 290 +â 289 +äÁè 288 +¸ 285 +ã¹ 280 +¼ 273 +è§ 268 +¹Ò 268 +é¹ 266 +¾Ã 263 +ѹ 263 +³ 263 +áÅ 256 +¹¡ 254 +ËÒ 253 +§¡ 252 +×èÍ 251 +ÁÕ 251 +ä´ 248 +­ 248 +ä´é 248 +¨Ð 248 +»ç¹ 247 +à»ç¹ 247 +»ç 247 +à»ç 247 +Í¡ 245 +ÇÒ 245 +ãË 244 +¶ 244 +ªÒ 243 +µÔ 241 +_á 240 +¡Ñ 238 +È 237 +_¡ 236 +µè 234 +« 227 +éÇ 225 +é§ 221 +É 216 +¡ 214 +ä 213 +Õ 211 +Ñé§ 211 +ÃÁ 211 +¢Í 210 +Ô¹ 209 +èÇ 206 +Õé 202 +ÅÐ 202 +˹ 201 +¹Ñ 201 +_¹ 200 +µÃ 197 +Ëé 196 +§_ 193 +Á¹ 191 +Ðà 191 +ÀÒ 188 +Í 188 +ÒÇ 186 +¢Í§ 184 +¹Õ 184 +ãËé 183 +¤Ç 183 +ÃÕ 181 +§à 180 +¡Å 179 +áÅÐ 178 +èÒ§ 177 +èÒ_ 176 +Ãä 176 +_¾ 176 +¤ÇÒÁ 174 +¹µ 174 +ÇÒÁ 174 +¤ÇÒ 174 +Ñ´ 172 +Ô´ 172 +ÇèÒ_ 171 +¾Ãà 167 +¨Ò 167 +͹ 167 +Òµ 167 +¹Õé 167 +¾Ãä 166 +¡ç 166 +¤Ã 165 +¹à 165 +è¹ 163 +ºÒ 162 +¢é 161 +§ã 161 +Õ_ 161 +ì_ 154 +ËÅ 154 +Á× 154 +éͧ 151 +¹¡Òà 151 +¹¡Ò 151 +ä» 150 +Ñ¡ 150 +é_ 148 +ÃÒ 147 +µÑ 146 +¹· 146 +ÅÑ 146 +Â_ 146 +ྠ145 +Åé 140 +à¡ 139 +¨Ò¡ 139 +àÁ 138 +ÃÔ 138 +¾Å 137 +Ã× 136 +·Ñ 135 +¡Ñº 134 +Ò¡ 133 +_à 132 +ºÃ 132 +§ä 132 +Ãà 131 +à· 130 +Åè 129 +ÒµÔ 129 +_· 128 +¡Ô 128 +µÃÕ 128 +ÃѺ 128 +Õ¡ 128 +àË 127 +¹Í 127 +µé 126 +_¹Ò 126 +ªÒµÔ 126 +ÅÒ 126 +ªÒµ 126 +¹Ç 126 +Òà 126 +_áÅ 125 +§¹ 124 +§¤ 124 +¡ÒÃà 124 +ÒÃà 124 +ÍÁ 123 +Ò¤ 122 +  122 +áµ 122 +àÊ 121 +ÇÑ 121 +Ñé¹ 120 +ÃÃÁ 120 +Ò· 119 +¹µÃ 119 +èÒÇ 118 +áµè 118 +§· 117 +ǹ 117 +ÂÑ 117 +Á¹µÃ 117 +¹µÃÕ 117 +Á¹µ 117 +Á¹µÃÕ 117 +ÃÍ 116 +Ùé 116 +_¹Ò 116 +àÁ× 116 +°Á¹ 115 +àà 115 +ÃÑ°Á¹ 115 +ËÁ 115 +ࢠ115 +Ñ°Á 115 +Í. 115 +Ñ°Á¹µ 115 +ÃÑ°Á 115 +°Á¹µ 115 +Ñ°Á¹ 115 +°Á¹µÃ 115 +°Á 115 +_áÅÐ 113 +éà 113 +Ãè 113 +èÁ 112 +㨠112 +_Ê 112 +¹Ñé 111 +Ô» 111 +¹Ñé¹ 111 +èà 111 +èä 110 +_Í 110 +Âà 110 +_¨ 110 +Ò¨ 109 +»ÃÒ 108 +¹Ò¡ 108 +_Ë 107 +Ñ­ 107 +éÒ¹ 107 +¨Ñ 106 +§¡Ò 106 +_¤ 106 +§¡Òà 105 +Ç 105 +Ôµ 105 +¹é 105 +ÒÅ 103 +´Â 102 +è_ 102 +ÃÐà 102 +àÍ 102 +¹¹ 102 +ÍÒ 101 +â´ 100 +µéÍ 100 +ªè 100 +_ä 99 +ÇÅ 99 +µéͧ 99 +â´Â 99 +Ã_ 98 +Ъ 98 +¾Ñ 98 +»ÃÐà 98 +¡à 97 +Öè§ 97 +¡_ 97 +Öè 97 +Òª 97 +é¹_ 96 +ÅÔ 96 +Ñ°º 94 +Ò¾ 94 +ÃÑ°º 94 +¼Ù 94 +°º 94 +Âè 93 +¹ä 93 +·Ò 93 +°ºÒ 92 +ÅèÒ 92 +Å. 92 +Ñ°ºÒ 92 +¡Ñ¹ 92 +Ñ°ºÒÅ 92 +§Ã 92 +ÃÑ°ºÒ 92 +ºÒÅ 92 +°ºÒÅ 92 +Ö§ 92 +.Í 91 +¢éÒ 91 +á 91 +_¾Å 90 +ÍÂè 90 +¾Å. 90 +Íà 90 +ÍÂèÒ 90 +ÂèÒ 90 +¡ÃÐ 89 +.Í. 89 +ÂèÒ§ 89 +Õé_ 89 +ÍÂèÒ§ 89 +Âѧ 89 +ÊØ 89 +µèÍ 88 +ͺ 88 +_â 88 +Å.Í 87 +èͧ 87 +ÃЪ 87 +Áà 87 +ÂÇ 87 +Åѧ 87 +¾Å.Í. 87 +Å.Í. 87 +¹Õé_ 87 +à´ 87 +Á¡ 87 +¼Ùé 87 +ÇÔ 87 +¾Å.Í 87 +»ÃЪ 87 +»Ñ 87 +' 86 +ÊÔ 86 +Êè 86 +Áèä 86 +_¾Å. 86 +·Ò§ 86 +ÇÁ 85 +¡à 85 +§ 85 +._ 85 +¡ÃÑ 85 +ÍÀ 85 +ªÇ 84 +ÒÐ 84 +¹éÒ 84 +¡ÃÑ° 84 +ÀÔ 84 +·Ó 84 +ËÒà 84 +_¾Å.Í 84 +ÍÍ 83 +§Ê 83 +ÍÀÔ 83 +äÁèä 83 +ѵ 82 +»ÃÒ 82 +¤¹ 82 +Í_ 82 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/ukrainian-koi8_r.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/ukrainian-koi8_r.lm new file mode 100644 index 0000000..fea9994 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/ukrainian-koi8_r.lm @@ -0,0 +1,400 @@ +_ 21726 +Ï 4832 +Á 4080 +É 3253 +¦ 2775 +Î 2747 +× 2642 +Ô 2481 +Å 2373 +Ò 2066 +Ë 1929 +Ä 1806 +Ó 1797 +Ì 1760 +Õ 1605 +Ð 1347 +Í 1345 +Ñ 1061 +Ú 1060 +Á_ 971 +Ï_ 965 +É_ 916 +_× 902 + 881 +_Ð 869 +Å_ 847 +Ø 843 +¦_ 810 +Ç 760 +_Î 696 +. 676 +Þ 654 +Ê 647 +_Ó 623 +" 621 +_Ú 606 +ÎÁ 582 +_Ä 565 +Ö 543 +_Ô 514 +ËÁ 480 +._ 476 +ÔÉ 464 +Ï× 459 +צ 457 +Õ_ 457 +×_ 451 +À 450 +Ñ_ 449 +_Ë 443 +È 438 +ÒÏ 431 +Û 428 +_Í 419 +ÎÅ 418 +ÐÏ 414 +ÓÔ 413 +¤ 410 +ÔÏ 400 +ÇÏ 396 +Ø_ 394 +ÔØ 377 +ÌÉ 375 +ËÏ 373 +ÒÁ 358 +ÎÏ 356 +Ê_ 354 +á 354 +_ 350 +ÔÁ 346 +, 343 +ÏÄ 341 +ÉÔ 340 +ÏÌ 336 +ÏÇ 333 +×Á 331 +à 328 +Á× 326 +,_ 323 +ÒÉ 322 +ÄÏ 321 +ÌÏ 319 +¦Ä 318 +ÎÉ 317 +÷ 314 +_ÐÏ 314 +î 312 +×É 310 +ÏÒ 310 +ÅÒ 305 +ï 295 +ÏÍ 295 +Φ 294 +_ÎÁ 289 +_ÎÅ 288 +×Ï 288 +Ý 287 +ÅÎ 282 +ÁÌ 282 +ÎÁ_ 280 +ÚÁ 274 +ô 273 +ËÉ 268 +_¦ 268 +§ 267 +ÐÒ 266 +"_ 264 +ÏÇÏ 254 +ÓÑ 252 +ÁÔ 252 +_" 251 +ÔØ_ 251 +ÎÅ_ 249 +Í_ 248 +ð 246 +ÔÉ_ 245 +I 245 +ÉÊ 244 +_Ò 241 +¤_ 239 +_ÄÏ 239 +ÄÁ 235 +Ï 235 +é 233 +_Ñ 232 +_¦_ 228 +ÖÅ 228 +ÁÎ 228 +Ë_ 226 +ÉÎ 224 +_ÐÒ 221 +ÍÏ 219 +_ÚÁ 218 +¦Î 216 +Á¤ 215 +ÍÁ 214 +ÌÁ 213 +_צ 210 +ÄÉ 209 +_Ç 207 +À_ 206 +ÒÅ 206 +ÇÏ_ 204 +É× 203 +_Ý 203 +Ú_ 202 +ÝÏ 201 +̦ 200 +ò 199 +ÏÇÏ_ 199 +ó 197 +ÓÑ_ 196 +ÉÓ 193 +ÏÎ 193 +_ÎÅ_ 190 +_ð 190 +¦Ì 188 +ÏÓ 187 +_Ï 186 +ÔÅ 186 +ÞÉ 185 +ÁÒ 184 +ÉÊ_ 184 +_÷ 176 +_×_ 174 +_Þ 174 +ÑË 173 +ÌØ 173 +ë 173 +ÁÓ 170 +_ÝÏ 169 +ÍÕ 168 +ÂÕ 167 +ñ 166 +ÉÌ 166 +ÉË 163 +å 163 +Ò¦ 163 +ä 163 +ú 162 +ÝÏ_ 161 +ÔÒ 160 +Φ_ 160 +¦× 160 +ÖÅ_ 159 +×¦Ä 159 +_Ì 158 +Ô¦ 155 +_×É 155 +* 154 +ÄÎ 153 +ÁÍ 153 +_* 152 +Á¤_ 152 +ÌÉ_ 152 +ØË 152 +_ËÏ 151 +È_ 151 +ËÕ 151 +*_ 151 +ÄÅ 151 +_*_ 150 +í 149 +_Ú_ 149 +_ÑË 148 +_Á 147 +Ħ 147 +ÄÕ 146 +ÁÖ 145 +_ÎÁ_ 144 +ÁÔÉ 144 +ËÁ_ 143 +ÐÉ 142 +_ÓÔ 141 +ÓØ 141 +ÌÑ 140 +Î_ 139 +ÌÅ 138 +Ц 137 +ÏÌÏ 137 +ÒÕ 136 +ÁÄ 136 +_ÝÏ_ 136 +ÍÉ 135 +æ 135 +_î 134 +_ÍÏ 133 +ÁË 133 +ËÉ_ 133 +ÏÀ 132 +ÎÕ 131 +ÉÍ 130 +¦Ô 129 +_ËÁ 129 +ÂÁ 129 +_ÔÏ 129 +§_ 128 +ÍÅ 128 +ÐÅ 128 +ͦ 128 +_ÂÕ 127 +×Ó 126 +á_ 126 +Ïצ 123 +ÏË 123 +×Å 122 +˦ 121 +: 119 +_à 118 +Õ× 118 +ÂÉ 116 +Ó¦ 116 +ÇÁ 115 +ϧ 115 +ÐÁ 115 +ÎÏ_ 115 +ÏÍÕ 114 +ÍÕ_ 113 +_Ö 113 +ÏÒÏ 113 +ÏÔ 113 +ÉÔØ 112 +ÏÚ 112 +? 111 +ÔÕ 110 +ÓÔÏ 109 +_ú 109 +ÏÞ 109 +ÉÈ 109 +ÕÔ 109 +ÏÀ_ 108 +¦Ë 108 +_È 106 +â 106 +ÄÏ_ 106 +¦Ê 106 +_×¦Ä 106 +Ó× 106 +ÚÎ 105 +¦ 105 +ÐÒÉ 105 +ÓÔÁ 104 +ÁÚ 104 +ËÒ 104 +ËÁÖ 104 +ÎÑ 103 +ÕÄ 103 +_ô 102 +_ÇÏ 102 +Ä_ 102 +ÔÏ_ 102 +ÉÔÉ 102 +_ó 101 +_ÔÁ 101 +ÌÏ× 101 +ì 100 +_ÒÏ 100 +ÞÁ 99 +ÏÍÕ_ 99 +ÐÅÒ 99 +_ÄÏ_ 98 +ÏÄÉ 98 +¦Ó 98 +ÁÖÅ 97 +ÌÁ_ 97 +ÁÊ 96 +ÓÏ 94 +ÁÔÉ_ 94 +_Õ 94 +ÌÀ 93 +! 93 +_Ó× 93 +.. 93 +ÅÒÅ 92 +ÓË 92 +¦ÌØ 92 +ÓÉ 92 +_ÐÒÉ 91 +ÅÌ 91 +ÐÒÏ 91 +_ËÁÖ 91 +ÈÏ 91 +ÏÖ 89 +þ 89 +Ô_ 88 +ÉÔØ_ 88 +ÅÓ 88 +ÞÏ 86 +ÂÏ 86 +ÓÌ 86 +ËÁÖÅ 86 +ÑÔ 85 +ñ_ 85 +ÓÐ 84 +ÔÏÒ 84 +ÏÌÉ 84 +_ËÁÖÅ 83 +_Ц 83 +_ÍÁ 82 +ÕÌ 82 +ÕË 82 +ç 81 +õ 81 +_ë 81 +Á×_ 81 +ÎÎ 81 +ÞÅ 81 +ÍÅÎ 81 +ÍÉ_ 80 +_Ê 79 +_í 79 +ØÓ 78 +ÎË 78 +ÁÀ 78 +ÂÅ 78 +ÃÅ 78 +_ÐÒÏ 77 +¦Î_ 77 +ÏÍ_ 77 +ÕÓ 77 +ÅÍ 77 +_ñ 77 +_ä 77 +_×Ï 76 +_ÍÅ 76 +ÉÈ_ 76 +ÅÔ 76 +ØÏ 75 +ÉÞ 75 +ØËÉ 75 +ÕÒ 74 +ØÓÑ 74 +ÔØÓ 74 +ÔØÓÑ 74 +ϧ_ 73 +_ÓÔÏ 73 +ËÏÌ 72 +". 72 +." 72 +ÏÌÏ× 72 +ÊÏ 72 +Ä× 71 +¦×_ 71 +ÏÐ 71 +Æ 71 +_ÐÅ 71 +Õ×Á 71 +ÎÉÊ 71 +ÓØ_ 70 +_â 70 +ÌØË 70 +_ÏÄ 69 +ÅΦ 69 +ÁÞ 68 +ÁÌÉ 68 +¦ÌØË 68 +ÈÁ 68 +ÑË_ 68 +ÔØÓÑ_ 68 +ÔÁË 68 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/vietnamese.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/vietnamese.lm new file mode 100644 index 0000000..54a21dc --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/vietnamese.lm @@ -0,0 +1,400 @@ +_ 88044 +n 17000 +h 12823 +t 9071 +i 8490 +c 8394 +g 8035 +ng 6718 +_t 6352 +_c 5234 +a 5083 +g_ 4883 +ng_ 4882 +_n 4379 +n_ 4365 +i_ 4365 +u 4149 +m 3648 +à 3635 +nh 3480 +o 3451 +Ç 3193 +_Ç 3168 +r 3011 +l 2692 +Ü 2659 +, 2328 +,_ 2295 +c_ 2279 +_l 2263 +ch 2226 +v 2161 +th 2158 +a_ 2132 +_th 2113 +y 2111 +. 2107 +t_ 2106 +h_ 2074 +_v 2057 +_h 1888 +_m 1834 +_ch 1813 +s 1749 +nh_ 1715 +u_ 1679 +á 1668 +à_ 1649 +tr 1611 +b 1589 +_tr 1581 +_nh 1541 +_b 1530 +m_ 1505 +p 1483 +._ 1455 +k 1429 +_s 1415 +o_ 1380 +y_ 1371 +_k 1367 +_ng 1348 +© 1343 +e 1296 +ó 1208 +‰ 1199 +ô 1181 +¶ 1139 +å 1132 +T 1126 +hi 1121 +â 1081 +ì 1058 +ê 1055 +d 1040 +_g 1039 +kh 1034 +_kh 1027 +_T 994 +©i 967 +là 943 +_là 941 +" 926 +ä 916 +Ü© 901 +an 893 +_d 888 +Ó 877 +©i_ 859 +on 853 +à 848 +N 846 +Š 820 +ó_ 813 +Œ 801 +ôn 795 +ph 776 +_p 772 +_ph 752 +û 752 +§ 734 +hÜ 728 +ho 715 +và 709 +_và 703 +gÜ 702 +® 700 +_r 696 +H 693 +_là_ 691 +là_ 691 +Ü©i 684 +àn 679 +ên 677 +ông 676 +ha 672 +gi 663 +C 656 +_gi 655 +Ö 654 +gÜ©i 646 +gÜ© 646 +Ü©i_ 624 +ông_ 610 +ngÜ 610 +_ngÜ 608 +ác 606 +ú 601 +ngÜ© 600 +ngÜ©i 600 +_ngÜ© 598 +gÜ©i_ 594 +ûa 587 +cû 586 +_cû 585 +¶t 585 +cûa 585 +ên_ 585 +_cûa 584 +có 583 +ûa_ 582 +_có 581 +cûa_ 581 +ã 581 +_cûa_ 580 +¶t_ 578 +_N 574 +có_ 574 +» 573 +_có_ 572 +iŒ 568 +À 562 +‹ 562 +m¶ 557 +_C 553 +_m¶ 551 +p_ 540 +Æ 540 +m¶t 538 +m¶t_ 534 +_m¶t 532 +ìn 528 +_m¶t_ 528 +ti 526 +i‰ 525 +Ù 517 +Î 512 +ình 500 +.. 500 +† 497 +và_ 497 +_và_ 496 +æ 491 +q 490 +qu 490 +_H 487 +_q 484 +_qu 484 +ong 481 +ong_ 471 +há 471 +x 470 +hô 468 +¿ 466 +_" 460 +Ü® 456 +ro 453 +ình_ 445 +ì_ 434 +_x 434 +ã_ 427 +í 423 +_ti 423 +in 422 +ân 421 +"_ 418 +iŠ 415 +Ön 413 +ron 412 +V 411 +rong 410 +§i 410 +rong_ 409 +ác_ 405 +ª 400 +‰n 399 +hôn 398 +åi 395 +ay 390 +_V 387 +h» 382 +hà 380 +ày 377 +Ãt 376 +uy 374 +ÇÜ 374 +_ÇÜ 373 +§i_ 372 +cá 371 +_cá 367 +nà 366 +‹_ 366 +hú 366 +_nà 365 +ra 363 +hông 362 +ho_ 359 +ân_ 356 +án 356 +° 355 +åi_ 354 +ai 352 +hu 352 +cho 352 +Ü®c 351 +®c 351 +Ón 351 +_cho 349 +tro 347 +‰t 347 +ào 347 +_tro 346 +_tron 346 +ñ 346 +tron 346 +trong 346 +M 345 +khô 340 +âu 338 +_khô 338 +cho_ 337 +_cho_ 336 +hông_ 336 +ay_ 333 +ch_ 332 +Çã 331 +Ãt_ 331 +( 331 +_( 330 +Ò 329 +_Çã 329 +ÇÜ® 328 +_ÇÜ®c 328 +) 328 +ÇÜ®c 328 +_ÇÜ® 328 +khôn 324 +_ñ 324 +_khôn 322 +Çã_ 322 +_Çã_ 320 +ò 318 +ån 318 +không 316 +ào_ 316 +Ü®c_ 316 +®c_ 316 +nhÜ 315 +Ü_ 315 +»ng 313 +»ng_ 313 +»n 313 +_nhÜ 313 +Th 312 +hì 311 +Û 310 +h»n 310 +h»ng_ 310 +h»ng 310 +iê 309 +gh 309 +Šu 307 +ta 307 +anh 307 +¡ 307 +ai_ 306 +àng 306 +ày_ 304 +ÇÜ®c_ 298 +ÜÖ 295 +S 295 +: 294 +‰t_ 294 +e_ 294 +:_ 290 +Î_ 289 +ua 288 +æn 288 +ài 286 +Šu_ 285 +_nh» 285 +nh» 285 +nh»ng 285 +nh»n 285 +_nh»n 285 +_Th 285 +‰n_ 284 +Œn 283 +Ø 281 +_M 281 +A 281 +úc 278 +L 277 +ø 277 +ÜÖn 276 +_ha 276 +n, 275 +Öng 275 +ÜÖng 275 +an_ 272 +ài_ 271 +iŠu 269 +sÓ 269 +n,_ 268 +¿_ 268 +on_ 267 +_sÓ 267 +các 265 +àng_ 265 +_các 264 +anh_ 264 +ngh 264 +_ta 263 +hi_ 262 +hàn 261 +Š_ 261 +âu_ 261 +Àn 260 +ù 260 +_ngh 257 +ia 255 +¢ 252 +... 252 +êu 251 +Ùc 251 +i, 249 +iŠu_ 248 +nhi 247 +B 246 +i,_ 245 +Óng 244 +ª_ 244 +co 244 +_nhi 244 +¥ 244 +ܧ 244 +iên 243 +D 243 +Tr 241 +_S 240 +hÜ_ 239 +òn 237 +hà 236 +hÆ 233 +K 233 +Öng_ 232 +ôi 232 +ÜÖng_ 232 +Àn_ 231 +_co 231 +Œn_ 229 +hå 229 +äi 229 +yê 229 +Ûn 229 +¢n 228 +Ûng 228 +_L 227 +Ûng_ 226 +inh 226 +Çi 225 +mà 225 +_Çi 225 +ng, 224 +ang 224 +P 224 +Šn 224 +g, 224 +g,_ 223 +_v§ 223 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/welsh.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/welsh.lm new file mode 100644 index 0000000..c25d4a4 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/welsh.lm @@ -0,0 +1,400 @@ +_ 78614 +a 18113 +d 17890 +y 16837 +e 14108 +n 13902 +r 13869 +i 12928 +o 9972 +l 9188 +h 7454 +g 7165 +w 7010 +t 6296 +f 6080 +u 5400 +n_ 5159 +_y 5051 +dd 4946 +s 4884 +r_ 4547 +m 4364 +d_ 4223 +yn 4082 +_a 4020 +c 3707 +th 3301 +u_ 2900 +yd 2900 +ae 2649 +l_ 2588 +_g 2547 +. 2460 +' 2458 +._ 2408 +wy 2334 +yn_ 2331 +_d 2307 +b 2267 +ym 2262 +ra 2261 +an 2235 +ar 2228 +ol 2218 +ia 2212 +i_ 2199 +ed 2191 +_yn 2038 +_i 2020 +y_ 1983 +_c 1934 +_yn_ 1861 +ei 1815 +it 1796 +g_ 1787 +ith 1779 +dd_ 1745 +h_ 1741 +ydd 1731 +ai 1709 +au 1708 +'r_ 1655 +'r 1655 +_y_ 1621 +di 1615 +, 1613 +,_ 1608 +da 1585 +od 1546 +_o 1535 +ad 1532 +th_ 1510 +ll 1494 +au_ 1492 +_s 1415 +er 1359 +o_ 1350 +io 1311 +a_ 1299 +ol_ 1294 +_e 1273 +_h 1249 +cy 1246 +yr 1243 +en 1228 +p 1217 +_f 1212 +_cy 1203 +mr 1200 +gy 1193 +ymr 1185 +ha 1172 +hy 1164 +eg 1159 +do 1151 +edd 1147 +G 1134 +we 1107 +C 1089 +_ar 1078 +_m 1075 +yf 1057 +de 1048 +fe 1047 +_G 1045 +ch 1043 +rae 1023 +el 1016 +no 1010 +ni 1010 +_b 1009 +ne 1001 +ef 992 +ri 983 +et 978 +_C 957 +_gy 952 +_a_ 943 +eth 943 +_. 940 +_._ 939 +eit 930 +eith 927 +ys 921 +wyd 912 +ga 901 +_i_ 893 +s_ 887 +mrae 878 +mraeg 878 +raeg 878 +ymrae 878 +aeg 878 +ymra 878 +mra 878 +_p 856 +aet 850 +aeth 850 +_n 844 +un 838 +on 836 +ait 833 +aith 833 +nn 830 +at 827 +oe 823 +li 805 +_r 801 +ddi 795 +gw 789 +ma 783 +le 777 +nt 772 +ho 769 +ff 766 +yr_ 764 +na 753 +la 748 +rh 747 +eg_ 734 +si 733 +ng 732 +dol 732 +ro 718 +al 712 +_dd 706 +wn 705 +oed 705 +Gy 704 +dy 701 +Cy 696 +o' 692 +ar_ 691 +ny 690 +Gym 678 +wr 677 +id 676 +_Gy 672 +_o_ 668 +Gymr 667 +if 662 +ith_ 662 +_ar_ 660 +iad 657 +_w 657 +fo 656 +eu 655 +aeg_ 650 +raeg_ 650 +aith_ 648 +or 648 +_Gym 646 +fa 642 +re 638 +_Cy 638 +_Gymr 635 +_gw 633 +fy 633 +oedd 633 +edd_ 629 +rd 627 +od_ 622 +ac 619 +ddo 612 +an_ 607 +Gymra 606 +er_ 605 +A 604 +eth_ 601 +hw 596 +ydd_ 591 +o'r 586 +o'r_ 586 +es 583 +ir 579 +dw 573 +go 559 +yl 548 +rw 545 +aeth_ 545 +wydd 543 +aw 539 +_rh 539 +dr 537 +ly 537 +fn 534 +dau 533 +_hy 531 +t_ 531 +sg 529 +'n 529 +* 528 +'n_ 523 +_* 522 +nyd 521 +nydd 521 +M 519 +st 518 +Y 516 +sy 515 +yd_ 513 +lw 512 +_ga 508 +iai 503 +il 502 +_l 499 +rt 494 +ad_ 493 +_yr 493 +_yr_ 492 +as 492 +dol_ 492 +f_ 491 +dda 491 +ig 490 +og 484 +wa 479 +he 478 +iaith 477 +iait 477 +oedd_ 475 +_ma 473 +c_ 472 +Cym 470 +te 469 +_ym 467 +am 467 +_M 465 +_ia 462 +efn 462 +i' 460 +ie 458 +_Cym 458 +_ac 457 +dau_ 456 +yw 455 +ew 453 +fr 441 +fod 441 +_A 441 +du 437 +_sy 434 +e_ 432 +wi 426 +Cymr 426 +se 425 +B 424 +D 424 +_Cymr 423 +bl 423 +lu 420 +in 417 +_t 417 +tr 414 +ac_ 413 +wed 410 +os 410 +_iai 407 +_iait 407 +el_ 405 +_ac_ 405 +rha 404 +m_ 404 +is 403 +on_ 401 +eu_ 393 +hi 393 +rdd 393 +id_ 389 +_Y 388 +ry 387 +odd 387 +rwy 387 +rf 386 +io_ 380 +ynn 380 +cyf 380 +hr 380 +_cyf 379 +yddi 379 +cyn 372 +_de 372 +rth 371 +ru 368 +S 363 +wei 363 +ysg 362 +_B 362 +u' 361 +yddo 360 +wn_ 360 +so 359 +dio 359 +_ei 358 +N 356 +dwy 355 +_da 353 +me 353 +gan 353 +gyf 353 +w_ 352 +_o' 351 +fer 349 +nol 347 +hyn 346 +ddy 346 +af 346 +ta 343 +ddol 343 +_fe 340 +nd 340 +mae 338 +_cyn 338 +efnyd 337 +fnydd 337 +fny 337 +efny 337 +fnyd 337 +iad_ 335 +_mae 333 +ion 333 +_ll 330 +def 330 +_gyf 327 +nt_ 326 +i'r_ 326 +- 326 +i'r 326 +weith 325 +weit 325 +defn 325 +defny 325 +bo 324 +hyd 323 +by 322 +_si 321 +ir_ 321 +hau 318 +nod 318 +edi 315 +I 314 +fyd 313 +wyr 313 +ada 311 +ddio 310 +rif 309 +sia 307 +sa 306 +fel 305 +tha 305 +_S 302 +_ne 302 +_u 301 +fod_ 300 +_o'r 300 +yg 300 +_o'r_ 300 +_i' 299 +ge 299 +dia 299 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/yiddish-utf.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/yiddish-utf.lm new file mode 100644 index 0000000..e3386a3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/DisabledLMs/yiddish-utf.lm @@ -0,0 +1,400 @@ +× 29767 +_ 13552 +_× 6516 +Ö 4273 + 3670 +× 3670 +×¢ 3261 +¢ 3261 +¢× 2826 +×¢× 2826 +×Ö 2785 +Ö 2785 +×™ 2565 +™ 2565 +¨ 2082 +ר 2082 +™× 2062 +×™× 2062 +˜ 1857 +ט 1857 +· 1828 +Ö· 1828 +Ÿ 1793 +ן 1793 +_× 1537 +Ÿ_ 1532 +ן_ 1532 +·× 1527 +Ö·× 1527 +×Ö· 1517 +Ö· 1517 +×¨× 1355 +¨× 1355 +œ 1270 +ל 1270 +¸ 1268 +×Ö¸ 1268 +Ö¸ 1268 +Ö¸ 1268 +Ö·× 1240 +×Ö·× 1240 +×  1232 +  1232 +×Ö¸× 1229 +Ö¸× 1229 +¸× 1229 +Ö¸× 1229 +× × 1181 + × 1181 +ו 1116 +• 1116 +“ 1031 +ד 1031 +×˜× 1012 +˜× 1012 +×œ× 1007 +œ× 1007 +×•× 975 +•× 975 +×“× 965 +“× 965 +×¤Ö 929 +¤ 929 +פ 929 +¤Ö 929 +¢×¨ 873 +ער 873 +×× 870 +× 870 +×– 868 +– 868 +¡ 832 +ס 832 +§ 797 +ק 797 +_×× 784 +מ 766 +ž 766 +_×Ö 752 +ž× 747 +×ž× 747 +’ 742 +×’ 742 +© 725 +ש 725 +ט_ 699 +˜_ 699 +×° 691 +° 691 +×°× 674 +°× 674 +² 667 +ײ 667 +’× 664 +×’× 664 +¿ 661 +Ö¿ 661 +×§× 654 +§× 654 +¿× 652 +Ö¿× 652 +×©× 651 +©× 651 +–× 643 +×–× 643 +פֿ 641 +¤Ö¿ 641 +×¤Ö¿× 638 +¤Ö¿× 638 +_×Ö· 638 +ר_ 592 +¨_ 592 +_ד 560 +_×“× 554 +, 551 +,_ 534 +ב 517 +‘ 517 +_×¤Ö 502 +_פ 502 +×‘× 472 +‘× 472 +×¡× 436 +¡× 436 +צ 436 +¦ 436 +×¦× 433 +¦× 433 +_×° 430 +_×°× 429 +” 410 +×” 410 +¢×¨_ 404 +_פֿ 404 +ער_ 404 +_מ 400 +_×ž× 396 +×’×¢ 390 +’×¢ 390 +_×– 390 +_×–× 386 +’×¢× 384 +ען 384 +×’×¢× 384 +¢×Ÿ 384 +×¢×¨× 382 +¢×¨× 382 +. 374 +××™ 372 +×™ 372 +Ö¼ 366 +¼ 366 +”× 363 +×”× 363 +×™× 362 +××™× 362 +_×’ 359 +×± 357 +± 357 +_×’× 356 +ון 349 +•×Ÿ 349 +×™_ 346 +™_ 346 +×¢_ 343 +¢_ 343 +•×Ÿ_ 337 +ון_ 337 +“×¢ 334 +דע 334 +_××™ 331 +ך 330 +š 330 +“×¢× 323 +¼× 323 +×“×¢× 323 +Ö¼× 323 +²× 322 +×²× 322 +ען_ 321 +¢×Ÿ_ 321 +±× 320 +×±× 320 +“×™ 317 +די 317 +²Ö· 311 +ַר 311 +×²Ö 311 +·×¨ 311 +ַר 311 +ײַ 311 +²Ö 311 +לע 310 +œ×¢ 310 +._ 307 +- 305 +·_ 297 +Ö·_ 297 +› 294 +×› 294 + ×¢ 290 +× ×¢ 290 +ס_ 289 +¡_ 289 +פּ 288 +¤Ö¼ 288 +×²Ö·× 287 +²Ö·× 287 +ך_ 283 +š_ 283 +Ö·_ 274 +×Ö·_ 274 +Ö·×¨× 272 +·×¨× 272 +×œ×¢× 261 +œ×¢× 261 +_×”× 260 +_×” 260 +_צ 259 +™×© 257 +יש 257 +_×¦× 256 +×–×™ 254 +–×™ 254 +×¤Ö¼× 252 +¤Ö¼× 252 +מע 248 +ž×¢ 248 +_ק 247 +× ×¢× 247 + ×¢× 247 +טע 245 +˜×¢ 245 +_×§× 245 +×ו 244 +×•× 244 +ו 244 +××•× 244 +¢×œ 238 +על 238 +”× 235 +×”× 235 +×”×Ö 235 +שט 235 +©×˜ 235 +”×Ö 235 +×›× 234 +›× 234 +_×‘× 231 +“ער 231 +_ב 231 +Ö·×  229 +·×  229 +·× × 228 +Ö·× × 228 +_×ו 227 +_×’×¢ 226 + 219 +× 219 +" 218 +ž×¢× 217 +×ž×¢× 217 +°×¢ 217 +×°×¢ 217 +·×œ 216 +ַל 216 +_×–×™ 215 +_×  215 +×¢×œ× 212 +¢×œ× 212 +¨× 211 +×¨× 211 +_× × 211 +×˜×¢× 211 +˜×¢× 211 +×°× 210 +°× 210 +_דע 210 +°×Ö 209 +×°×¢× 209 +×°×Ö 209 +°×¢× 209 +™×©× 208 +×™×©× 208 +™×§ 207 +יק 207 +ר×Ö 206 +¨×Ö 206 +–_ 205 +×–_ 205 +ž×™ 196 +מי 196 +_ש 195 +×ž×™× 195 +ž×™× 195 +ַל 193 +_×©× 191 +Ö¿× 189 +¿× 189 +¤Ö¿× 189 +Ö¿×Ö 188 +¿×• 188 +Ö¿×•× 188 +ֿו 188 +¿×•× 188 +¿×Ö 188 +ון 187 +”×Ö¸ 186 +_×”× 185 +¤Ö¿×• 184 +_×¢ 179 +_די 178 +˜× 176 +×˜× 176 +ט×Ö 175 +˜×Ö 175 +ָס 174 +ָס 174 +יט 174 +™×˜ 174 +¸×¡ 174 +ל_ 173 +œ_ 173 +“×™_ 173 +די_ 173 +×_ 171 +·×œ× 171 +_ 171 +Ö·×œ× 171 +_×¢× 171 +ָט 169 +¸×˜ 169 +ָט 169 +יך 168 +™×š 168 +ָר 166 +–×™× 166 +ָר 166 +¸×¨ 166 +×–×™× 166 +× ×™ 164 +×¢×  164 + ×™ 164 +¢×  164 +¨×™ 163 +רי 163 +יך_ 163 +™×š_ 163 +°×Ö¸ 162 +×¢× × 162 +¢× × 162 +¿×Ö· 160 +¢×˜ 160 +עט 160 +_×™ 158 +¨×™× 157 +™×¨ 157 +×¨×™× 157 +יר 157 +-× 156 +ָס_ 155 +¸×¡_ 155 +œ×™ 154 +_מי 154 +לי 154 +קע 153 +ונ 153 +§×¢ 153 +•×  153 +_×°× 152 + ×™× 152 +× ×™× 152 +™×Ÿ 151 +ין 151 +××± 151 +×± 151 +×™Ö 150 +·×˜ 150 +´ 150 +™Ö 150 +×™Ö´ 150 +™Ö´ 150 +Ö´ 150 +ַט 150 +Ö´× 149 +™Ö´× 149 +´× 149 +×™Ö´× 149 +œ×™× 148 +_×™× 148 +×œ×™× 148 +×±× 146 +××±× 146 +Ö·×  146 +_××± 145 +¿×•×Ÿ 145 +×™×– 143 +™×– 143 +“×™× 142 +×“×™× 142 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/albanian.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/albanian.lm new file mode 100644 index 0000000..8a2dcd3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/albanian.lm @@ -0,0 +1,400 @@ +_ 19480 +ë 4099 +e 4082 +t 3635 +i 3134 +a 2893 +r 2820 +n 2610 +s 2380 +h 2060 +ë_ 2055 +e_ 1825 +j 1677 +u 1489 +d 1381 +o 1370 +m 1318 +k 1264 +të 1091 +p 1072 +_t 1068 +sh 998 +l 936 +_n 876 +a_ 822 +, 816 +,_ 808 +të_ 795 +i_ 770 +_p 739 +_m 702 +_s 700 +te 653 +ër 620 +_d 613 +_e 607 +g 602 +_k 601 +_të 593 +. 575 +_të_ 574 +v 567 +_e_ 554 +r_ 525 +._ 523 +ht 503 +n_ 480 +he 473 +në 462 +sht 461 +te_ 457 +q 454 +nd 436 +ri 432 +is 414 +et 403 +b 402 +je 401 +me 395 +in 391 +it 381 +rë 374 +_a 374 +t_ 359 +ur 353 +_i 346 +ar 342 +ës 339 +er 338 +në_ 338 +ën 338 +dh 337 +en 336 +pë 334 +f 328 +_v 323 +jë 318 +nj 313 +ish 312 +për 294 +y 285 +z 282 +es 281 +at 274 +_me 273 +_q 273 +gj 269 +ra 261 +as 258 +_në 256 +ku 256 +j_ 250 +ta 249 +re 246 +një 245 +o_ 243 +ni 243 +_pë 240 +hte 240 +_nj 239 +on 239 +isht 236 +pa 234 +th 233 +shte 233 +_për 232 +se 228 +_g 223 +ve 221 +in_ 220 +s_ 219 +_në_ 219 +do 218 +hte_ 218 +më 216 +ti 215 +aj 212 +shte_ 212 +ej 212 +u_ 211 +që 211 +_sh 210 +nt 207 +jë_ 206 +_b 205 +_një 203 +di 202 +_pa 201 +_i_ 201 +ll 199 +_f 199 +kë 198 +me_ 197 +dhe 195 +ishte 195 +si 194 +hi 191 +he_ 188 +- 187 +ja 187 +_që 187 +ua 186 +il 184 +_dh 184 +ur_ 183 +ër_ 182 +or 180 +se_ 179 +që_ 178 +S 176 +ç 175 +_h 173 +an 172 +një_ 172 +ng 170 +nte 170 +_që_ 169 +_S 169 +rë_ 166 +dhe_ 165 +_me_ 164 +ka 162 +im 159 +hë 158 +mi 157 +to 156 +tu 156 +ën_ 155 +_një_ 154 +ha 153 +nte_ 150 +tr 148 +sa 148 +ët 148 +_gj 148 +un 147 +rr 147 +ë, 147 +_dhe 147 +ej_ 147 +ki 146 +ë,_ 146 +_ku 145 +_- 144 +_ng 142 +ik 141 +_nd 140 +end 138 +uk 137 +etë 135 +ko 135 +_dhe_ 135 +_ve 132 +va 131 +_l 131 +për_ 131 +shi 131 +erë 129 +ke 127 +kis 127 +së 126 +jo 125 +li 124 +ga 124 +kish 123 +_ki 122 +po 122 +_se 122 +' 121 +du 120 +mb 120 +_më 119 +Si 115 +më_ 115 +esh 115 +_si 114 +qe 114 +lë 114 +_kis 113 +oh 113 +_kish 113 +_Si 113 +pr 112 +_u 112 +uar 111 +de 111 +hu 111 +_th 111 +al 111 +ta_ 109 +ilv 108 +Sil 108 +Silv 108 +lv 108 +k_ 108 +e, 108 +ji 107 +e,_ 106 +_Sil 106 +_Silv 106 +_r 105 +os 104 +_se_ 104 +kisht 102 +_di 102 +st 101 +_për_ 101 +bë 101 +tj 100 +_nga 99 +nga 99 +_du 98 +ra_ 98 +vë 98 +gji 98 +_ish 96 +rt 96 +_is 96 +ro 95 +ir 94 +ga_ 94 +ësh 94 +ont 93 +c 93 +t, 93 +t,_ 93 +hin 92 +a, 92 +_at 92 +und 92 +jt 91 +_mb 91 +a,_ 91 +tje 90 +_nga_ 90 +_do 90 +_pr 90 +rit 90 +men 90 +nga_ 90 +ri_ 89 +N 89 +ma 89 +it_ 88 +_kë 88 +-_ 88 +m_ 87 +jo_ 87 +onte 87 +atë 87 +la 87 +ëri 87 +ilva 86 +shin 86 +ë. 86 +Silva 86 +lva 86 +së_ 85 +jer 85 +et_ 85 +_po 85 +ës_ 84 +kur 84 +ru 84 +nin 83 +ot 83 +hin_ 83 +_N 83 +her 83 +htë 82 +ap 82 +shin_ 82 +mo 81 +ash 81 +tha 81 +_ç 81 +ë._ 81 +ëm 81 +jit 80 +_ta 80 +ul 80 +le 80 +ho 80 +_z 79 +dr 78 +jet 78 +nin_ 78 +_më_ 78 +gjit 78 +A 78 +hk 78 +onte_ 78 +oni 77 +lo 77 +ba 77 +herë 77 +ndo 76 +shk 76 +mend 75 +_vë 75 +ha_ 75 +dë 75 +tur 74 +_A 74 +el 74 +bi 74 +_ko 74 +uk_ 73 +erë_ 73 +si_ 73 +_sa 73 +ar_ 72 +P 72 +rs 72 +pas 72 +ith 72 +uar_ 71 +_isht 71 +ai 70 +e. 70 +_vet 70 +vet 70 +_bë 70 +zi 70 +d_ 70 +jith 70 +da 70 +gjith 69 +duk 69 +na 69 +hej 69 +tër 68 +_men 68 +_ka 68 +am 68 +nd_ 68 +_c 67 +_pas 67 +_duk 67 +jes 67 +ak 67 +s, 67 +e._ 67 +s,_ 67 +K 67 +ësht 67 +mu 66 +kur_ 66 +yr 66 +em 65 +_së 65 +tha_ 65 +imi 65 +ie 65 +hej_ 64 +_së_ 64 +_u_ 64 +? 64 +fu 64 +_P 64 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/armenian.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/armenian.lm new file mode 100644 index 0000000..ed4a54e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/armenian.lm @@ -0,0 +1,400 @@ +_ 49002 +³ 12626 + 9480 +Ý 8485 +ñ 7623 +ï 7071 +á 7010 +» 6370 +« 6320 +¯ 5012 +ó 4656 +‰ 4607 +õ 4506 +Ç 4210 +í 3775 +áõ 3655 +Ù 3369 +ë 3320 +• 3208 +Ï 3016 +¯ó 2832 +³Ý 2755 +Û 2552 +§ 2519 +, 2502 +,_ 2492 +Ý_ 2177 +« 2099 + 2034 +é 2007 +© 1918 +»ñ 1748 +³ñ 1703 +Ñ 1605 +«_ 1587 +É 1558 +ã 1528 +ϳ 1502 +: 1483 +:_ 1482 +ù 1420 +_³ 1403 +ñ_ 1382 +Ç_ 1335 +à 1307 +Á 1294 +Ý» 1281 +— 1274 +¹ 1264 +ï 1229 +å 1218 +‰ï 1184 +÷ 1170 +³Ï 1154 +_á 1139 +³Û 1130 +_Ñ 1121 +Ÿ 1085 + 1065 +_ 1046 +_» 1036 +áñ 1019 +‘ 1017 +õÙ 1001 +áõÙ 993 +ÇÝ 987 +ï_ 964 + 962 +_Ù 961 +ñ³ 952 +Ù³ 951 +•_ 945 +‡ 941 + 938 +ѳ 934 +Õ 929 +Ý»ñ 919 +¯ï 918 +· 915 +ó_ 911 +»Ý 910 +ݳ 910 +³Ý_ 882 +•« 863 +«‰ 846 +ç 834 + 827 +© 824 +¿ 818 +ÃÛ 817 +õà 804 +áõà 804 +_‰ 791 +õÃÛ 787 +áõÃÛ 787 +£ 781 +õÝ 753 +_¯ 750 +Ù_ 748 +_Ÿ 747 +ï 747 +áõÝ 744 +_¿ 732 +ñá 730 +« 723 +ó§ 710 +õ_ 710 +¯ó§ 709 +_ѳ 708 +_Ï 705 +ï³ 703 +µ 702 +‰— 697 + 695 +§_ 684 +_§ 683 +ñÇ 682 +… 672 +³Ï³ 671 +Ûá 669 +»É 666 +ó‘ 659 +ß 659 +Í 658 +¯ó‘ 658 +Ë 653 +‘© 649 +ó‘© 641 +¯ó‘© 641 +ó« 640 +Ûáõ 636 +»õ 635 +¯ó« 631 +_ã 626 +Ÿ 623 +Û³ 620 +ë_ 616 +_ 615 +õÙ_ 614 +áõÙ_ 613 +Ýá 601 +Ï³Ý 597 +‰« 596 +«_ 590 +³Ù 590 +§ 582 +Á_ 581 +«‰ï 576 +³ï 574 +í³ 574 +ƒ 566 +í 564 +› 555 +_í 532 +©¯ 527 +Ýù 527 +© 526 +_ 524 +©¯ó 517 +_Ç 511 +ï• 510 +_ 507 +§ 500 +í 500 +ÛáõÝ 497 +ï¯ 496 +½ 488 +™ 485 +³í 480 +_Ÿ 480 +ó§_ 478 +¯ó§_ 477 +«¯ 476 +ÃÛá 475 +ÃÛáõ 475 +³Ï³Ý 473 +_Ý 469 +É_ 466 +­ 465 +»ñÇ 465 +ÃÛáõÝ 464 +_ë 463 +õÃÛá 459 +õÃÛáõ 459 +áõÃÛá 459 +Ýáõ 454 +‹ 449 +_áñ 449 +ñ» 444 +_³Û 442 +—_ 431 +Ù» 428 +í_ 427 +_ϳ 422 + 422 +©¯ó« 421 +»õ_ 416 +‰ó 416 +_¯ï 415 +³ë 414 +_• 413 +å³ 408 +‘©¯ 405 +‘©¯ó 405 +ÇÝ_ 404 +‘©¯ó« 400 +󑩯 399 +¯ó‘©¯ 399 +󑩯ó 399 +ñÇ_ 398 +¿_ 395 +Û³Ý 394 +áñ_ 387 +- 385 +ñáõ 383 +« 382 +é 380 +ù_ 379 +ã 377 +«¯ó 377 +é_ 377 +áí 376 +Ý»ñÇ 374 +ëï 371 +©« 371 +»Ý_ 371 +_¹ 371 +ï‰ 370 +ë 368 +³ 367 +_¿_ 366 +íá 363 +í» 361 +ï» 358 +. 357 +ÙÇ 356 +_å 351 +¡ 347 +_»õ 345 +ÃÛ³ 342 +³é 341 +_µ 341 +_« 340 +ϳÝ_ 339 +ñÁ 338 +_ï 337 +_ 331 +¯ï_ 330 +õÃÛ³ 328 +áõÃÛ³ 328 +ÝÇ 328 +‰ï• 327 +•«_ 324 +_»Ý 324 +¯£ 324 +_»õ_ 322 +Éá 321 +»ñÇ_ 321 +_Ù» 318 +µ³ 317 +áÕ 317 +Ù³Ý 316 +_· 314 +ÝÝ 314 +å» 309 +_© 309 +³Ï³Ý_ 307 +ë 306 +»ï 306 +_÷ 303 +ÛÝ 302 +«÷ 302 +¹³ 302 +Çñ 300 +—¯ 299 +ÃÛ³Ý 299 +³Ýá 299 +_ 299 +__ 299 +Ïá 298 +« 298 +ñ¹ 297 +‰—_ 294 +_áõ 293 +_‡ 292 +ïá 291 +³ó 291 +õÃÛ³Ý 288 +»Õ 288 +»ë 287 +áõ_ 286 +_… 286 +² 284 +ë‰ 284 +¯ë 284 +˳ 283 +Å 283 +‰ó_ 281 +‰«_ 281 +Û³Ý_ 281 +` 280 +ñ 279 +`_ 279 +«• 279 +³Ù³ 278 +»É_ 274 +³Í 271 +Ó 268 +_Ù³ 266 +ç 266 +§• 266 +ÉÇ 266 +Ý»ñÇ_ 266 +í‰ 264 +Ý, 263 +§‰ 263 +³_ 262 +ë¯ 262 +Ý,_ 262 +«« 259 +ÝÁ 258 +_ƒ 258 +Ï» 257 +»ñÁ 257 +Ï_ 255 +ï¯ó 255 +_ù 255 +_áñ_ 255 +ï 255 +ñÏ 253 +ÝÝ» 252 +»ñ_ 252 +ƒ 250 +ù³ 248 +ÝÝ»ñ 248 +_¯ï_ 247 +ݹ 246 +Ýù_ 246 +™ 245 +•ï 244 +³Ñ 244 +«‰ï• 244 +‘© 244 +»ó 243 +ÃÛ³Ý_ 243 +ó‘© 242 +¯ó‘© 242 +› 241 +¯ 239 +³ñ³ 238 +ï•_ 238 +³Ý³ 237 +« 237 +‰í 237 +·á 237 +_é 236 +ÝáõÙ 234 +³É 234 +«_ 233 +÷_ 233 +Ù³ñ 233 +ë³ 232 +³Ýáõ 232 +« 231 +× 230 +‰é 230 +«¯ 230 +_‰ó 228 +³ÛÝ 228 +©« 228 +û 227 +»Ýù 227 +_ÙÇ 226 +Ý³Ï 223 +«_ 223 +_- 222 +»Ï 222 +¯ó_ 222 +éí 220 +_à 220 +_³Ý 218 +ϳñ 217 +‘©« 216 +_ã 216 +§ 216 +€ 215 +“ 215 +ó‘©« 214 +í¯ 214 +_¯ó 213 +û 213 +‡ 213 +÷ 212 +ѳ٠211 +ï‡ 210 +³½ 210 +_‰ó_ 210 +_‰« 209 +ïí 209 +_»Ý_ 208 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/belarus-windows1251.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/belarus-windows1251.lm new file mode 100644 index 0000000..9c38c0d --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/belarus-windows1251.lm @@ -0,0 +1,400 @@ +_ 9440 +à 4377 +í 1855 +i 1544 +ð 1436 +ó 1345 +ê 1246 +û 1233 +å 1215 +ñ 1093 +ë 1090 +ò 1050 +ÿ 934 +ä 860 +î 811 +â 792 +à_ 740 +ì 724 +ç 699 +ö 643 +íà 589 +ï 580 +ã 531 +. 480 +êà 467 +ðà 458 +ó_ 432 +i_ 430 +._ 418 +, 402 +,_ 402 +á 391 +àð 373 +òà 361 +÷ 350 +âà 340 +ü 335 +àë 330 +ý 329 +_ï 328 +àí 315 +ëà 307 +ÿ_ 306 +_ñ 305 +û_ 296 +àä 279 +é 279 +_ó 274 +ðû 271 +ø 269 +ãà 250 +å_ 247 +õ 244 +_í 240 +_ç 236 +_à 221 +ñò 221 +íû 220 +ëi 218 +äà 210 +àâ 203 +_ê 199 +ñê 197 +ïà 195 +_ó_ 194 +äç 193 +íi 193 +àì 192 +_ã 190 +êi 190 +_i 189 +àñ 187 +çå 185 +_ä 179 +é_ 178 +àó 176 +àã 174 +þ 171 +_íà 169 +ëü 167 +_â 166 +íà_ 166 +ëå 162 +_ì 161 +àé 160 +ií 158 +ì_ 154 +æ 154 +òû 154 +ðó 151 +ïð 151 +_á 149 +iê 148 +ûÿ 147 +çà 146 +åð 145 +ðî 142 +àê 141 +óñ 140 +_i_ 140 +ü_ 140 +" 137 +åí 135 +àö 135 +êó 131 +ìà 129 +_ïà 129 +õ_ 126 +äçå 126 +àç 125 +íå 125 +íí 123 +_ò 122 +àò 122 +ãà_ 121 +àãà 120 +_ïð 120 +åë 120 +àâà 119 +À 119 +ûì 116 +- 113 +âå 112 +âû 112 +ñà 112 +àé_ 111 +öû 109 +öü 109 +_À 107 +ìi 106 +àãà_ 105 +îð 103 +öü_ 102 +Ì 101 +_êà 100 +_Ì 100 +_ÿ 99 +ëÿ 99 +íÿ 98 +íñ 96 + 95 +ñÿ 94 +òð 94 +âi 92 +ãî 92 +ç_ 91 +ñêà 91 +öà 91 +òó 91 +àá 91 +àëà 90 +÷à 88 +òî 88 +íû_ 87 +ñòà 87 +î_ 87 +_ð 86 +ÿê 84 +öö 84 +iêà 83 +îó 83 +ñâ 83 +àÿ 83 +÷û 82 +ïðà 81 +_çà 79 +ûí 79 +åò 79 +ìå 79 +ÿí 79 +âÿ 79 +_ç_ 78 +ëi_ 78 +ûÿ_ 78 +ðóñ 77 +êi_ 75 +îä 74 +_ãà 74 +i÷ 74 +åö 73 +íñê 73 +åëà 72 +àíà 72 +âàí 72 +äð 72 +ô 71 +óí 71 +ðí 71 +àðó 71 +àó_ 70 +àå 70 +àëå 70 +_íà_ 70 +àëi 69 +iì 68 +Ï 68 +à. 68 +îë 68 +òâ 68 +_àä 68 +ûì_ 67 +àÿ_ 67 +ëàð 67 +ööà 67 +ñï 67 +_" 67 +îí 67 +i, 67 +à._ 67 +àðóñ 67 +i,_ 67 +åëàðó 66 +öi 66 +óä 66 +àðà 66 +ëàðóñ 66 +ëàðó 66 +ïå 66 +åëàð 66 +_ø 65 +àäç 65 +êò 65 +Í 65 +_äà 65 +òà_ 65 +Á 64 +_ 64 +ðàä 64 +íàã 64 +_ñò 64 +øû 63 +íê 63 +üí 63 +óð 62 +ëüí 62 +_Ï 62 +çi 62 +óë 62 +ëà_ 62 +ðý 62 +iö 62 +òàð 62 +óê 61 +û, 61 +ñö 61 +_Í 61 +û,_ 61 +àõ 61 +êàë 60 +iñ 60 +ð_ 60 +öà_ 60 +I 59 +îâ 59 +íàãà 59 +_I 59 +_Á 59 +ûõ 59 +Ê 59 +_ïðà 59 +äí 59 +óñê 59 +ië 59 +íå_ 59 +ó. 59 +_ñâ 58 +ó._ 58 +ä_ 57 +êî 57 +áå 57 +ñi 57 +çå_ 57 +êð 57 +ýí 56 +àâàí 56 +àðû 56 +ïi 56 +åä 56 +äçå_ 55 +_âû 55 +íàãà_ 54 +áà 54 +ööà_ 54 +öå 53 +áî 53 +Ìi 53 +÷í 53 +à÷ 53 +åê 53 +iÿ 53 +Ñ 53 +íî 53 +_Ìi 52 +_ÿê 52 +ÿð 52 +òâà 51 +íûÿ 51 +ûñ 51 +àï 50 +à,_ 50 +ó,_ 50 +àëü 50 +ïðû 50 +_÷ 50 +à, 50 +ó, 50 +àíí 50 +ûõ_ 50 +_Ñ 50 +áû 49 +êñ 49 +iõ 49 +åðà 49 +ê_ 49 +þ_ 48 +ðóñê 48 +_Ê 48 +_ý 47 +äû 47 +êë 47 +ãi 47 +_. 47 +àø 47 +óò 47 +íiê 46 +âàð 46 +àäà 46 +_._ 46 +øò 46 +ðû_ 46 +òý 46 +_íå 46 +çí 45 +òû_ 45 +ûë 45 +_- 45 +_ñà 45 +àì_ 45 +Ä 45 +_ìà 45 +iò 44 +_ë 44 +_ïðû 44 +óñêà 44 +ëiê 44 +âà_ 44 +àçå 43 +ýò 43 +êàì 43 +ÿë 43 +_ãî 43 +äî 43 +í_ 43 +ÿò 43 +iõ_ 42 +íûÿ_ 42 +ðò 42 +ñòâ 42 +íàé 42 +êàâ 42 +ãàçå 42 +.. 42 +_ãàç 42 +_ãàçå 42 +ãàç 42 +ïåð 42 +íò 41 +_áå 41 +ñå 41 +ðàâ 41 +áð 41 +àðî 41 +ûö 41 +íä 41 +Áåë 40 +åööà 40 +äà_ 40 +û. 40 +iíñê 40 +ûi 40 +_ðà 40 +îëü 40 +è 40 +"_ 40 +( 40 +_Ä 40 +øà 40 +òàê 40 +Ó 40 +ñÿ_ 40 +iíñ 40 +_âà 40 +_( 40 +àíû 40 +Áå 40 +) 40 +åöö 40 +íÿ_ 39 +äçi 39 +_Ó 39 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/bosnian.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/bosnian.lm new file mode 100644 index 0000000..cf6b8a4 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/bosnian.lm @@ -0,0 +1,400 @@ +_ 9464 +a 2787 +i 2108 +e 2077 +o 2018 +j 1396 +n 1328 +s 1170 +u 1010 +r 988 +d 957 +a_ 889 +e_ 833 +t 774 +je 771 +k 756 +l 743 +m 702 +v 685 +p 604 +c 538 +i_ 538 +_s 522 +u_ 476 +z 463 +_p 450 +o_ 433 +,_ 381 +, 381 +_i 369 +_n 358 +b 349 +_d 349 +. 346 +na 341 +je_ 337 +._ 321 +_j 307 +g 299 +ra 292 +st 283 +ko 278 +_je 274 +ij 254 +_o 245 +ni 240 +_k 236 +an 228 +oj 227 +da 226 +_u 222 +pr 221 +no 219 +ma 219 +la 211 +ri 206 +_je_ 203 +po 203 +ci 196 +_pr 191 +os 190 +od 187 +ka 186 +im 185 +ti 184 +li 182 +vo 178 +_po 174 +ja 171 +_i_ 169 +ov 169 +al 168 +re 167 +ne 167 +m_ 164 +ta 160 +na_ 158 +ed 157 +_m 157 +_na 157 +se 156 +_u_ 154 +en 153 +ic 151 +sa 151 +_b 149 +ak 141 +va 140 +ad 137 +h 136 +ju 135 +su 134 +dj 133 +ije 133 +ar 127 +ca 127 +_z 126 +nj 125 +ji 124 +da_ 124 +_ko 123 +_da 122 +il 121 +" 120 +av 120 +_t 118 +aj 116 +ob 115 +ro 114 +am 114 +vi 114 +_su 113 +om 112 +dje 112 +za 112 +at 111 +le 111 +di 110 +su_ 107 +iz 107 +ve 107 +lj 106 +_se 105 +ev 105 +is 105 +es 103 +se_ 103 +do 101 +ih 100 +a, 99 +_su_ 99 +a,_ 99 +on 98 +bi 98 +in 97 +voj 97 +az 96 +ac 95 +_da_ 95 +la_ 95 +_r 93 +_g 93 +jev 92 +ma_ 92 +er 92 +or 91 +h_ 90 +_sa 90 +e, 90 +e,_ 90 +ba 90 +ima 89 +a. 88 +ol 88 +_do 87 +dn 87 +it 87 +ko_ 86 +ne_ 86 +ost 85 +ek 85 +to 85 +d_ 84 +as 84 +ju_ 84 +ao 84 +ih_ 84 +a._ 84 +te 83 +evo 83 +koj 83 +pri 82 +jevo 82 +ce 81 +_se_ 81 +og 80 +go 80 +jevoj 79 +de 79 +uc 79 +evoj 79 +_od 78 +_za 78 +tr 78 +S 77 +_koj 76 +ke 75 +_v 75 +ao_ 75 +_dje 74 +_bi 74 +sta 74 +_dj 74 +cij 74 +ik 74 +djev 73 +sl 73 +_djev 72 +ga 72 +djevo 72 +_ka 71 +rij 71 +_iz 71 +P 71 +_pri 70 +_a 69 +us 68 +_S 68 +mo 67 +el 67 +sk 66 +me 66 +zi 66 +ija 65 +n_ 65 +ku 64 +im_ 63 +_st 63 +ica 63 +_na_ 62 +_ne 62 +em 61 +edn 61 +jk 61 +io 61 +li_ 60 +ojk 60 +evojk 60 +_" 60 +zn 60 +vojk 60 +pro 59 +lo 59 +ije_ 59 +jed 58 +ke_ 58 +om_ 58 +jen 58 +sti 57 +_im 57 +le_ 57 +_ra 56 +e. 56 +ze 55 +_pro 55 +nu 55 +nje 55 +ti_ 55 +ec 55 +pre 55 +oc 54 +aci 54 +no_ 54 +et 54 +oji 53 +si 53 +ara 53 +ama 53 +z_ 53 +pos 52 +rad 52 +ran 52 +ima_ 52 +ru 52 +_P 52 +tu 52 +mu 51 +e._ 51 +ja_ 50 +_pre 50 +sa_ 49 +io_ 49 +od_ 48 +ni_ 48 +_nj 48 +j_ 48 +_pos 47 +_c 47 +ila 47 +K 46 +_sa_ 46 +uz 46 +N 46 +_ni 45 +zna 45 +U 45 +za_ 45 +_no 45 +ako 45 +u, 44 +lu 44 +ali 44 +u,_ 44 +sto 44 +ste 44 +ve_ 44 +ani 44 +oli 44 +aka 44 +_jed 43 +i,_ 43 +ji_ 43 +uci 43 +i, 43 +ci_ 43 +osti 43 +_N 42 +dr 42 +so 42 +ust 41 +ila_ 41 +B 41 +- 41 +red 41 +jke 41 +sv 41 +_go 41 +bar 41 +g_ 41 +est 40 +D 40 +iv 40 +vojke 40 +aju 40 +ta_ 40 +A 40 +lje 40 +jedn 40 +bil 40 +ojke 40 +ova 40 +ati 39 +_mu 39 +pa 39 +M 39 +_ba 39 +ca_ 39 +O 39 +ka_ 39 +_a_ 38 +_B 38 +_ima 38 +sn 38 +nu_ 38 +T 38 +to_ 38 +eg 38 +ava 38 +ros 37 +ir 37 +ala 37 +og_ 37 +osl 37 +ovi 37 +koji 37 +_sv 37 +dv 36 +ric 36 +_za_ 36 +br 36 +_on 36 +odi 36 +_koji 36 +_jedn 35 +nik 35 +dno 35 +_D 35 +jo 35 +tra 35 +_M 35 +sp 35 +iz_ 35 +oz 35 +vr 35 +u. 35 +eri 35 +I 35 +eko 35 +ale 35 +_ma 34 +lik 34 +_bil 34 +c_ 34 +ut 34 +je,_ 34 +u._ 34 +str 34 +je, 34 +adi 34 +tit 34 +_iz_ 34 +iti 34 +i. 33 +_rad 33 +ici 33 +rost 33 +aju_ 33 +va_ 33 +_ob 33 +nog 33 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/bulgarian-iso8859_5.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/bulgarian-iso8859_5.lm new file mode 100644 index 0000000..548ab02 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/bulgarian-iso8859_5.lm @@ -0,0 +1,400 @@ +_ 11056 +Ð 3428 +Ø 3007 +Õ 2501 +Þ 2490 +Ý 2179 +â 2166 +à 1596 +á 1492 +Ò 1159 +Ð_ 1144 +Ú 1093 +Û 918 +Ô 803 +Ø_ 803 +ÝÐ 724 +ß 720 +× 702 +Õ_ 642 +Ü 613 +_Ý 577 +_á 569 +Þ_ 556 +. 537 +ÝØ 534 +âÕ 473 +._ 467 +ï 462 +áâ 455 +_ß 452 +_ÝÐ 446 +,_ 440 +, 440 +Ó 439 +Ñ 432 +ÝÐ_ 422 +ê 405 +ã 382 +âÞ 376 +ÕÝ 360 +àÐ 360 +ç 355 +_Ø 353 +Ðâ 334 +âÐ 330 +â_ 324 +Øâ 322 +_ÝÐ_ 316 +ÐÝ 310 +àÕ 308 +àØ 305 +ÒÐ 303 +ÝÞ 301 +Þâ 281 +_Ò 278 +_Þ 275 +ØâÕ 262 +ÚÞ 262 +ßà 262 +_Ú 250 +âÞ_ 248 +ÚÐ 242 +àÞ 236 +ßÞ 235 +Ðà 230 +_Ô 226 +ÝÕ 222 +Þá 216 +æ 214 +Øï 210 +âÕ_ 203 +âØ 198 +_Ø_ 196 +Õâ 196 +_ßà 195 +áÚ 189 +ÕÔ 189 +ØâÕ_ 189 +Ò_ 186 +ÐÒ 185 +ÔÐ 185 +_Õ 184 +×Ø 178 +ÞÒ 177 +ä 175 +ÛØ 175 +âÐ_ 172 +ØÚ 171 +ÐÚ 170 +_à 169 +_ßÞ 169 +_Ñ 165 +ï_ 163 +×Ð 162 +Ö 161 +Õà 160 +ÝØ_ 159 +ÛÕ 156 +áÕ 156 +ÒÕ 155 +ÕÛ 154 +_Ò_ 152 +_× 152 +Ø× 151 +ÚØ 151 +_Ü 150 +ÛÐ 149 +é 148 +_Þâ 146 +ØÝ 145 +æØ 143 +ÜØ 141 +_â 138 +Ð× 137 +ÓÐ 135 +Þà 134 +Õ× 133 +_×Ð 133 +ÞÔ 131 +ÞÑ 129 +Ù 128 +ÐÛ 127 +_Ó 126 +ÐâÐ 124 +Þáâ 123 +ÔØ 123 +Øï_ 123 +Øá 122 +Õá 121 +_áÕ 120 +ÕÝØ 119 +ÞÛ 118 +ÒØ 116 +ÒÐ_ 115 +âÝ 113 +ÝÞ_ 112 +¿ 112 +- 111 +Þâ_ 111 +ÜÕ 110 +ÐâÐ_ 109 +Ýâ 108 +_Þâ_ 108 +Úâ 108 +ÐÝØ 107 +ÔÕ 107 +ÒÞ 107 +_ÚÞ 106 +áÕ_ 105 +çÕ 103 +_¿ 103 +_áÕ_ 101 +Øà 101 +âÒ 100 +_ÔÐ 99 +" 99 +ØÕ 99 +ØÜ 99 +ÜÐ 98 +áÚØ 97 +ÕâÞ 97 +ÐÝÕ 97 +_Õ_ 97 +ßàÞ 96 +ÐÚâ 96 +è 93 +ÔÐ_ 93 +ÓÞ 92 +áØ 92 +ÐàØ 92 +ÔÞ 92 +áÛ 91 +Øæ 90 +ÛÝ 90 +Øç 89 +Õ×Ø 89 +×Ð_ 89 +ÞÓ 88 +ÕâÞ_ 88 +_ã 88 +ÐÜ 88 +Ø, 87 +âÕà 87 +Ðá 87 +Ø,_ 87 +_ÔÐ_ 85 +_×Ð_ 83 +êÛ 83 +áâÒ 83 +Ðâ_ 83 +å 82 +ØÛ 81 +Ú_ 81 +_Ø× 81 +_Ð 80 +ßàÕ 80 +ÝØâ 79 +ÞÝ 78 +ïâ 78 +ÝØâÕ 78 +âà 78 +Á 77 +ÕàØ 77 +ÝÕ_ 77 +ÑØ 77 +ÚØ_ 76 +_ÝÕ 76 +ÓÐà 75 +Øáâ 75 +ÛÓ 75 +ØÒ 75 +ÝÞá 74 +ÛÞ 73 +_àÕ 73 +ÜÞ 73 +á_ 73 +àÕÔ 73 +_ßàÞ 72 +ÑÐ 72 +ãç 72 +ÛÓÐà 72 +ÛÓÐ 72 +êÛÓ 71 +Ðä 71 +Ð,_ 71 +êÛÓÐà 71 +ÝØâÕ_ 71 +ÒÐÝ 71 +êÛÓÐ 71 +Ý_ 71 +Ð, 71 +êà 70 +áê 70 +àÕ× 70 +ÐÔ 70 +àÐÝ 70 +ÕÚ 70 +_àÐ 70 +Û_ 69 +çÝ 68 +ØàÐ 68 +Óà 67 +Ýá 67 +ØæØ 66 +ÝØï 66 +ÝÞáâ 66 +Ü_ 66 +áÐ 66 +ÕÜ 65 +àÐ× 65 +ÚÐâ 64 +ÞâÞ 64 +Ñê 64 +ÝØÕ 64 +_ç 64 +âÕàØ 63 +ÐÒÐ 63 +_ÚÐ 63 +_Á 62 +_± 62 +ÚÐ_ 62 +± 62 +ØÚ_ 62 +_. 62 +çÐ 61 +ÞÙ 61 +Òê 61 +çØ 61 +ÞÜ 61 +_áê 61 +Õáâ 60 +ÕÝâ 60 +( 60 +) 60 +áâÕ 59 +ßÕ 59 +Þß 59 +âÝÞ 59 +äÐ 59 +Ø. 58 +À 58 +áâÐ 58 +_( 58 +_ßàÕ 58 +ÔÝ 58 +àá 58 +_Û 57 +ÞâÞ_ 57 +ÓàÐ 57 +ßàØ 57 +ØÝÐ 56 +Ø._ 56 +Úê 56 +ÝÐâ 56 +âÕÝ 56 +_àÐ× 55 +×Ò 55 +áâØ 55 +ÚâÕ 55 +_á_ 55 +áà 55 +_,_ 55 +_ÔÞ 55 +ÑêÛÓÐ 55 +ÑêÛ 55 +ÑêÛÓ 55 +_, 55 +ØÕ_ 54 +ÐÚâÕà 54 +È 54 +ÐÚâÕ 54 +_- 54 +ÚâÕà 54 +-_ 53 +áÚÐ 53 +ãá 53 +áâ_ 53 +ÚâÕàØ 53 +áâÞ 53 +_áà 53 +ÕÒ 53 +_Ñê 52 +âÕÛ 52 +ÛÝØ 52 +_-_ 52 +ØÞ 51 +_È 51 +Ðß 51 +Þ× 51 +Ô_ 50 +_À 50 +äÐà 50 +ÒÐâ 50 +ØØ 50 +¸ 50 +_ßàØ 50 +_áÛ 50 +_" 50 +ÞÚ 49 +_ÑÐ 49 +áß 49 +áâÕÝ 49 +ØÐ 48 +ÛÕÔ 48 +áÚØ_ 48 +àØÚ 48 +ÑÐÚâÕ 48 +_áÐ 48 +ÈÐ 48 +_._ 48 +ÑÐÚ 48 +àã 48 +ÑÐÚâ 48 +Òï 48 +ØáâÕ 48 +ÛÐÒ 47 +Úà 47 +½ 47 +äÐàØÚ 47 +_ÈÐ 47 +äÐàØ 47 +ÐäÐ 47 +ÐäÐàØ 47 +Ðàá 47 +ÐäÐà 47 +ÐàØÚ 47 +ÈÐä 47 +àáÚ 47 +âÝØ 46 +ÈÐäÐ 46 +_ÈÐä 46 +ÐÝÕ_ 46 +ÞÒÕ 46 +ÈÐäÐà 46 +_ÈÐäÐ 45 +ÐâÞ 45 +Øïâ 45 +ÞØ 45 +ïÝ 45 +ÕÝØÕ 45 +_áâ 45 +éÐ 45 +ÕÝ_ 45 +ÑÞ 45 +×Øá 45 +×ØÚ 45 +âÕÝâ 44 +ØáâÕÝ 44 +_ÑêÛ 44 +áâÕÝâ 44 +_ÑêÛÓ 44 +ÚÞ_ 44 +ÝØï_ 44 +ÝáÚ 44 +àØ_ 44 +ÝÐâÐ 44 + 43 +×Øáâ 43 +Ðáâ 43 +×ØáâÕ 43 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/croatian-ascii.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/croatian-ascii.lm new file mode 100644 index 0000000..b054ac3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/croatian-ascii.lm @@ -0,0 +1,400 @@ +_ 36598 +a 9456 +o 9050 +i 8526 +e 7955 +n 5513 +j 5379 +s 4971 +t 4125 +r 3889 +u 3423 +je 3281 +l 3231 +e_ 3177 +d 3128 +k 2992 +v 2891 +a_ 2835 +o_ 2679 +m 2645 +p 2316 +_s 2212 +i_ 2205 +y 2174 +c 1894 +z 1867 +je_ 1613 +_n 1593 +g 1581 +_p 1490 +b 1386 +u_ 1382 +, 1208 +,_ 1208 +st 1203 +_j 1202 +na 1159 +_je 1118 +_d 1105 +_i 1104 +. 1069 +._ 1058 +ra 1017 +ko 981 +ni 980 +_je_ 918 +ij 914 +ti 911 +no 891 +da 884 +to 879 +_k 863 +_o 856 +cy 839 +li 838 +ne 790 +sy 786 +- 785 +pr 760 +_u 748 +po 734 +ta 711 +_b 705 +_t 704 +la 699 +ja 699 +an 691 +m_ 680 +ov 674 +ije 673 +_z 669 +ka 662 +ri 652 +lo 651 +vo 643 +re 641 +is 626 +in 623 +se 623 +va 622 +_m 617 +oj 614 +_po 594 +_pr 592 +bi 588 +en 582 +il 578 +os 576 +vi 572 +nj 569 +ak 564 +_na 558 +im 558 +da_ 553 +od 550 +ao 550 +al 549 +om 545 +na_ 533 +_se 524 +_i_ 523 +h 517 +_g 511 +ma 508 +at 502 +cj 501 +og 497 +-- 493 +ro 493 +on 485 +av 480 +_da 474 +_ne 474 +ed 472 +zy 471 +se_ 466 +_se_ 458 +_bi 457 +ao_ 452 +ad 452 +lj 445 +es 444 +ji 441 +_v 433 +_c 430 +za 421 +go 418 +_r 413 +_u_ 411 +yi 410 +ek 406 +di 403 +sa 396 +et 393 +ic 391 +io 390 +_da_ 389 +to_ 389 +as 386 +_ko 383 +ye 378 +ar 378 +mo 373 +le 367 +or 364 +ju 363 +el 354 +tr 354 +io_ 352 +ve 345 +lo_ 344 +su 344 +ol 344 +am 344 +iz 343 +li_ 338 +ti_ 336 +sto 323 +n_ 321 +it 319 +_za 319 +sta 317 +_ni 316 +te 312 +nu 312 +a, 309 +a,_ 309 +ya 309 +do 304 +om_ 303 +la_ 300 +no_ 299 +_na_ 299 +d_ 297 +ko_ 296 +aj 294 +ik 292 +ru 291 +ga 291 +em 288 +nje 283 +dj 281 +ne_ 281 +k_ 277 +_st 276 +koj 276 +ec 274 +_ka 272 +_su 270 +ob 265 +-_ 263 +az 261 +sv 260 +_koj 260 +im_ 260 +ije_ 259 +pa 258 +ot 257 +yt 256 +ok 255 +su_ 255 +ih 254 +me 253 +dn 253 +_cy 253 +iv 251 +syt 248 +g_ 247 +--_ 246 +_- 246 +kr 246 +--- 246 +a. 245 +e,_ 245 +---_ 245 +e, 245 +er 245 +a._ 244 +_iz 244 +mi 243 +_---_ 242 +cyi 242 +_-- 242 +_--- 242 +jed 240 +h_ 239 +_a 239 +_sa 237 +j_ 236 +_l 231 +_sv 229 +_to 229 +sk 228 +ih_ 224 +ja_ 223 +pro 223 +yn 222 +t_ 222 +ost 221 +_do 221 +oc 219 +gl 218 +_su_ 216 +og_ 216 +uc 214 +s_ 214 +bil 213 +oz 213 +ki 212 +ni_ 212 +nij 209 +ako 208 +eg 208 +ut 205 +pre 205 +ci 204 +ji_ 203 +_od 203 +ilo 202 +ati 202 +ac 201 +ns 200 +_mo 197 +rij 196 +bo 195 +ovo 195 +ku 195 +dje 194 +ma_ 192 +_bil 191 +cje 186 +sti 186 +_go 186 +de 185 +sl 183 +_pro 182 +ju_ 182 +nije 181 +tv 180 +lje 179 +isy 179 +pri 178 +_pre 177 +dr 177 +e._ 177 +e. 177 +op 176 +ima 176 +anj 175 +jen 175 +us 172 +ilo_ 172 +_ra 170 +S 167 +ecj 166 +iti 166 +sp 163 +_S 161 +vr 161 +i. 161 +i._ 161 +zn 161 +ali 161 +i,_ 160 +i, 160 +ap 157 +nije_ 157 +nst 156 +pi 156 +ga_ 156 +_sy 155 +_nj 155 +jes 155 +ran 155 +vo_ 155 +yto 154 +ev 153 +_to_ 152 +_pri 151 +est 150 +N 150 +ins 150 +ist 149 +ir 149 +o, 148 +vj 148 +vje 148 +o,_ 148 +B 148 +zi 147 +jec 147 +gov 147 +yto_ 147 +syto 146 +ton 146 +od_ 145 +O 144 +rije 144 +lik 143 +on_ 142 +ocy 142 +W 142 +ba 142 +_W 141 +kao 141 +Wi 141 +_N 141 +inst 141 +_nij 141 +_nije 140 +_Wi 140 +syto_ 140 +lic 139 +P 139 +ovi 138 +_tr 138 +rs 137 +ez 137 +edn 136 +_P 136 +si 136 +ili 136 +du 136 +Winst 135 +cye 135 +nston 135 +ston 135 +ud 135 +kao_ 135 +Wins 135 +insto 135 +oji 135 +nsto 135 +Win 135 +raz 135 +zye 135 +_Win 134 +ova 134 +_Wins 134 +_on 133 +ako_ 133 +odi 133 +cya 133 +ila 133 +icy 133 +oj_ 133 +ke 133 +va_ 132 +ija 132 +_is 132 +jel 132 +oje 130 +pu 130 +cje_ 130 +bi_ 129 +rat 128 +ce 128 +tu 128 +mu 128 +ve_ 127 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/czech-iso8859_2.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/czech-iso8859_2.lm new file mode 100644 index 0000000..bb1755b --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/czech-iso8859_2.lm @@ -0,0 +1,400 @@ +_ 26378 +o 5870 +e 5354 +a 4740 +n 4462 +t 3745 +s 3438 +i 3187 +v 3118 +l 2891 +r 2754 +k 2566 +d 2508 +m 2198 +u 2197 +p 2032 +í 1924 +c 1678 +h 1572 +z 1544 +á 1522 +_p 1299 +e_ 1266 +y 1231 +a_ 1219 +j 1219 +_s 1156 +b 1079 +o_ 1065 +ì 1043 +_v 1038 +, 952 +,_ 946 +st 945 +_n 911 +é 878 +. 870 +í_ 848 +ø 822 +._ 803 +ní 782 +ov 757 +_z 723 +i_ 716 +u_ 684 +ro 674 +en 656 +ý 647 +¾ 639 +po 630 +ch 629 +è 625 +na 599 +_a 598 +sk 592 +¹ 563 +ho 552 +_d 551 +ra 545 +m_ 539 +y_ 530 +_t 512 +ko 504 +_k 503 +le 502 +_j 501 +_o 486 +to 479 +pr 471 +ne 468 +ní_ 462 +je 458 +é_ 456 +ti 455 +od 433 +li 432 +va 432 +_po 429 +_m 428 +al 424 +te 424 +ou 423 +ed 418 +se 415 +la 410 +no 397 +os 382 +lo 377 +an 376 +_pr 375 +ù 375 +v_ 372 +øe 370 +_a_ 364 +em 363 +at 360 +ta 359 +do 357 +t_ 357 +_b 355 +or 349 +h_ 345 +_v_ 338 +ch_ 327 +S 325 +ce 323 +av 323 +pø 322 +ni 319 +ké 316 +er 315 +nì 315 +_na 313 +na_ 312 +_ne 311 +de 308 +ic 307 +in 306 +_se 306 +l_ 304 +dn 302 +za 298 +_pø 293 +ì_ 291 +ol 290 +_je 281 +ob 280 +is 277 +ve 274 +ho_ 272 +es 270 +ot 268 +ak 265 +vo 263 +ná 260 +il 257 +se_ 257 +it 256 +et 253 +ad 250 +by 249 +P 242 +_r 242 +k_ 242 +ost 241 +_se_ 241 +tr 238 +me 237 +pro 234 +¾e 234 +ka 230 +_za 227 +om 224 +el 223 +_P 223 +on 218 +_pro 216 +ou_ 216 +tu 215 +O 212 +mi 212 +ku 211 +_u 210 +_do 208 +_l 207 +_na_ 206 +N 205 +ské 205 +ím 205 +íc 205 +ý_ 203 +mì 203 +_S 200 +oz 200 +V 200 +ze 198 +da 194 +sl 192 +á_ 191 +ova 190 +mo 190 +re 189 +so 187 +vy 186 +ej 185 +rá 184 +ar 184 +s_ 183 +vì 183 +A 181 +ru 180 +_st 178 +f 178 +éh 177 +ého 176 +kt 176 +tn 175 +g 174 +bo 174 +ez 173 +ci 172 +ký 172 +né 170 +M 170 +án 169 +as 168 +vi 167 +øi 167 +ac 166 +¾e_ 165 +ýc 165 +¾_ 165 +ck 164 +K 164 +B 164 +ých 164 +vá 162 +_c 162 +ého_ 162 +ení 161 +lá 160 +_¾ 160 +øí 160 +pøe 159 +ec 158 +ù_ 157 +J 156 +vn 156 +_h 155 +ké_ 155 +ok 154 +sta 154 +to_ 152 +vý 152 +nt 151 +ých_ 149 +lo_ 149 +_by 149 +dy 149 +_pøe 148 +ce_ 147 +R 146 +n_ 146 +ád 146 +pa 145 +vé 145 +am 145 +mu 145 +ný 145 +ud 144 +_è 144 +_B 142 +ter 141 +nì_ 141 +èe 140 +¹e 140 +_V 140 +_ko 140 +li_ 139 +dì 137 +hl 137 +je_ 137 +ji 137 +ist 135 +jí 135 +- 134 +ik 133 +si 133 +ál 132 +em_ 132 +_to 132 +_vy 131 +sp 130 +ut 130 +_J 130 +_¾e 130 +_M 129 +di 129 +kon 128 +la_ 128 +tí 128 +_ro 127 +ns 127 +ek 126 +ick 126 +T 126 +yl 125 +èn 125 +rn 125 +_¾e_ 124 +op 124 +sti 124 +kte 124 +øed 124 +edn 123 +us 121 +ím_ 120 +" 119 +z_ 119 +str 118 +ti_ 118 +ém 118 +vat 118 +d_ 118 +_ve 118 +áv 118 +ení_ 117 +iv 117 +oj 117 +_kt 117 +ìl 117 +val 116 +eb 116 +_K 115 +tø 115 +_kte 115 +át 115 +_i 114 +_N 114 +D 114 +kl 114 +ny 114 +byl 113 +ev 113 +ri 113 +ú 113 +ky 111 +sm 111 +oh 111 +E 110 +ma 110 +ìt 110 +ský 110 +kter 109 +nu 109 +le_ 108 +ja 107 +zá 107 +tì 106 +tá 106 +zn 106 +let 105 +aj 105 +sto 105 +¹í 105 +me_ 105 +-_ 105 +u, 105 +sv 104 +_le 104 +pol 104 +L 104 +_- 104 +ln 104 +pod 104 +H 103 +zi 103 +kéh 103 +kého 103 +_ná 103 +ent 102 +u,_ 102 +_od 102 +né_ 101 +_-_ 101 +al_ 101 +_kter 101 +do_ 100 +nos 100 +cí 100 +rav 99 +ran 99 +_sv 99 +ká 98 +eè 98 +ním 98 +bu 97 +_z_ 97 +ích 97 +_byl 97 +ání 96 +rov 96 +kr 96 +dá 95 +ové 95 +dl 95 +uj 95 +nost 95 +ém_ 95 +ech 94 +ly 94 +oc 94 +vé_ 93 +_o_ 93 +dy_ 93 +ak_ 93 +nsk 93 +_so 93 +_ob 92 +nc 92 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/danish.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/danish.lm new file mode 100644 index 0000000..3fbd48a --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/danish.lm @@ -0,0 +1,400 @@ +_ 21274 +e 9291 +r 5307 +n 4733 +i 3976 +t 3948 +s 3751 +a 3296 +l 3063 +d 3025 +o 2868 +g 2471 +er 2164 +k 2002 +m 1680 +e_ 1655 +en 1613 +f 1507 +de 1484 +r_ 1379 +v 1245 +u 1176 +t_ 1081 +n_ 1032 +er_ 992 +b 942 +. 870 +ge 868 +._ 831 +re 816 +h 816 +et 813 +te 813 +p 806 +in 788 +or 775 +_s 753 +_a 749 +en_ 712 +_e 691 +ti 689 +an 687 +, 681 +,_ 677 +_f 655 +_d 645 +el 642 +ng 635 +nd 634 +g_ 634 +se 615 +le 615 +st 607 +s_ 601 +_o 572 +ne 560 +li 537 +et_ 524 +es 521 +_i 512 +ri 511 +sk 510 +_de 498 +å 497 +ar 475 +ed 473 +ig 463 +at 452 +_m 446 +is 443 +fo 441 +æ 441 +ve 438 +_k 434 +ø 432 +der 429 +ke 428 +ing 427 +og 426 +_b 412 +me 408 +il 407 +for 405 +ns 394 +y 389 +_h 380 +_t 374 +on 371 +d_ 370 +al 362 +be 359 +_fo 351 +af 336 +de_ 335 +_og 333 +_p 332 +og_ 325 +om 325 +_for 324 +_og_ 313 +l_ 308 +nge 302 +i_ 295 +_v 294 +c 289 +ter 283 +ll 280 +ni 278 +nde 278 +rs 277 +_af 277 +un 275 +ra 271 +ko 271 +den 270 +_i_ 268 +id 265 +til 265 +j 265 +vi 264 +D 260 +ere 256 +ma 255 +si 253 +f_ 252 +af_ 238 +_af_ 235 +ik 235 +m_ 234 +å_ 232 +_ti 227 +_D 226 +_u 226 +_er 225 +nt 224 +_en 224 +ls 221 +es_ 216 +lig 216 +ger 216 +re_ 210 +ag 210 +_me 207 +at_ 204 +lle 200 +ge_ 200 +_til 200 +ige 199 +_er_ 199 +der_ 199 +em 199 +ds 197 +r. 195 +io 195 +r._ 195 +ud 193 +_at 192 +_at_ 191 +ta 190 +els 190 +_l 190 +ha 190 +il_ 189 +or_ 189 +ke_ 186 +rt 185 +gen 184 +ka 183 +- 180 +rk 180 +ning 178 +ol 178 +nin 178 +la 177 +ld 175 +De 175 +it 173 +ede 172 +ed_ 171 +_ko 171 +lse 171 +ek 168 +else 167 +inge 167 +på 167 +ng_ 167 +_på 167 +iv 166 +ør 166 +so 165 +he 165 +ens 165 +ske 165 +ind 164 +til_ 163 +rn 163 +ide 162 +ev 162 +den_ 162 +to 162 +sen 160 +_be 160 +sa 160 +bl 158 +_g 158 +an_ 157 +det 156 +om_ 156 +ru 156 +va 155 +_til_ 155 +ste 154 +rd 153 +_på_ 152 +k_ 152 +på_ 152 +di 152 +kr 152 +K 151 +_De 149 +for_ 148 +te_ 148 +kon 148 +ver 147 +mm 146 +am 146 +_en_ 145 +_r 145 +ne_ 144 +ing_ 144 +tr 143 +le_ 142 +del 142 +_in 142 +gt 140 +_st 138 +S 138 +eg 138 +gs 138 +tt 138 +r, 137 +ser 137 +r,_ 137 +er. 137 +ro 137 +er._ 137 +_for_ 136 +ent 136 +kt 136 +eri 135 +ur 134 +lin 134 +B 133 +A 133 +sti 133 +ner 133 +da 133 +ris 132 +ion 132 +_K 131 +ern 131 +ers 130 +ist 130 +ær 130 +ige_ 130 +_si 130 +tte 129 +E 128 +_n 128 +nn 127 +_B 126 +_ha 126 +_. 126 +rne 125 +H 125 +_ud 125 +rin 124 +na 124 +und 124 +ft 124 +_der 124 +ku 123 +_A 122 +ler 120 +and 120 +end 120 +ns_ 120 +rg 119 +op 119 +er,_ 119 +er, 119 +ar_ 118 +P 118 +_S 117 +_H 117 +_._ 116 +ov 116 +erne 115 +tio 115 +med 115 +tion 115 +_E 115 +_P 115 +det_ 114 +pr 114 +e. 113 +ter_ 113 +: 113 +kk 113 +e._ 113 +e,_ 113 +e, 113 +od 113 +kke 113 +ten 113 +ling 113 +:_ 112 +mi 112 +eli 112 +lo 111 +som 111 +_den 111 +rb 110 +se_ 110 +ell 110 +sid 110 +nne 109 +fi 108 +lt 107 +v_ 107 +_de_ 107 +ark 106 +lige 106 +ngen 106 +ie 105 +_med 105 +_der_ 105 +ring 105 +a_ 105 +_vi 104 +-_ 104 +ys 103 +gel 103 +_so 103 +ia 103 +ive 102 +ej 101 +ati 101 +ren 101 +_det 101 +side 101 +ske_ 101 +br 100 +gi 100 +F 100 +M 100 +ul 99 +isk 99 +men 99 +n,_ 99 +age 99 +fr 99 +n, 99 +tu 98 +ts 98 +_ma 98 +nder 98 +ot 97 +dt 97 +R 97 +med_ 96 +ho 96 +ans 95 +_kon 95 +pe 95 +ce 94 +gr 93 +mme 92 +ret 92 +lige_ 92 +mu 91 +_med_ 91 +hv 91 +væ 91 +Det 91 +ens_ 91 +kl 91 +_M 90 +T 90 +ingen 90 +rm 90 +ill 89 +elle 89 +ef 89 +ene 89 +nds 89 +ove 89 +som_ 89 +C 88 +_den_ 88 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/dutch.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/dutch.lm new file mode 100644 index 0000000..17a0626 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/dutch.lm @@ -0,0 +1,400 @@ +_ 20104 +e 9848 +n 5323 +a 3733 +t 3683 +i 3490 +r 3195 +d 2876 +o 2845 +n_ 2443 +en 2439 +s 2195 +e_ 1842 +l 1837 +g 1522 +en_ 1500 +de 1489 +er 1388 +t_ 1377 +v 1253 +u 1217 +k 1204 +_d 1136 +h 1102 +m 1084 +an 939 +te 875 +j 857 +in 810 +_v 793 +r_ 751 +de_ 742 +ee 737 +p 732 +et 718 +ge 716 +aa 708 +b 703 +_e 686 +st 669 +z 668 +ie 662 +_de 655 +w 631 +c 611 +. 604 +s_ 582 +_de_ 576 +_h 572 +el 570 +ij 564 +._ 554 +et_ 531 +an_ 522 +he 505 +_o 497 +nd 478 +_i 475 +ar 459 +_m 451 +re 442 +ve 441 +' 428 +or 424 +ng 421 +at 418 +_s 415 +oo 403 +_z 401 +le 395 +_b 394 +_a 391 +_he 386 +va 385 +er_ 381 +me 372 +_w 368 +f 361 +on 351 +_t 351 +_va 345 +_g 342 +di 342 +nt 340 +, 335 +g_ 335 +,_ 334 +van 327 +ch 326 +is 326 +ing 325 +be 325 +ni 320 +it 317 +een 316 +_van 315 +al 310 +den 309 +ti 309 +van_ 307 +oe 302 +ke 302 +_van_ 299 +aar 299 +d_ 295 +we 293 +da 292 +tu 290 +_ee 290 +ud 287 +een_ 286 +li 284 +es 282 +_st 281 +ver 281 +ten 281 +ri 275 +nde 275 +der 274 +_in 270 +k_ 268 +vo 267 +het 266 +oor 264 +_het 262 +het_ 262 +_het_ 259 +_een 258 +l_ 258 +ze 257 +_n 254 +ro 248 +gen 243 +_een_ 241 +at_ 240 +op 238 +n. 238 +_en 237 +rs 237 +_da 235 +stu 232 +in_ 230 +_be 229 +_ge 228 +_k 226 +rd 226 +tud 220 +_en_ 220 +n._ 217 +te_ 209 +ei 208 +ent 206 +_me 203 +la 202 +ek 202 +ed 201 +ra 200 +stud 200 +en. 200 +ie_ 197 +ste 196 +_vo 195 +_in_ 193 +_stu 191 +zi 191 +om 189 +ui 189 +en._ 186 +ten_ 185 +_stud 185 +ude 184 +die 183 +ns 183 +_j 181 +D 179 +aan 179 +se 179 +ma 178 +_ve 176 +ne 174 +_p 174 +eg 173 +p_ 172 +ar_ 172 +aar_ 171 +_te 170 +ng_ 169 +_we 169 +'' 167 +_D 165 +ers 164 +_op 163 +dat 161 +dat_ 160 +ig 160 +ere 159 +eer 158 +_zi 158 +voor 156 +voo 156 +nge 155 +nder 151 +nte 151 +or_ 150 +ta 150 +je 149 +ing_ 148 +ll 148 +_ver 147 +jk 146 +oor_ 146 +_dat 145 +ijk 145 +ren 145 +is_ 145 +_dat_ 144 +_l 144 +and 144 +lij 143 +ter 143 +na 142 +uden 139 +tude 138 +_voor 136 +_voo 136 +ond 136 +ken 135 +cht 135 +_al 135 +ht 135 +wa 134 +ho 133 +em 133 +den_ 133 +pe 132 +sc 132 +un 131 +ur 131 +_di 130 +gen_ 130 +zo 129 +rt 129 +ev 128 +mo 128 +lijk 127 +_is 126 +stude 124 +ha 123 +to 122 +el_ 121 +og 121 +op_ 121 +sch 120 +ol 120 +ente 119 +_u 118 +pr 118 +end 118 +mi 117 +iet 116 +_aa 116 +eli 115 +dent 115 +ijn 115 +jn 115 +ou 115 +men 114 +_' 114 +tie 113 +_is_ 113 +nie 113 +tr 112 +ak 112 +id 112 +udent 111 +tuden 111 +uit 110 +_te_ 109 +aan_ 109 +ld 109 +S 108 +_aan 108 +ede 108 +ja 107 +nten 107 +it_ 107 +je_ 107 +ts 107 +erd 106 +est 106 +E 105 +_op_ 105 +ad 104 +al_ 104 +_ze 104 +_on 104 +rk 104 +lle 103 +ens 103 +gel 103 +m_ 103 +len 103 +_r 102 +ec 102 +inge 102 +met 102 +_met 101 +si 100 +die_ 100 +us 100 +onde 99 +_ni 99 +De 99 +eu 99 +dente 99 +enten 99 +ic 99 +_met_ 98 +f_ 98 +met_ 98 +no 97 +ko 96 +voor_ 96 +rde 96 +H 96 +ngen 95 +lo 95 +ot 95 +as 94 +zij 93 +_nie 92 +vi 92 +eb 92 +_De 92 +_zij 91 +ep 91 +wi 91 +_zo 91 +kt 91 +ege 91 +G 91 +bi 90 +j_ 90 +ij_ 90 +ze_ 90 +do 90 +lan 89 +ov 89 +udi 89 +ord 89 +onder 89 +V 88 +elij 88 +_wa 88 +elijk 88 +ef 88 +_die 87 +ag 86 +erk 86 +eren 86 +R 85 +ik 85 +_ma 85 +gr 85 +am 85 +_mo 84 +ul 84 +nn 83 +eve 83 +De_ 83 +maa 83 +ingen 83 +wo 83 +_'' 83 +O 83 +tudi 82 +I 82 +nt_ 82 +tudie 81 +ven 81 +udie 81 +nten_ 81 +_die_ 81 +jaa 80 +ka 80 +eke 80 +ite 80 +a_ 80 +_je 80 +ac 80 +jaar 80 +_je_ 79 +_H 79 +_zijn 79 +zijn 79 +n, 78 +nen 78 +N 78 +n,_ 78 +ijn_ 77 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/english.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/english.lm new file mode 100644 index 0000000..ab71632 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/english.lm @@ -0,0 +1,400 @@ +_ 20326 +e 6617 +t 4843 +o 3834 +n 3653 +i 3602 +a 3433 +s 2945 +r 2921 +h 2507 +e_ 2000 +d 1816 +_t 1785 +c 1639 +l 1635 +th 1535 +he 1351 +_th 1333 +u 1309 +f 1253 +m 1175 +p 1151 +_a 1145 +the 1142 +_the 1060 +s_ 978 +er 968 +_o 967 +he_ 928 +d_ 888 +t_ 885 +the_ 844 +_the_ 843 +on 842 +in 817 +y 783 +n_ 773 +b 761 +re 754 +, 734 +,_ 732 +an 732 +g 728 +w 718 +_i 707 +en 676 +f_ 599 +y_ 595 +of 594 +_of 592 +es 589 +ti 587 +v 580 +_of_ 575 +of_ 575 +nd 568 +at 549 +r_ 540 +_w 534 +it 522 +ed 496 +_p 494 +nt 485 +_c 462 +o_ 457 +io 450 +_an 439 +te 432 +or 425 +_b 418 +nd_ 407 +to 406 +st 402 +is 401 +_s 396 +_in 389 +ion 385 +and 385 +de 384 +ve 382 +ha 375 +ar 366 +_m 361 +and_ 360 +_and 360 +_and_ 358 +se 353 +_to 347 +me 346 +to_ 344 +ed_ 339 +. 330 +be 329 +_f 329 +._ 329 +_to_ 320 +co 317 +ic 316 +ns 308 +al 307 +le 304 +ou 304 +ce 293 +ent 279 +l_ 278 +_co 277 +tio 275 +on_ 274 +_d 274 +tion 268 +ri 266 +_e 264 +ng 253 +hi 251 +er_ 249 +ea 246 +as 245 +_be 242 +pe 242 +h_ 234 +_r 232 +ec 227 +ch 223 +ro 222 +ct 220 +_h 219 +pr 217 +in_ 217 +ne 214 +ll 214 +rt 213 +s,_ 210 +s, 210 +li 209 +ra 208 +T 207 +wh 204 +a_ 203 +ac 201 +_wh 199 +_n 196 +ts 196 +di 196 +es_ 195 +si 194 +re_ 193 +at_ 192 +nc 192 +ie 190 +_a_ 188 +_in_ 185 +ing 184 +us 182 +_re 182 +g_ 179 +ng_ 178 +op 178 +con 177 +tha 175 +_l 174 +_tha 174 +ver 173 +ma 173 +ion_ 171 +_con 171 +ci 170 +ons 170 +_it 170 +po 169 +ere 168 +is_ 167 +ta 167 +la 166 +_pr 165 +fo 164 +ho 164 +ir 162 +ss 161 +men 160 +be_ 160 +un 159 +ty 159 +_be_ 158 +ing_ 157 +om 156 +ot 156 +hat 155 +ly 155 +_g 155 +em 153 +_T 151 +rs 150 +mo 148 +ch_ 148 +wi 147 +we 147 +ad 147 +ts_ 145 +res 143 +_wi 143 +I 143 +hat_ 142 +ei 141 +ly_ 141 +ni 140 +os 140 +ca 139 +ur 139 +A 138 +ut 138 +that 138 +_that 137 +ati 137 +_fo 137 +st_ 137 +il 136 +or_ 136 +for 136 +pa 136 +ul 135 +ate 135 +ter 134 +it_ 134 +nt_ 133 +that_ 132 +_ha 129 +al_ 128 +el 128 +as_ 127 +ll_ 127 +_ma 125 +no 124 +ment 124 +an_ 124 +tion_ 122 +su 122 +bl 122 +_de 122 +nce 120 +pl 120 +fe 119 +tr 118 +so 118 +int 115 +ov 114 +e, 114 +e,_ 114 +_u 113 +ent_ 113 +Th 113 +her 113 +j 112 +atio 112 +ation 112 +_Th 111 +le_ 110 +ai 110 +_it_ 110 +_on 110 +_for 109 +ect 109 +k 109 +hic 108 +est 108 +der 107 +tu 107 +na 106 +_by_ 106 +by_ 106 +E 106 +by 106 +_by 106 +ve_ 106 +_di 106 +en_ 104 +vi 104 +m_ 103 +_whi 102 +iv 102 +whi 102 +ns_ 102 +_A 101 +ich 100 +ge 100 +pro 99 +ess 99 +_whic 99 +ers 99 +hich 99 +ce_ 99 +which 99 +whic 99 +all 98 +ove 98 +_is 98 +ich_ 97 +ee 97 +hich_ 97 +n,_ 96 +n, 96 +im 95 +ir_ 94 +hei 94 +ions 94 +sti 94 +se_ 94 +per 93 +The 93 +_pa 93 +heir 93 +id 93 +eir 93 +eir_ 93 +ig 93 +heir_ 93 +_no 93 +ev 93 +era 92 +_int 92 +ted 91 +_The 91 +ies 91 +art 91 +thei 90 +_ar 90 +_thei 90 +their 90 +_pro 90 +et 89 +_pe 88 +_mo 88 +ther 88 +x 87 +gh 87 +S 87 +_is_ 87 +ol 87 +ty_ 87 +_I 86 +nde 86 +am 86 +rn 86 +nte 86 +mp 85 +_su 84 +_we 84 +par 84 +_v 84 +pu 82 +his 82 +ow 82 +mi 82 +go 81 +N 81 +ue 81 +ple 81 +ep 80 +ab 80 +;_ 80 +; 80 +ex 80 +ain 80 +over 80 +_un 79 +q 79 +qu 79 +pp 79 +ith 79 +ry 79 +_as 79 +ber 79 +ub 78 +av 78 +uc 78 +s._ 77 +s. 77 +enc 77 +are 77 +iti 77 +gr 76 +his_ 76 +ua 76 +part 76 +ff 75 +eve 75 +O 75 +rea 74 +ous 74 +ia 74 +The_ 73 +ag 73 +mb 73 +_go 73 +fa 72 +on,_ 72 +ern 72 +t,_ 72 +on, 72 +t, 72 +_me 71 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/estonian.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/estonian.lm new file mode 100644 index 0000000..45934b5 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/estonian.lm @@ -0,0 +1,400 @@ +_ 20738 +a 7004 +e 5699 +i 5321 +s 4731 +t 3769 +l 3448 +u 3446 +n 2902 +k 2584 +d 2202 +m 2043 +a_ 1758 +o 1684 +r 1429 +g 1174 +v 1151 +e_ 1139 +i_ 1136 +_k 1136 +s_ 1077 +h 1009 +, 995 +,_ 995 +_t 953 +p 953 +j 940 +ä 900 +is 896 +st 851 +se 841 +_s 822 +. 821 +as 801 +d_ 801 +le 800 +ta 794 +in 793 +_m 790 +ô 754 +._ 753 +t_ 746 +ma 710 +_p 680 +si 677 +_v 660 +es 636 +al 626 +us 619 +el 602 +_o 596 +_e 586 +ja 580 +_j 563 +te 562 +ü 549 +li 532 +va 515 +id 501 +ol 498 +tu 497 +da 490 +_n 480 +ku 478 +ud 459 +nu 455 +na 438 +ei 432 +ks 418 +mi 411 +ee 411 +u_ 407 +ka 400 +n_ 394 +b 394 +ga 386 +_l 384 +_a 380 +an 366 +ja_ 365 +et 358 +me 358 +l_ 350 +at 348 +la 341 +ad 340 +st_ 339 +ne 336 +ll 333 +_ta 332 +ra 330 +_ja 328 +ik 323 +en 318 +ni 308 +ul 305 +sa 302 +_ol 302 +nd 299 +_ja_ 299 +nud 296 +ii 291 +ko 286 +_se 285 +le_ 283 +aa 281 +is_ 281 +gi 270 +_te 269 +ag 269 +_va 268 +_ku 267 +ed 262 +em 255 +_mi 255 +ma_ 247 +ti 246 +ri 245 +_h 242 +gu 239 +id_ 238 +ast 237 +it 236 +ga_ 236 +un 232 +de 230 +ud_ 230 +ha 230 +ak 228 +ah 228 +uu 228 +il 227 +ôi 226 +as_ 223 +ke 222 +ar 220 +a, 220 +am 220 +_ko 220 +a,_ 220 +_ka 220 +ai 220 +eg 216 +sin 214 +est 214 +ui 214 +he 214 +ks_ 213 +ö 213 +oo 213 +ju 207 +är 205 +ut 203 +in_ 203 +oli 201 +ki 199 +su 199 +es_ 199 +lt 198 +ist 188 +li_ 186 +ea 186 +vi 184 +im 181 +mu 181 +se_ 180 +ts 180 +on 178 +ise 178 +ta_ 177 +ek 176 +_oli 176 +sel 173 +nud_ 173 +_ü 172 +a. 171 +nn 170 +ema 169 +ng 168 +lu 168 +ge 167 +_si 166 +_ei 165 +_i 165 +_ei_ 164 +ei_ 164 +_r 163 +ole 161 +pa 160 +lle 160 +a._ 160 +ust 159 +du 156 +er 156 +vô 153 +da_ 153 +min 152 +et_ 151 +d,_ 149 +_M 149 +ht 149 +d, 149 +M 149 +kui 148 +_et 147 +K 147 +_K 146 +pe 145 +gi_ 145 +_vô 145 +or 144 +_tu 142 +lt_ 141 +_ma 141 +asi 140 +ve 139 +us_ 138 +ig 136 +sin_ 136 +ur 135 +_ta_ 134 +di 134 +_et_ 134 +s,_ 132 +tas 132 +s, 132 +_kui 131 +sk 131 +re 130 +po 129 +oli_ 129 +om 129 +äi 128 +inu 128 +_na 128 +_oli_ 128 +_sa 128 +aj 128 +mis 127 +ui_ 127 +_me 127 +_pa 126 +tus 125 +pi 125 +te_ 124 +ül 123 +- 123 +est_ 122 +_on 121 +kk 121 +tt 120 +aga 119 +na_ 119 +_T 119 +T 119 +b_ 118 +al_ 118 +sta 118 +_mu 116 +_ju 116 +ida 116 +aks 116 +gu_ 116 +_ni 116 +s. 116 +ad_ 116 +_pe 114 +eks 114 +ev 114 +end 113 +s._ 113 +use 111 +ära 111 +_po 111 +_min 110 +S 110 +aja 110 +_la 110 +ele 109 +el_ 108 +on_ 108 +ab 108 +_S 108 +av 107 +ing 107 +kui_ 106 +_on_ 106 +au 104 +ne_ 104 +ti_ 104 +ell 103 +ae 101 +kô 101 +ed_ 100 +_ke 99 +ata 99 +iis 99 +! 98 +!_ 98 +sid 98 +nda 98 +eh 98 +lle_ 97 +pu 97 +ää 97 +vôi 97 +ine 96 +t, 96 +e,_ 96 +ale 96 +_vôi 96 +t,_ 96 +e, 96 +eda 96 +uk 95 +ast_ 95 +ld 95 +? 94 +_kui_ 94 +_sel 93 +_kô 93 +tul 93 +ega 93 +lg 92 +sii 92 +val 92 +e. 92 +_su 92 +ug 92 +oh 92 +kü 92 +d. 91 +ee_ 91 +see 91 +e._ 91 +öö 91 +oma 91 +_ole 90 +ses 90 +stu 90 +ôt 90 +üü 90 +_om 89 +me_ 89 +ot 89 +d._ 89 +_sii 88 +to 88 +_en 87 +atu 87 +?_ 87 +A 86 +J 86 +pea 86 +jä 85 +_A 85 +_see 85 +ime 84 +_pi 84 +_ha 84 +mô 84 +nä 84 +_J 84 +les 84 +ste 84 +kas 84 +_ä 84 +vä 83 +E 83 +pä 83 +_ve 83 +_E 83 +eis 82 +_jä 81 +_pea 81 +_mô 80 +um 80 +_kü 80 +iku 80 +üd 80 +all 79 +eid 79 +ba 79 +_vä 79 +ina 78 +lj 78 +sid_ 78 +hu 78 +tun 78 +lä 78 +_oma 77 +i,_ 77 +i, 77 +agu 77 +uh 77 +lm 76 +ras 76 +ss 76 +kä 76 +ees 76 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/finnish.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/finnish.lm new file mode 100644 index 0000000..6f5f3b1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/finnish.lm @@ -0,0 +1,400 @@ +_ 19984 +a 9133 +i 8384 +t 7797 +e 6481 +n 6431 +s 5897 +l 4504 +o 4163 +u 4106 +k 4013 +ä 3354 +n_ 2868 +m 2569 +a_ 1987 +v 1905 +r 1827 +ta 1580 +en 1553 +is 1515 +h 1508 +y 1462 +st 1390 +in 1375 +p 1342 +j 1333 +an 1139 +si 1073 +tt 1030 +te 1008 +en_ 982 +_k 980 +it 974 +ll 947 +aa 942 +ä_ 902 +va 878 +el 855 +_t 851 +ka 846 +i_ 835 +. 832 +se 818 +li 806 +tä 804 +oi 767 +ai 744 +._ 739 +tu 734 +_o 719 +mi 715 +al 703 +on 684 +d 681 +_v 662 +et 654 +_j 641 +t_ 635 +ti 632 +_m 628 +_s 620 +ja 616 +ma 596 +sa 595 +la 582 +ist 575 +_e 565 +to 565 +ks 557 +in_ 554 +es 551 +il 538 +an_ 536 +ki 527 +, 525 +ku 525 +,_ 524 +us 520 +as 514 +nt 512 +ri 495 +ke 494 +at 491 +_p 485 +le 484 +ik 483 +ss 477 +ut 469 +ö 469 +sta 460 +ee 459 +uu 458 +ol 457 +ta_ 451 +ne 445 +ää 445 +ei 443 +uo 436 +ko 433 +un 430 +lu 421 +ii 420 +e_ 418 +nn 413 +_h 412 +ar 408 +er 402 +än 396 +ja_ 386 +im 381 +on_ 365 +_va 363 +aan 354 +_a 352 +me 350 +ak 345 +ssa 331 +na 330 +ie 329 +pa 327 +_ja 326 +ia 325 +tä_ 322 +_l 319 +vi 317 +ise 316 +tta 315 +de 314 +os 312 +lli 309 +_ja_ 304 +jo 295 +vä 290 +su 289 +au 287 +lis 286 +_on 285 +sä 284 +uk 280 +am 280 +ot 280 +ty 275 +ett 271 +ttä 270 +ni 269 +lä 267 +ksi 264 +nk 264 +ht 263 +ul 261 +ell 261 +sa_ 259 +ha 257 +sen 257 +a. 254 +isi 253 +ste 253 +aan_ 252 +_on_ 252 +_ka 252 +sk 251 +kk 246 +itt 245 +ok 242 +a._ 239 +all 239 +yt 239 +mä 237 +mu 237 +av 237 +_y 236 +lla 233 +taa 231 +ais 231 +een 230 +K 230 +lt 228 +s_ 227 +ast 227 +iv 226 +ssa_ 225 +ra 225 +- 223 +kse 223 +oit 220 +om 220 +T 219 +_ku 218 +än_ 216 +aa_ 214 +at_ 214 +tel 211 +ui 210 +si_ 208 +rk 207 +sta_ 207 +_jo 203 +kä 202 +_K 201 +est 200 +em 200 +he 199 +_n 199 +vo 198 +_ta 196 +eh 196 +_ol 196 +S 196 +nta 196 +_ko 194 +je 194 +stä 194 +är 193 +ust 191 +mis 191 +ns 190 +pu 189 +nen 188 +ät 188 +toi 188 +iin 187 +ten 187 +min 186 +ista 185 +hd 184 +a, 184 +a,_ 184 +sen_ 183 +E 182 +lle 181 +vat 179 +ill 177 +no 176 +pä 176 +lm 176 +llis 175 +n. 175 +io 172 +ine 171 +n._ 170 +pi 169 +uks 168 +ava 168 +ään 166 +nen_ 165 +ah 165 +_mu 164 +tus 163 +mm 162 +_to 162 +ek 160 +int 159 +_r 159 +lin 158 +oim 158 +_T 158 +A 158 +imi 157 +tö 157 +la_ 157 +jä 157 +aj 156 +yh 155 +o_ 154 +lo 154 +oli 153 +een_ 153 +le_ 153 +_si 153 +g 152 +aik 151 +vat_ 150 +L 149 +ur 149 +ti_ 149 +sia 148 +ite 147 +inen 147 +ain 146 +sti 146 +lla_ 146 +ys 145 +_mi 145 +val 144 +stu 144 +äm 144 +alli 143 +pe 143 +utt 142 +et_ 141 +_tu 141 +eri 140 +_E 140 +: 140 +nki 139 +ir 139 +llä 138 +up 138 +äi 137 +ama 137 +_ha 135 +id 135 +_se 135 +po 134 +inen_ 134 +tte 133 +nna 133 +ten_ 132 +or 132 +ts 131 +nä 131 +yk 131 +äs 131 +_S 130 +ses 130 +ve 130 +ess 129 +äl 129 +ita 129 +lai 129 +H 129 +van 127 +äk 127 +kin 127 +N 127 +_te 126 +den 126 +tee 126 +P 126 +kaa 126 +iin_ 125 +kun 125 +ois 125 +sit 125 +oh 124 +V 124 +yö 124 +äv 124 +tav 124 +voi 124 +ia_ 123 +I 123 +oll 123 +maa 122 +ih 122 +oj 122 +rj 121 +ro 121 +ikk 120 +so 120 +oo 120 +oimi 120 +do 120 +pp 119 +M 119 +_ei 118 +toim 118 +op 118 +uut 118 +tet 118 +_i 118 +_ma 117 +vai 117 +lä_ 116 +u_ 116 +sy 116 +kau 116 +utta 116 +un_ 115 +eu 115 +ssä 115 +tti 115 +_sa 115 +mp 114 +eis 114 +ka_ 112 +että 112 +taa_ 111 +_et 111 +hu 111 +itu 111 +suu 111 +den_ 111 +ksen 110 +ap 110 +_ke 110 +uv 110 +tam 110 +yv 109 +aup 109 +stä_ 109 +asta 109 +äy 109 +kan 108 +nu 108 +ukse 108 +_toi 107 +ien 107 +hi 107 +iss 107 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/french.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/french.lm new file mode 100644 index 0000000..24906c3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/french.lm @@ -0,0 +1,400 @@ +_ 20800 +e 7258 +i 4051 +s 4003 +a 3972 +n 3903 +r 3650 +t 3590 +u 2968 +o 2823 +l 2723 +e_ 2632 +d 2241 +s_ 1721 +_d 1693 +c 1663 +p 1528 +é 1320 +m 1297 +es 1164 +t_ 1106 +_l 1079 +de 1048 +on 959 +_de 940 +en 939 +_p 852 +nt 825 +le 808 +es_ 791 +re 777 +, 721 +,_ 720 +n_ 703 +de_ 685 +' 670 +an 667 +_de_ 645 +v 641 +_s 610 +r_ 596 +_c 594 +er 585 +ai 575 +_a 558 +_e 554 +ou 554 +q 549 +qu 538 +is 530 +te 528 +ti 525 +ur 519 +it 514 +g 498 +a_ 490 +f 480 +la 476 +in 475 +_le 441 +me 436 +nt_ 432 +. 427 +b 427 +ra 423 +io 416 +ent 415 +._ 404 +ne 395 +ns 392 +ion 383 +h 381 +ue 376 +se 371 +le_ 370 +ar 370 +ie 362 +co 361 +at 359 +tr 359 +et 349 +pr 342 +ce 336 +au 328 +u_ 321 +il 314 +_r 313 +_la 304 +un 303 +eu 303 +st 300 +re_ 296 +ro 290 +la_ 288 +on_ 287 +_m 286 +_la_ 283 +que 281 +_qu 280 +_q 280 +po 275 +tio 273 +tion 273 +pa 273 +li 271 +_t 269 +nc 268 +si 266 +_pr 265 +ri 264 +al 263 +ui 262 +_co 259 +i_ 255 +ta 255 +é_ 251 +x 247 +em 244 +l_ 243 +et_ 238 +_l' 236 +l' 236 +les 233 +ns_ 233 +ir 232 +_le_ 228 +ent_ 227 +or 226 +ré 224 +_f 224 +ne_ 222 +à 221 +ve 220 +ch 220 +it_ 219 +di 219 +oi 217 +- 216 +ni 215 +à_ 215 +les_ 215 +d' 214 +el 212 +ss 212 +_n 212 +ut 211 +our 210 +des 210 +" 208 +ur_ 207 +nd 207 +er_ 206 +ait 206 +ion_ 204 +rs 202 +_en 201 +_et 200 +j 200 +_d' 200 +ll 199 +_des 198 +des_ 197 +_pa 197 +té 196 +_et_ 195 +_à 195 +_à_ 195 +om 193 +ma 192 +ati 190 +_des_ 189 +L 188 +so 187 +_u 185 +è 184 +_" 183 +sa 182 +_po 181 +tre 181 +dé 181 +ue_ 180 +pe 179 +en_ 179 +ont 178 +_un 178 +_L 178 +us 176 +_les 176 +_les_ 176 +rt 176 +is_ 173 +_i 173 +du 172 +e,_ 171 +e, 171 +na 171 +s, 170 +s,_ 170 +as 169 +men 169 +M 167 +ait_ 167 +'a 166 +vi 162 +ci 159 +ant 158 +_au 158 +da 157 +_M 157 +ation 155 +atio 155 +con 154 +que_ 153 +ons 153 +eur 151 +est 149 +me_ 149 +mi 149 +par 148 +tion_ 148 +_so 147 +te_ 147 +res 144 +lo 144 +ment 144 +és 144 +ans 143 +_du 142 +du_ 141 +ux 141 +un_ 140 +y 138 +pro 138 +_du_ 136 +_dé 136 +ce_ 135 +_se 134 +_re 134 +pl 133 +A 132 +ge 131 +ic 131 +su 130 +x_ 129 +ien 129 +nce 129 +"_ 129 +ac 128 +il_ 128 +qui 128 +_pro 127 +no 127 +av 126 +_v 125 +_o 125 +rs_ 125 +ans_ 124 +eme 124 +bl 123 +emen 122 +_en_ 122 +iqu 122 +ct 122 +iq 122 +lle 122 +nn 121 +ts 121 +ement 121 +ét 120 +_"_ 120 +ér 119 +té_ 119 +_ce 119 +mp 119 +ire 119 +ui_ 119 +to 118 +he 117 +_é 117 +ca 117 +_j 116 +ec 116 +va 116 +_par 116 +ée 115 +_con 115 +se_ 114 +tre_ 113 +ique 112 +dan 111 +éc 111 +ha 110 +une 110 +P 110 +lu 110 +ux_ 109 +_b 108 +s. 108 +pou 108 +_pou 108 +ier 107 +C 107 +ais 106 +s._ 105 +ain 104 +_un_ 104 +nte 103 +'e 103 +mo 103 +mm 103 +ment_ 102 +une_ 102 +com 101 +_P 101 +'i 101 +_ma 100 +do 99 +ant_ 98 +anc 98 +che 97 +ap 97 +ont_ 97 +_que 97 +os 97 +urs 96 +_di 96 +fi 96 +im 96 +pour 96 +_pour 96 +ê 95 +ts_ 95 +_g 95 +our_ 94 +_sa 94 +ntr 94 +_da 94 +_ré 93 +rai 93 +rm 93 +_qui 93 +e. 92 +am 92 +_com 91 +uv 91 +_C 91 +D 91 +qui_ 90 +e._ 90 +pu 89 +_qui_ 88 +ia 87 +_dan 87 +_dans 87 +dans 87 +ter 87 +fo 87 +son 87 +dans_ 87 +id 86 +ag 86 +ine 86 +tu 85 +ran 85 +au_ 85 +ol 85 +oc 84 +est_ 84 +st_ 84 +enc 84 +F 82 +_tr 81 +'u 81 +tai 81 +ell 80 +R 79 +_su 79 +S 79 +ions 79 +pré 79 +sé 78 +ab 78 +né 77 +_que_ 77 +_in 77 +_av 76 +pour_ 76 +fa 76 +rr 76 +air 75 +_ch 75 +_a_ 75 +ba 74 +_pl 74 +gr 74 +tt 74 +ssi 74 +rd 73 +pas 73 +bi 73 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/georgian.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/georgian.lm new file mode 100644 index 0000000..5219115 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/georgian.lm @@ -0,0 +1,400 @@ +_ 14926 +À 7221 +È 5780 +Ä 4137 +Ð 2966 +Ñ 2908 +Ë 2607 +Ê 2372 +Í 2260 +Å 2080 +à 2078 +Ì 2005 +Ç 1598 +Á 1383 +Ó 1363 +È_ 1248 +À_ 1149 + 1145 +ÊÈ 1009 +Þ 974 +_Ë 965 +Ñ_ 964 +ÃÀ 912 +ÈÑ 901 +ÀÐ 897 +Ø 820 +. 813 +ÄÁ 767 +" 762 +._ 735 +, 720 +,_ 718 +ÑÀ 684 +_À 669 +Ú 653 +ËÀ 631 +ÀÌ 622 +ÄÊ 575 +ÐÈ 570 +ÅÄ 567 +Õ 551 +_à 550 +Ò 542 +_Ñ 526 +É 518 +ÀË 517 +ÅÀ 485 +ÅÈ 479 +ÂÀ 478 +_ 474 +ÓÊ 468 +_È 436 +ÐÀ 435 +ÀÅ 420 +ËÈ 419 +ÌÈ 418 +ÄÐ 416 +ÄÌ 412 +ÈÑ_ 407 +_ÃÀ 404 +ÃÀ_ 393 +ÀÊ 384 +ËÍ 382 +Ü 376 +_" 374 +ÊÈ_ 371 +× 369 +ÐÍ 364 +ÀÑ 360 +ÈÇ 358 +Àà 353 +ÌÀ 349 +Ô 349 +ÁÀ 342 +Æ 341 +ËÄ 335 +ÈÀ 334 +ÈÊ 332 +ÐÇ 326 +_Ð 322 +ÁÈ 321 +ØÈ 319 +_Ä 319 +_Ø 319 +ÃÄ 317 +_ÂÀ 316 +ÇÀ 316 +ÄÑ 306 +Ä_ 299 +_Ç 288 +ÐÄ 279 +ÓÊÈ 273 +ÊÍ 271 +Ö 270 +Ì_ 267 +ÌÄ 267 +_ÑÀ 266 +ÍÁ 263 +ÓÐ 260 +Ç_ 256 +ÄÊÈ 255 +ÃÈ 238 +ÊÄ 238 +ÑÈ 234 +ÊÀ 233 +ÍÐ 230 +ÈÌ 229 +_Þ 227 +"_ 225 +ÄÁÈ 224 +: 224 +:_ 223 +È. 221 +_ÃÀ_ 217 +Û 215 +ÞÄ 213 +È, 213 +È,_ 212 +_Ó 211 +Í_ 209 +_ËÀ 208 +ÈÑÀ 208 +ÍË 206 +_ÀÐ 204 +ÇÅ 203 +ÀÐÇ 203 +ØÄ 203 +È._ 201 +À. 200 +- 193 +ÀÞ 192 +ÅÄÊ 192 +Ú_ 189 +Èà 188 +Ù 188 +ÕÀ 187 +Ã_ 185 +ÈÊÈ 183 +Äà 179 +À._ 177 +Ð_ 177 +Íà 174 +ÞÀ 174 +ÈÐ 173 +Ìà 172 +_ÐÍ 172 +ÍÑ 172 +ÄÁÀ 171 +_ËÍ 170 +ÐÈ_ 170 +_ËÈ 170 +_Ü 169 +ÇÈ 166 +ÁÄ 166 +_Õ 165 +ØÈ_ 165 +ÄÑ_ 163 +ÀÈ 162 +_ØÄ 160 +ÄÅ 158 +_É 155 +ÀÚ 154 +ÊÈÑ 153 +Î 151 +Ë_ 149 +ÕÀÐ 148 +À,_ 147 +À, 147 +ÀÇ 147 +À 145 +ÕÀÐÇ 145 +È 143 +ËÀÐ 143 +ÍÊ 143 +ÀÊÈ 142 +ÂÈ 142 +ÌÄÁ 141 +ÄË 140 +ÀØ 139 +ÓÊÈ_ 139 +ÄÇ 139 +ÇÓ 138 +_Ì 136 +ÈÇ_ 135 +ÀÐÈ 133 +ÀÌ_ 132 +ÊÄÁ 131 +×Í 130 +ÑÄ 130 +ÈË 130 +ÐÄÁ 128 +ÀÕ 125 +ÆÄ 125 +ÔÄ 125 +Ê_ 124 +ÀÅÈ 124 +ÀÃ_ 124 +ÅÈÑ 123 +_ËÄ 123 +ÀËÈ 122 +_ÕÀ 121 +ÉÈ 121 +_Å 120 +×Å 120 +ÍÅ 116 +_Á 114 +ÀÌÈ 113 +ÀËÍ 113 +ÂÀÌ 113 +ÍÌ 112 +ÉÀ 112 +ÈÚ 112 +ØÀ 112 +ÀÐÀ 111 +ÁÓ 111 +ÞÅ 109 +ÀÖ 109 +ÂÍ 107 +ÁÀ_ 107 +ÌÈ_ 107 +ÅÀÐ 107 +ÄÊÈ_ 106 +Ðà 106 +ÀÐ_ 106 +_ÀË 105 +ß 104 +ÄÐÇ 104 +_ÄÐ 104 +ÅÄÌ 103 +_ÄÑ 103 +ÐÍË 103 +ÄÌÈ 103 +_Ú 103 +ÁÍ 102 +_Ù 102 +ËÈÑ 102 +ÐÈÑ 102 +ÞÍ 102 +_ÐÍË 101 +_ÕÀÐ 101 +ÈÅ 100 +_ÕÀÐÇ 100 +ÓÐÈ 99 +ÒÈ 99 +ÂÄ 99 +ÈÒ 99 +ÀÀ 97 +ÀÒ 97 +ÁÓÊ 96 +ÕÅ 94 +ÈÄ 94 +_ÇÀ 94 +Ñ,_ 93 +ÐÑ 93 +ÅÊ 93 +_ØÀ 93 +Ñ, 93 +_ÑÈ 93 +ÀÉ 93 +ÀÆ 92 +ÍÁÀ 92 +ÀÑ_ 92 +ÌÍ 91 +ÄÁÓ 91 +ÇÕ 91 +ËÓ 90 +ÄÌ_ 90 +ÇÀÅ 89 +ÄÁÓÊ 89 +ÊÑ 89 +ÀØÈ 89 +ÃÄÁ 89 +ÀÁ 89 +È" 89 +Ñ. 88 +ÚÞ 88 +ÂÀË 88 +ÍÑ_ 87 +_ÄÐÇ 87 +È× 87 +ÁÈÑ 87 +ÌÃÀ 87 +ØÅ 87 +ÞÄÊ 87 +ÁÈÇ 85 +ÑÀ_ 85 +ÇÅÄ 85 +ÓÌ 85 +ÒÀ 85 +_Î 84 +ÊÈ. 84 +_ÐÀ 83 +Ñ._ 83 +_Ô 83 +_ÂÀË 83 +ÊÈÀ 83 +ÊÈ._ 82 +ÄÐÈ 82 +ÈÀ_ 82 +ÈÀÌ 82 +ÜÈ 81 +ÀÚ_ 81 +"Ë 81 +ÈÓ 80 +_"Ë 80 +ÐÇÅ 80 +_ÄÑ_ 79 +_È 79 +ÀÓ 79 +ÈÕ 79 +ÀÐÇÅ 79 +ÇÈ_ 79 +ÑÀÞ 79 +ÐÇÓ 78 +ÊÈ, 78 +ÚÈ 78 +ÞÈ 78 +ÐÇÓÊ 78 +ÇÓÊ 78 +ÊÈ,_ 78 +ÀÃÀ 78 +ÁÑ 78 +_ÀÐ_ 77 +ÞÊ 77 +ÐÓ 77 +ÀÐÇÓÊ 77 +_ÌÀ 77 +ÅÈÇ 77 +ÈÂÈ 77 +ÀÐÇÓ 77 +ÜÀ 76 +ÅÀ_ 75 +_ÞÀ 75 +ÉÅ 75 +ÒÄ 75 +ÐÀ_ 75 +ÅÀÊ 75 +ÇÅÄÊ 74 +ÐÇÅÄ 74 +ÀÐÇÅÄ 74 +ÄÁÀ_ 74 +ÐË 73 +ÑÞ 73 +ÑÒ 73 +ÅÑ 73 +ÑÓ 73 +ÐÇÅÄÊ 73 +ËÞ 73 +ÍÊÍ 72 +ÐÚ 72 +_× 72 +ÂÐ 71 +ÅÄ_ 71 +ÒÍ 71 +ÇÄ 71 +Í 71 +ÅÄÁ 71 +ÕÀÐÇÓ 71 +ÐÀà 70 +ÀË_ 70 +Åà 69 +ËÀ_ 69 +ÍÄ 69 +_ÀÐÀ 67 +à 67 +ÄÃÀ 67 +ÇÀÌ 67 +È×Í 67 +ÕÀÐÇÅ 67 +Ò× 67 +ÂÀËÍ 66 +_ÂÀËÍ 66 +ÄÒ 66 +ÍÃÀ 66 +ÅÄÊÈ 66 +ÀÌÀ 66 +ÄÁÈÇ 66 +_ÈÂÈ 66 +ÄÊÍ 65 +Ä 65 +ËÈÊ 65 +ÊË 65 +ÈÊÈ_ 65 +ÍÁÈ 65 +ÅÐ 65 +_ÈÑ 64 +Ó_ 63 +Ëà 63 +", 63 +ÃÍ 63 +ÊÍÁ 63 +ÂÅ 63 +à63 +ÄÍ 62 +À" 62 +ÀÅÀ 62 +? 62 +",_ 62 +! 62 +_È× 62 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/german.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/german.lm new file mode 100644 index 0000000..6f14f51 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/german.lm @@ -0,0 +1,400 @@ +_ 31586 +e 15008 +n 9058 +i 7299 +r 6830 +t 5662 +s 5348 +a 4618 +h 4176 +d 4011 +er 3415 +en 3412 +u 3341 +l 3266 +n_ 2848 +c 2636 +ch 2460 +g 2407 +o 2376 +e_ 2208 +r_ 2128 +m 2077 +_d 1948 +de 1831 +en_ 1786 +ei 1718 +er_ 1570 +in 1568 +te 1505 +ie 1505 +b 1458 +t_ 1425 +f 1306 +k 1176 +ge 1144 +s_ 1137 +un 1113 +, 1104 +,_ 1099 +w 1099 +z 1060 +nd 1039 +he 1004 +st 989 +_s 952 +_de 949 +. 909 +_e 906 +ne 906 +der 880 +._ 847 +be 841 +es 829 +ic 796 +_a 791 +ie_ 779 +is 769 +ich 763 +an 755 +re 749 +di 732 +ein 730 +se 730 +" 720 +ng 709 +_i 706 +sc 683 +sch 681 +it 673 +der_ 652 +h_ 651 +ch_ 642 +S 630 +le 609 +p 609 +ä 607 +ü 603 +au 603 +v 602 +che 599 +_w 596 +d_ 585 +die 576 +_di 572 +m_ 562 +_die 559 +el 548 +_S 540 +_der 529 +li 527 +_der_ 523 +si 515 +al 514 +ns 507 +on 501 +or 495 +ti 490 +ten 487 +ht 486 +die_ 485 +_die_ 483 +D 479 +rt 478 +nd_ 476 +_u 470 +nt 468 +A 466 +in_ 464 +den 461 +cht 447 +und 443 +me 440 +_z 429 +ung 426 +ll 423 +_un 421 +_ei 419 +_n 415 +hr 412 +ine 412 +_A 408 +_ein 405 +ar 404 +ra 403 +_v 400 +_g 400 +as 395 +zu 392 +et 389 +em 385 +_D 380 +eine 376 +gen 376 +g_ 376 +da 368 +we 366 +K 365 +lt 360 +B 354 +_" 353 +nde 349 +ni 347 +und_ 345 +E 345 +ur 345 +_m 342 +ri 341 +ha 340 +eh 339 +ten_ 338 +es_ 336 +_K 336 +_und 335 +ig 335 +_b 335 +hen 334 +_und_ 332 +_au 329 +_B 327 +_da 325 +_zu 324 +_in 322 +at 321 +us 318 +wi 307 +n, 305 +n,_ 304 +nn 304 +te_ 301 +eit 301 +_h 300 +ter 299 +M 298 +n. 295 +ß 294 +ng_ 289 +sche 289 +- 283 +rs 282 +den_ 282 +_si 280 +G 280 +im 278 +_ge 277 +chen 276 +rd 273 +_E 273 +n._ 270 +icht 270 +rn 268 +uf 267 +isch 264 +isc 264 +nen 263 +_in_ 262 +_M 260 +_er 257 +ich_ 255 +ac 253 +lic 252 +_G 252 +ber 252 +la 251 +vo 251 +eb 250 +ke 249 +F 248 +as_ 248 +hen_ 248 +ach 245 +en, 244 +ung_ 243 +lich 243 +ste 243 +en,_ 243 +_k 241 +ben 241 +_f 241 +en. 241 +_be 239 +it_ 239 +L 238 +_se 237 +mi 236 +ve 236 +na 236 +on_ 236 +P 235 +ss 234 +ist 234 +ö 234 +ht_ 233 +ru 233 +st_ 229 +_F 229 +ts 227 +ab 226 +W 226 +ol 225 +_eine 225 +hi 225 +so 224 +em_ 223 +"_ 223 +ren 222 +en._ 221 +chen_ 221 +R 221 +ta 221 +ere 220 +ische 219 +ers 218 +ert 217 +_P 217 +tr 217 +ed 215 +ze 215 +eg 215 +ens 215 +ür 213 +ah 212 +_vo 212 +ne_ 211 +cht_ 210 +uc 209 +_wi 209 +nge 208 +lle 208 +fe 207 +_L 207 +ver 206 +hl 205 +V 204 +ma 203 +wa 203 +auf 201 +H 198 +_W 195 +T 195 +nte 193 +uch 193 +l_ 192 +sei 192 +nen_ 190 +u_ 189 +_den 189 +_al 189 +_V 188 +t. 188 +lte 187 +ut 186 +ent 184 +sich 183 +sic 183 +il 183 +ier 182 +am 181 +gen_ 180 +sen 179 +fü 178 +um 178 +t._ 177 +f_ 174 +he_ 174 +ner 174 +nst 174 +ls 174 +_sei 173 +ro 173 +ir 173 +ebe 173 +mm 173 +ag 172 +ern 169 +t,_ 169 +t, 169 +eu 169 +ft 168 +icht_ 167 +hre 167 +Be 166 +nz 165 +nder 165 +_T 164 +_den_ 164 +iche 163 +tt 163 +zu_ 162 +and 162 +J 161 +rde 160 +rei 160 +_we 159 +_H 159 +ige 159 +_Be 158 +rte 157 +hei 156 +das 155 +aus 155 +che_ 154 +_das 154 +_zu_ 154 +tz 154 +_ni 153 +das_ 153 +_R 153 +N 153 +des 153 +_ve 153 +_J 152 +I 152 +_das_ 152 +men 151 +_so 151 +_ver 151 +_auf 150 +ine_ 150 +_ha 150 +rg 149 +ind 148 +eben 148 +kt 147 +mit 147 +_an 147 +her 146 +Ge 146 +Sc 145 +_sich 145 +U 145 +Sch 145 +_sic 145 +end 145 +Di 144 +abe 143 +ck 143 +sse 142 +ür_ 142 +ell 142 +ik 141 +o_ 141 +nic 141 +nich 141 +sa 141 +_fü 140 +hn 140 +zi 140 +no 140 +nicht 140 +im_ 139 +von_ 139 +von 139 +_nic 139 +_nich 139 +eine_ 139 +oc 138 +wei 138 +io 138 +schen 138 +gt 138 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/greek-utf.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/greek-utf.lm new file mode 100644 index 0000000..bd45893 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/greek-utf.lm @@ -0,0 +1,400 @@ +_ 89284 +α 19666 +Ï„ 16086 +ο 15826 +ε 14848 +ι 12766 +ν 12189 +Ï€ 8776 +σ 8653 +Ï 8399 +κ 7761 +μ 7529 +Ï… 6850 +ά 6284 +_Ï„ 5918 +λ 5802 +Ï‚ 5371 +α_ 5272 +η 5236 +έ 4739 +ί 4609 +ÏŒ 4489 +το 4461 +Ï‚_ 4111 +ου 4075 +ι_ 4033 +ε_ 4019 +. 3916 +_κ 3897 +ο_ 3836 +._ 3810 +ν_ 3661 +_Ï€ 3414 +_σ 3333 +" 3247 +_μ 3242 +_το 3118 +, 3106 +,_ 3068 +γ 3058 +_α 2912 +ω 2689 +να 2593 +δ 2455 +τα 2420 +χ 2411 +κα 2406 +στ 2406 +_ε 2353 +- 2335 +-_ 2192 +Ï 2171 +αν 2162 +τη 2151 +ή 2141 +Ï…_ 2133 +αι 2100 +θ 2053 +φ 1989 +ου_ 1974 +ει 1889 +_κα 1882 +εί 1864 +το_ 1802 +πο 1771 +αι_ 1727 +σε 1709 +_ν 1647 +_" 1619 +η_ 1609 +ια 1602 +να_ 1518 +τι 1501 +ον 1501 +του 1495 +με 1460 +_του 1407 +_έ 1405 +_στ 1396 +ÏŽ 1364 +πε 1359 +τε 1300 +μα 1298 +β 1274 +Ïι 1252 +ÏŒ_ 1241 +_δ 1231 +ξ 1223 +ντ 1220 +_το_ 1196 +απ 1187 +Ïο 1184 +_γ 1183 +_τη 1177 +ζ 1158 +_εί 1150 +ά_ 1150 +_να 1124 +έν 1115 +και 1110 +_και 1093 +αν_ 1082 +Ïα 1078 +και_ 1061 +_να_ 1060 +_και_ 1053 +μπ 1049 +νο 1048 +ατ 1036 +ιο 1024 +ια_ 1018 +ÎµÏ 1003 +Î¿Ï 993 +_απ 984 +σε_ 974 +ικ 973 +_ο 967 +εν 947 +ος 936 +ει_ 935 +πό 901 +λο 892 +_με 890 +νε 884 +του_ 871 +ον_ 869 +ας 865 +_του_ 854 +ασ 841 +με_ 840 +σα 834 +κο 833 +Î±Ï 832 +Ï€Ï 824 +ίν 820 +κά 808 +_πο 804 +πι 796 +Κ 796 +μέ 783 +μο 777 +Î­Ï 772 +αλ 766 +ην 762 +Îœ 759 +ισ 745 +κε 742 +τα_ 740 +στο 738 +ω_ 730 +ην_ 728 +Ο 717 +Τ 714 +_φ 711 +ετ 705 +δε 704 +πα 697 +ας_ 688 +τά 684 +ος_ 683 +_ÏŒ 680 +_Κ 675 +οι 671 +_χ 670 +την 663 +την_ 658 +_στο 647 +ή_ 645 +πό_ 638 +_θ 633 +_ο_ 631 +", 630 +_Ï€Ï 626 +_Îœ 624 +ίπ 624 +άν 623 +",_ 623 +από 620 +που 619 +ότ 618 +λα 617 +τον 617 +_από 616 +μι 612 +Ο_ 611 +Ïε 607 +Ï…Ï„ 604 +λε 595 +_λ 594 +ÏÏŒ 590 +_με_ 586 +ιά 580 +τον_ 577 +γι 577 +_Ο 575 +από_ 572 +Î¬Ï 570 +πά 570 +_από_ 569 +Ïά 562 +ταν 554 +ένα 553 +υν 552 +που_ 551 +δι 547 +Ï„Ï 547 +Ï„ÏŒ 544 +_β 540 +χε 536 +εν_ 534 +ησ 528 +_Ο_ 525 +ης 520 +". 519 +_που 516 +_Τ 515 +"._ 513 +τη_ 512 +Ï‚. 510 +είπ 508 +ταν_ 504 +_είπ 503 +Ï‚._ 501 +_τα 500 +ξε 497 +στο_ 496 +λλ 493 +ακ 492 +Α 491 +_που_ 490 +άλ 489 +ίπε 489 +είπε 485 +_είπε 483 +_την 483 +τι_ 482 +_την_ 481 +άτ 480 +λι 480 +_δε 479 +άμ 477 +_στο_ 475 +σο 473 +_ά 468 +"_ 463 +μέν 463 +ιν 461 +ις 452 +_αν 452 +κό 451 +αυ 451 +_τον 450 +_γι 449 +θα 447 +ες 446 +ση 446 +_μι 445 +_τον_ 443 +ε. 441 +ε._ 441 +ους 439 +λά 439 +Ï…Ï‚ 439 +ολ 438 +πιο 437 +Î¿Ï 432 +_πα 428 +_κά 427 +τε_ 427 +αμ 423 +; 423 +_μο 422 +σκ 421 +της 421 +_ξ 418 +στη 415 +Κά 411 +νη 408 +για 405 +α. 403 +ÎºÏ 402 +κι 402 +Ï‚, 402 +Ï‚,_ 401 +α._ 398 +ηκ 397 +_Κά 397 +ελ 396 +_έν 395 +_ή 393 +_μα 392 +ία 391 +ως 391 +λη 390 +ίνα 389 +πί 389 +μου 388 +μά 388 +_αυ 387 +ης_ 386 +συ 384 +ναι 384 +Π 383 +αυτ 382 +ί_ 376 +μπι 375 +ίσ 372 +_της 370 +_τα_ 367 +_για 365 +_ένα 362 +_μπ 361 +θε 361 +ιον 359 +ις_ 358 +τή 358 +_θα 354 +_αυτ 354 +άμπ 352 +κ. 352 +κ._ 351 +είν 351 +ομ 350 +ίναι 348 +ντα 348 +ναι_ 348 +ως_ 347 +χα 346 +Ε 346 +Ï…. 346 +για_ 346 +Ï…._ 345 +δεν 345 +ένα_ 345 +α, 344 +α,_ 344 +δεν_ 344 +ÏÏ 343 +όν 343 +α- 342 +Ïσ 341 +_κ. 340 +στε 339 +Κάμ 339 +_κ._ 339 +τέ 339 +α-_ 338 +ευ 338 +ιλ 338 +Ïί 338 +Κάμπ 338 +_μου 338 +_Κάμ 338 +_Κάμπ 337 +υμ 336 +σει 336 +πιον 336 +μπιον 336 +μπιο 336 +_κο 334 +Κάμπι 334 +_η 334 +άμπι 334 +θα_ 333 +νι 332 +της_ 331 +ψ 331 +όμ 330 +ησε 330 +_σα 329 +μα_ 328 +ός 328 +Σ 326 +_δεν 325 +_δεν_ 325 +σμ 324 +ες_ 324 +Ï€ÎµÏ 324 +ίχ 323 +ίναι_ 323 +τικ 322 +_Ï 321 +άμπιο 321 +Ï…Ï‚_ 321 +ους_ 321 +_πε 321 +σω 320 +_για_ 320 +Ï€Ïο 320 +γε 318 +;" 316 +;"_ 316 +Δ 315 +Ï„Ï… 314 +Ïα_ 313 +_συ 312 +Ïω 312 +_θα_ 310 +όσ 309 +ου. 309 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/hungarian.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/hungarian.lm new file mode 100644 index 0000000..0b5a0d9 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/hungarian.lm @@ -0,0 +1,400 @@ +_ 19186 +e 5753 +a 4627 +t 4522 +s 3480 +l 3437 +n 3137 +k 3036 +i 2527 +r 2437 +z 2399 +o 2303 +á 2039 +é 1995 +g 1978 +m 1695 +y 1338 +_a 1256 +b 1186 +d 1148 +a_ 1108 +v 1057 +t_ 901 +sz 889 +el 832 +, 819 +,_ 818 +h 792 +k_ 769 +. 767 +et 743 +gy 711 +s_ 705 +_m 702 +_a_ 695 +en 671 +ö 662 +n_ 646 +_k 645 +j 623 +._ 613 +i_ 606 +eg 601 +p 586 +_e 580 +u 579 +le 576 +ó 542 +er 495 +f 485 +ek 477 +te 477 +és 473 +_s 471 +al 464 +ta 458 +í 453 +_h 444 +_t 442 +an 426 +ze 425 +me 406 +at 405 +l_ 401 +es 395 +õ 387 +y_ 381 +z_ 375 +tt 374 +ke 372 +_v 369 +ás 368 +ak 367 +_é 365 +ny 363 +tá 359 +c 358 +re 350 +to 347 +A 343 +e_ 340 +ü 332 +ne 330 +os 326 +ál 320 +_f 320 +az 317 +zt 317 +ár 317 +_n 315 +ko 312 +_A 303 +_sz 302 +is 301 +ve 299 +gy_ 297 +ít 293 +_b 293 +ra 291 +or 289 +ol 284 +_i 281 +em 279 +_l 274 +la 264 +ez 262 +be 260 +lt 260 +ok 260 +ye 256 +_me 252 +on 251 +en_ 247 +ar 245 +_az 245 +in 243 +án 242 +se 242 +ég 238 +egy 237 +ha 237 +r_ 237 +té 237 +ér 235 +sze 233 +én 226 +ly 224 +g_ 221 +" 221 +ll 219 +iz 214 +de 214 +ek_ 213 +mi 212 +rt 211 +ba 209 +ho 209 +A_ 209 +és_ 209 +az_ 205 +va 204 +ag 203 +ka 202 +na 202 +og 201 +ik 201 +nt 200 +_A_ 199 +ô 199 +- 198 +tt_ 198 +_az_ 197 +ni 195 +cs 194 +ki 190 +kö 187 +át 187 +_eg 187 +nd 186 +fe 185 +_és 185 +lá 182 +bi 181 +nk 180 +_le 179 +an_ 179 +_és_ 177 +tás 175 +ké 174 +meg 173 +_egy 172 +ma 171 +as 170 +sa 170 +sí 169 +ge 167 +ot 167 +za 167 +E 166 +m_ 165 +_meg 165 +_el 165 +bb 164 +ro 164 +zá 163 +he 162 +má 161 +sé 160 +_r 160 +sít 160 +tos 159 +ti 159 +st 158 +_j 158 +él 157 +it 156 +_ho 156 +ül 156 +_ha 155 +vé 154 +am 152 +oz 152 +ele 151 +ya 151 +zto 150 +ú 149 +biz 147 +so 147 +et_ 145 +izto 144 +izt 144 +ap 141 +"_ 141 +ed 141 +ss 140 +bizt 140 +ék 140 +bizto 140 +iztos 139 +ét 139 +ztos 139 +osít 138 +zet 138 +osí 138 +mé 137 +_is 137 +t, 136 +tosít 136 +tosí 136 +t,_ 136 +ó_ 135 +agy 135 +ztosí 135 +li 134 +om 134 +_fe 134 +ere 133 +ág 133 +t. 132 +nek 131 +vi 129 +_d 129 +zo 128 +k,_ 128 +k, 128 +_kö 127 +_p 127 +M 126 +let 126 +ak_ 125 +já 125 +ett 125 +û 124 +si 124 +ész 123 +_E 123 +ép 123 +vá 123 +rá 123 +t._ 123 +is_ 123 +S 123 +ítás 122 +ítá 122 +kor 121 +ai 121 +fel 120 +da 120 +_mi 120 +pe 119 +ogy 118 +ban 118 +ad 117 +ga 116 +_va 116 +ott 114 +_ne 114 +_ki 113 +ör 113 +zé 112 +ben 112 +_te 111 +zi 111 +sá 110 +ség 109 +do 109 +tó 108 +em_ 108 +_" 108 +_ta 108 +_M 107 +ogy_ 107 +_á 107 +k. 106 +ól 105 +_ke 105 +_g 104 +: 103 +gye 102 +ák 102 +hog 102 +ri 102 +mo 101 +ok_ 101 +:_ 101 +hogy 101 +il 101 +el_ 100 +zer 100 +ete 99 +nn 99 +nak 98 +je 98 +sítá 98 +szá 98 +yo 98 +osítá 98 +sítás 98 +_ké 98 +_hog 98 +lé 97 +_S 97 +_hogy 97 +ig 97 +_- 96 +hogy_ 96 +ban_ 96 +ese 95 +_bi 94 +fo 94 +ja 94 +ul 94 +õ_ 94 +k._ 94 +_c 93 +ká 91 +es_ 91 +ná 91 +ény 91 +gé 91 +ás_ 91 +egy_ 90 +áb 90 +rd 89 +I 89 +ány 89 +_biz 89 +_fel 88 +öv 88 +ala 88 +szer 88 +po 88 +_ma 88 +leg 88 +tö 88 +ket 87 +un 87 +di 87 +ai_ 87 +nek_ 87 +rm 86 +tal 86 +év 85 +_is_ 85 +nem 85 +ti_ 84 +öz 84 +szt 84 +ut 83 +ter 83 +dé 83 +kk 83 +or_ 83 +b_ 82 +né 82 +os_ 82 +re_ 82 +rs 82 +_bizt 82 +min 82 +ben_ 81 +ra_ 81 +ik_ 81 +go 80 +len 80 +lm 80 +öt 80 +ely 80 +aj 80 +öl 80 +_sze 80 +_be 79 +ev 79 +ré 79 +ssz 79 +nt_ 79 +gya 79 +K 79 +si_ 79 +sza 78 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/icelandic.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/icelandic.lm new file mode 100644 index 0000000..b1fe0f2 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/icelandic.lm @@ -0,0 +1,400 @@ +_ 26104 +a 6496 +r 6044 +n 5160 +i 5123 +s 3987 +e 3891 +u 3582 +t 3300 +ð 3126 +l 3071 +g 2726 +m 2459 +k 2256 +f 2230 +r_ 1967 +v 1641 +ar 1472 +ð_ 1420 +_s 1332 +á 1248 +o 1221 +í 1197 +a_ 1155 +in 1150 +i_ 1114 +h 1023 +j 975 +d 974 +st 929 +að 925 +. 922 +n_ 875 +._ 875 +_v 874 +m_ 854 +nn 842 +_f 840 +ur 824 +_a 806 +ó 785 +_h 782 +æ 779 +ið 771 +er 765 +um 727 +g_ 716 +y 711 +_e 709 +þ 672 +b 672 +ir 671 +ri 670 +an 667 +ö 650 +_á 648 +að_ 645 +u_ 633 +na 631 +í_ 625 +ar_ 622 +_þ 608 +á_ 606 +_í 595 +ta 567 +ei 566 +la 558 +_m 549 +_í_ 549 +um_ 547 +t_ 535 +ti 529 +_o 524 +ur_ 523 +_að 519 +ið_ 512 +ði 496 +ve 494 +og 494 +ú 482 +og_ 479 +_og 478 +_og_ 478 +nd 469 +p 464 +ra 455 +un 454 +ir_ 452 +_að_ 451 +ni 439 +en 439 +ðu 439 +_á_ 436 +ng 434 +il 404 +ga 395 +_t 395 +nu 393 +ki 392 +ja 383 +inn 379 +_b 375 +sk 352 +s_ 350 +vi 349 +rð 347 +ða 345 +ef 339 +ag 336 +_u 330 +se 324 +lu 324 +af 321 +_ve 320 +tu 318 +em 307 +eg 304 +nn_ 303 +_l 303 +va 301 +_k 296 +, 295 +ns 292 +re 292 +tt 291 +,_ 291 +l_ 286 +am 286 +es 285 +yr 285 +al 281 +da 277 +S 275 +gu 273 +_se 271 +ver 268 +_g 266 +ing 266 +_n 262 +is 258 +_er 257 +sa 256 +ður 255 +le 255 +_st 255 +_S 254 +sem 254 +ll 254 +me 253 +ha 251 +li 249 +kk 249 +rs 247 +_vi 247 +rn 246 +sl 244 +gi 243 +ss 242 +rf 241 +fy 240 +ði_ 240 +mi 238 +ka 237 +ma 231 +ld 230 +é 229 +rir 227 +sta 227 +fyr 227 +ví 227 +di 226 +ru 224 +var 224 +_fy 222 +ku 221 +em_ 221 +nar 220 +_sem_ 220 +_sem 220 +sem_ 220 +he 219 +yri 217 +_fyr 216 +si 216 +yrir 215 +au 212 +er_ 212 +ek 211 +_ha 210 +þe 209 +fyri 207 +fyrir 207 +_þe 205 +fi 204 +fr 203 +ge 201 +or 200 +ne 200 +ann 198 +jó 198 +_va 196 +_fyri 196 +_ver 194 +fl 192 +_er_ 191 +_um 189 +ík 188 +til 187 +_he 186 +fa 186 +il_ 182 +_ti 178 +_til 177 +gar 176 +_var 176 +na_ 176 +ý 175 +eð 171 +fu 170 +nni 169 +_me 168 +ki_ 167 +við 166 +ey 165 +fn 165 +arf 164 +til_ 163 +st_ 162 +_til_ 162 +þa 161 +num 161 +_þa 161 +as 160 +_við 160 +rt 159 +el 158 +uð 156 +inn_ 155 +_um_ 154 +ra_ 153 +bæ 153 +tar 151 +ta_ 151 +erð 151 +ór 148 +and 148 +_sa 146 +ig 146 +_en 146 +nga 145 +rir_ 145 +us 144 +jar 143 +et 143 +ár 142 +_sk 140 +ndi 140 +æð 139 +var_ 139 +_r 138 +av 138 +æk 137 +nna 137 +ður_ 136 +ál 136 +ko 135 +nin 135 +við_ 135 +ól 135 +ins 134 +ik 133 +E 133 +K 133 +yrir_ 133 +ns_ 133 +on 133 +ein 132 +_við_ 132 +ög 132 +já 132 +Þ 132 +öl 132 +ðs 132 +_mi 131 +f_ 131 +sí 131 +sj 131 +stu 131 +nda 130 +_var_ 130 +gr 129 +ús 128 +tæ 127 +ri_ 126 +haf 126 +_sí 125 +vík 124 +rin 124 +te 124 +r. 124 +r._ 123 +H 123 +nes 123 +ót 123 +ru_ 123 +kr 122 +F 122 +ær 121 +num_ 121 +k_ 121 +a. 121 +_H 121 +_fr 120 +_ge 120 +rá 120 +_E 120 +_Þ 120 +ug 120 +ngu 119 +an_ 119 +inga 118 +_K 118 +_haf 118 +enn 117 +ars 117 +rið 117 +en_ 117 +sin 116 +kur 116 +it 116 +ða_ 116 +ti_ 115 +rði 114 +tj 114 +ni_ 114 +at 114 +tarf 114 +br 113 +slu 113 +kki 113 +rg 113 +má 113 +kv 113 +_en_ 113 +a._ 112 +gar_ 112 +du 112 +ju 110 +eið 110 +und 110 +lag 110 +tur 110 +ega 109 +hú 109 +íð 109 +gn 109 +hef 109 +kj 109 +_hef 109 +_sta 108 +B 108 +V 108 +sam 107 +_ei 106 +_B 106 +ft 106 +ga_ 106 +G 106 +_G 105 +lö 105 +kki_ 105 +star 104 +in_ 104 +R 104 +með 104 +_ár 103 +_með 103 +ekk 103 +inu 103 +tö 103 +_V 103 +m. 103 +aði 103 +jö 102 +æj 102 +_bæ 102 +ess 102 +hús 101 +ut 101 +gs 101 +aví 101 +mu 101 +_R 101 +_ú 101 +rst 100 +æjar 100 +leg 100 +æja 100 +ja_ 99 +avík 99 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/italian.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/italian.lm new file mode 100644 index 0000000..d9cda09 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/italian.lm @@ -0,0 +1,400 @@ +_ 25028 +a 7570 +e 6477 +i 5481 +o 5104 +l 3905 +n 3866 +r 3502 +t 2934 +c 2862 +s 2862 +a_ 2504 +e_ 2404 +d 2004 +i_ 1749 +o_ 1679 +u 1650 +v 1611 +p 1561 +m 1414 +_c 1325 +, 1192 +,_ 1192 +_s 1190 +_d 1094 +g 1067 +an 925 +er 915 +_a 914 +_p 895 +la 858 +_l 830 +re 799 +ar 769 +h 762 +no 753 +co 726 +va 698 +_e 657 +n_ 656 +on 656 +ra 653 +to 651 +f 638 +di 638 +_i 634 +ch 634 +ll 633 +l_ 624 +la_ 598 +ta 593 +el 576 +in 567 +_m 558 +en 529 +b 528 +ri 525 +_co 523 +_n 523 +_di 522 +li 513 +av 507 +al 501 +le 494 +ia 492 +se 484 +ol 479 +_f 477 +or 477 +te 469 +_e_ 467 +ve 454 +at 449 +de 447 +. 443 +ne 429 +va_ 428 +ca 426 +._ 422 +tt 422 +re_ 415 +nt 415 +io 411 +_v 407 +pe 405 +z 392 +to_ 391 +_ch 389 +na 384 +si 384 +' 383 +he 382 +no_ 379 +ci 374 +_la 373 +ro 371 +_g 370 +st 368 +cc 366 +he_ 362 +di_ 362 +ma 358 +ev 354 +che 354 +es 352 +me 352 +pa 351 +_t 349 +ti 348 +_di_ 347 +ss 345 +che_ 344 +a,_ 337 +a, 337 +nd 335 +o, 333 +o,_ 333 +ell 330 +gl 323 +sa 322 +il 322 +gli 321 +da 318 +as 318 +do 314 +_che 308 +_che_ 306 +eva 306 +_la_ 300 +lla 298 +le_ 293 +un 291 +_pe 290 +_de 288 +q 283 +qu 283 +ava 280 +po 277 +on_ 275 +r_ 273 +li_ 273 +_b 269 +_il 268 +_il_ 268 +il_ 268 +lo 267 +om 263 +e, 263 +e,_ 263 +ni 258 +tr 258 +so 255 +ra_ 253 +os 251 +_in 249 +_u 248 +per 244 +are 243 +et 243 +_se 240 +ano 239 +si_ 238 +_ca 238 +_qu 238 +lla_ 238 +_q 238 +_a_ 236 +ac 236 +_r 234 +ic 233 +_no 232 +ie 227 +fa 227 +hi 226 +del 225 +ua 222 +_per 218 +ce 218 +_ma 216 +sc 216 +_del 215 +mi 212 +_un 208 +chi 206 +era 205 +i, 205 +i,_ 205 +su 203 +and 202 +vo 202 +_fa 201 +eva_ 200 +ano_ 199 +gli_ 197 +non 196 +pi 196 +vi 195 +er_ 195 +_al 194 +se_ 193 +_ne 192 +_non 191 +am 190 +is 187 +ava_ 187 +_non_ 186 +non_ 186 +in_ 185 +ent 185 +_si 184 +_pa 184 +com 183 +! 182 +_le 182 +_su 181 +uo 181 +el_ 180 +!_ 180 +l' 178 +ue 177 +te_ 177 +_com 177 +are_ 176 +pr 176 +_in_ 176 +van 172 +mo 172 +ta_ 171 +gn 167 +ere 166 +na_ 166 +tto 163 +it 161 +_per_ 161 +per_ 161 +é 161 +all 160 +ess 159 +ut 159 +col 158 +acc 157 +gi 155 +lo_ 154 +oc 154 +vano 153 +io_ 153 +_av 151 +ndo 151 +é_ 151 +ato 149 +ave 148 +_st 147 +me_ 147 +'a 146 +ia_ 144 +con 143 +mp 143 +fi 142 +ett 142 +_si_ 141 +_pi 140 +era_ 140 +ti_ 140 +ó 140 +vano_ 140 +_gl 139 +qua 139 +ella 139 +sta 138 +ome 137 +S 137 +_gli 137 +_S 137 +ad 136 +_ve 134 +ant 134 +ne_ 134 +ó_ 133 +sp 133 +do_ 133 +_po 132 +ro_ 132 +ov 132 +_le_ 131 +ella_ 130 +sse 129 +_con 128 +ir 128 +_vi 128 +ig 127 +_gli_ 127 +_ave 127 +vev 127 +un_ 126 +ot 126 +veva 125 +dell 125 +que 125 +a. 125 +_o 125 +a._ 124 +tu 124 +cia 123 +za 123 +_que 123 +_da 121 +par 121 +_pr 120 +cch 120 +_dell 120 +eg 119 +_sa 119 +o._ 119 +o. 119 +_col 118 +lt 118 +_un_ 118 +rt 118 +ur 117 +_vo 117 +_me 117 +ome_ 117 +L 116 +ap 116 +_L 116 +zi 116 +nto 116 +og 115 +_an 115 +_so 115 +em 114 +ag 114 +be 111 +ni_ 111 +im 110 +cchi 110 +ver 110 +lle 109 +nz 109 +cci 109 +_ri 109 +nc 108 +_er 108 +come_ 107 +come 107 +aveva 107 +ui 107 +avev 107 +tto_ 107 +_come 106 +ed 106 +P 105 +man 105 +_P 105 +rs 105 +occ 104 +ndo_ 103 +ato_ 103 +_qua 103 +_era 103 +ari 102 +ba 100 +_mo 100 +nel 100 +id 99 +men 98 +_fi 98 +_all 98 +rr 97 +_do 97 +_avev 97 +att 97 +l'a 96 +ei 96 +zz 96 +; 96 +vol 95 +pp 95 +tra 95 +;_ 95 +ere_ 94 +lle_ 94 +nda 94 +utt 94 +est 93 +_nel 93 +ul 92 +ola 92 +iv 92 +ando 90 +ale 90 +lu 90 +rn 90 +e. 89 +e._ 89 +ll' 89 +tta 88 +nte 87 +_l' 87 +uel 87 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/latin.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/latin.lm new file mode 100644 index 0000000..177cd35 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/latin.lm @@ -0,0 +1,400 @@ +_ 20136 +e 6892 +i 5604 +a 5443 +u 4581 +t 4552 +s 4354 +r 3923 +n 3375 +m 3063 +o 2921 +c 2224 +l 1805 +e_ 1625 +s_ 1503 +p 1424 +d 1397 +, 1285 +,_ 1276 +er 1077 +qu 1028 +q 1028 +a_ 1019 +t_ 1018 +is 942 +_a 921 +re 902 +m_ 891 +v 858 +b 821 +um 808 +_s 773 +us 772 +en 766 +nt 733 +in 729 +ue 727 +te 720 +g 718 +_i 710 +_p 679 +it 676 +_c 669 +et 653 +que 652 +_e 643 +at 643 +ue_ 616 +ra 614 +que_ 611 +f 601 +or 598 +ri 576 +ti 572 +ta 559 +tu 552 +an 551 +ae 527 +_m 513 +am 501 +_t 493 +us_ 488 +is_ 487 +es 479 +em 479 +_f 451 +um_ 443 +_v 442 +ia 442 +li 438 +_d 436 +. 432 +i_ 430 +et_ 429 +ni 412 +ne 409 +h 406 +de 404 +ur 396 +._ 392 +ar 388 +os 388 +mi 382 +pe 382 +la 376 +st 371 +s, 368 +di 367 +_et 366 +s,_ 365 +_in 363 +on 360 +o_ 359 +_n 351 +_et_ 351 +as 346 +im 336 +na 327 +se 320 +ma 315 +cu 307 +vi 306 +si 303 +ro 303 +r_ 302 +su 299 +un 295 +_l 291 +to 291 +ec 290 +ci 288 +co 287 +_r 287 +ere 286 +ce 284 +tr 280 +re_ 278 +ent 275 +x 275 +ct 274 +ve 271 +ru 259 +ul 256 +me 255 +ui 255 +c_ 252 +_o 250 +ic 249 +ns 247 +_qu 242 +_q 242 +no 241 +ant 235 +am_ 235 +_co 233 +sa 231 +ca 230 +t, 226 +mu 225 +t,_ 225 +_re 223 +el 222 +ib 222 +id 218 +om 212 +_te 211 +al 209 +le 209 +it_ 208 +mo 208 +ol 206 +_u 203 +; 199 +_h 199 +ac 198 +;_ 198 +bu 197 +nu 196 +ua 195 +n_ 195 +ll 194 +tis 191 +A 189 +rt 188 +ge 188 +nd 187 +au 187 +lu 186 +iu 185 +squ 185 +per 185 +sq 185 +ter 185 +pa 183 +_A 183 +em_ 183 +ia_ 180 +ed 179 +_pe 178 +m, 176 +sque 175 +_su 175 +ae_ 175 +m,_ 175 +pr 175 +bi 175 +bus 174 +_vi 174 +os_ 173 +ta_ 172 +mqu 171 +mq 171 +ss 170 +sque_ 169 +ibu 167 +ad 166 +ibus 165 +I 164 +nte 163 +ra_ 163 +mque 162 +_de 162 +po 161 +_se 160 +ere_ 160 +nc 160 +qua 159 +T 159 +lo 157 +oc 156 +mque_ 156 +_T 155 +_pa 155 +_pr 155 +tem 154 +bus_ 152 +nti 149 +rum 149 +er_ 149 +ab 148 +ir 148 +da 147 +_ve 146 +ibus_ 146 +ex 146 +ut 145 +pi 145 +tur 145 +_ca 143 +_me 142 +es_ 142 +gi 142 +te_ 141 +_I 141 +vo 141 +do 141 +_si 140 +tus 139 +il 137 +_ar 136 +du 133 +nt_ 133 +uc 133 +fa 132 +as_ 132 +rr 131 +ba 130 +_ad 128 +ne_ 127 +_ma 127 +ens 127 +gn 126 +s. 126 +y 126 +min 125 +ris 124 +in_ 123 +tum 123 +P 123 +_g 123 +mp 123 +e, 122 +io 122 +_P 122 +ea 122 +hi 122 +e,_ 121 +era 120 +sc 120 +_la 120 +qui 120 +unt 120 +fe 119 +_in_ 118 +_no 118 +ore 118 +iam 118 +va 117 +tis_ 117 +s._ 117 +at_ 117 +eri 116 +d_ 116 +con 115 +fu 115 +pu 114 +cum 114 +ub 114 +ng 114 +ine 113 +_au 113 +: 113 +_di 112 +ag 111 +_con 111 +ect 111 +i, 111 +equ 111 +i,_ 111 +be 111 +eq 111 +_po 110 +so 110 +:_ 110 +nis 109 +ha 109 +uo 109 +_fa 108 +na_ 107 +ip 107 +is, 107 +_cu 106 +cr 106 +ate 105 +is,_ 105 +ig 105 +tor 105 +rat 104 +_qua 103 +eg 103 +a, 103 +a,_ 102 +tra 102 +_mo 101 +sp 101 +mis 100 +itu 100 +D 99 +ali 99 +eb 99 +eni 99 +_sa 98 +ie 98 +imu 98 +_ex 97 +_D 96 +res 95 +est 94 +tri 94 +ene 94 +_mi 94 +str 94 +enti 93 +t. 92 +av 92 +_per 91 +ur_ 91 +ora 91 +lt 91 +umqu 90 +_vo 90 +umq 90 +up 89 +t._ 88 +quo 88 +_ne 88 +gen 88 +rum_ 87 +tqu 87 +tq 87 +_fu 86 +ep 86 +ma_ 86 +umque 86 +it,_ 85 +ine_ 85 +it, 85 +men 85 +mus 84 +ort 83 +ven 83 +ina 83 +us,_ 83 +us, 83 +tque 82 +_ge 82 +per_ 82 +mor 82 +inc 82 +are 81 +tus_ 81 +_an 81 +rim 81 +tque_ 81 +ot 81 +ani 80 +H 80 +_tu 80 +ho 80 +tem_ 80 +u_ 80 +ser 79 +um,_ 79 +um, 79 +S 79 +ten 79 +ver 79 +sti 79 +ntu 78 +fer 78 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/latvian.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/latvian.lm new file mode 100644 index 0000000..6fcf8be --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/latvian.lm @@ -0,0 +1,400 @@ +_ 24504 +a 8735 +i 7353 +s 6064 +t 5176 +e 4390 +r 4339 +u 4200 +n 3422 +â 3055 +m 2817 +p 2755 +k 2703 +o 2643 +s_ 2595 +d 2131 +l 2035 +j 1972 +î 1958 +ie 1887 +v 1822 +as 1530 +u_ 1396 +_p 1380 +b 1357 +z 1311 +ç 1267 +a_ 1261 +as_ 1217 +. 1065 +, 1048 +,_ 1033 +g 1010 +ar 970 +ð 965 +ti 962 +c 922 +_a 876 +ja 838 +st 828 +_i 822 +_v 805 +pa 792 +_t 775 +._ 774 +um 760 +_k 749 +â_ 734 +_n 728 +es 712 +i_ 706 +at 703 +is 695 +_s 680 +ai 649 +ta 635 +an 631 +ka 621 +r_ 615 +îb 586 +ij 585 +_u 568 +_pa 548 +un 541 +no 539 +va 537 +ma 525 +ra 522 +ri 515 +iz 512 +in 509 +vi 508 +pr 506 +sa 487 +ju 486 +tâ 483 +ik 473 +n_ 472 +am 454 +en 452 +tie 440 +na 432 +ða 430 +tu 420 +ija 420 +ir 419 +o_ 415 +m_ 414 +li 411 +ci 409 +ku 404 +mi 401 +_no 398 +ek 398 +_un 397 +t_ 395 +_l 394 +un_ 393 +_d 393 +ot 392 +_un_ 392 +ies 391 +ar_ 388 +nâ 387 +da 387 +ei 385 +em 382 +_ti 382 +pi 380 +al 368 +ba 356 +ts 355 +_iz 353 +ap 350 +jas 349 +ko 346 +au 345 +ðan 339 +re 339 +ni 337 +kâ 328 +ro 327 +et 326 +rî 325 +ga 323 +mu 322 +jas_ 321 +tr 317 +_va 312 +te 310 +_pr 307 +sp 298 +sk 297 +ne 295 +îba 293 +âs 289 +ijas 287 +_ar 283 +la 283 +to 282 +ad 280 +dz 278 +îg 277 +tî 277 +çj 277 +_sa 277 +jâ 274 +_m 273 +ties 273 +lî 272 +ijas_ 269 +_at 269 +ed 267 +_pi 267 +ò 267 +s, 265 +s,_ 265 +çr 261 +gu 258 +f 258 +si 257 +mâ 256 +nt 254 +tu_ 254 +_r 253 +ru 252 +âj 251 +jum 251 +âs_ 250 +ât 249 +iem 248 +_b 248 +_vi 245 +par 244 +pie 244 +rt 243 +vç 242 +_ne 240 +âr 240 +ai_ 239 +_. 239 +_j 237 +us 237 +_ka 236 +er 232 +bas 232 +_tie 232 +_par 230 +di 229 +û 228 +ms 228 +âd 226 +îbas 224 +om 220 +bu 219 +umu 217 +iek 216 +kt 216 +it 216 +râ 215 +_ko 214 +ana 211 +âk 211 +or 210 +de 210 +inâ 207 +dî 204 +ur 203 +pri 203 +_c 202 +ta_ 202 +bas_ 201 +es_ 201 +_pie 200 +il 200 +os 199 +ðana 199 +id 198 +L 198 +_ie 197 +bi 194 +ak 194 +ja_ 194 +îbas_ 193 +çt 192 +îbu 192 +_g 191 +ï 189 +ma_ 189 +ien 188 +kum 187 +— 187 +_ir 186 +on 186 +_ties 185 +zî 185 +ce 185 +ied 184 +ist 183 +ts_ 183 +_— 183 +—_ 182 +âm 181 +vie 180 +_—_ 180 +cij 180 +ka_ 179 +_ap 175 +sî 174 +ir_ 174 +zi 174 +uma 173 +âl 172 +_ir_ 172 +oð 171 +_da 169 +î_ 168 +arî 168 +) 167 +do 166 +ve 166 +( 165 +ls 165 +bu_ 164 +val 164 +mu_ 164 +isk 163 +uz 161 +av 160 +par_ 160 +_vç 159 +_par_ 158 +vçr 158 +_ar_ 157 +rie 157 +_uz 157 +aj 156 +îbu_ 156 +oj 155 +kâ_ 155 +ld 154 +iet 154 +iku 154 +ks 153 +du 153 +ep 153 +ms_ 152 +ec 152 +V 151 +ais 150 +str 150 +nie 149 +am_ 149 +ums 148 +_( 147 +ju_ 146 +z_ 142 +ru_ 142 +îj 142 +gum 142 +u,_ 141 +u, 141 +iò 141 +uma_ 141 +çrt 141 +îgu 141 +me 140 +dâ 140 +ît 140 +ent 139 +ikum 138 +pâ 138 +em_ 138 +_L 138 +lie 136 +sta 136 +rî_ 136 +lst 136 +eik 135 +se 135 +s. 134 +pro 134 +rs 134 +s._ 134 +tik 134 +lç 134 +ska 133 +pap 133 +kas 133 +rm 133 +âju 133 +pî 132 +nu 132 +T 132 +pç 131 +tei 131 +nas 131 +_V 131 +jo 131 +lîg 131 +ut 131 +iem_ 130 +ras 129 +pu 129 +_li 129 +_ga 128 +dar 128 +_kâ 128 +umu_ 127 +îv 126 +îgum 126 +kas_ 126 +tîb 125 +vai 125 +lîgu 125 +P 125 +arî_ 125 +ev 124 +lai 124 +îr 124 +lîgum 124 +tv 123 +að 123 +_arî_ 122 +_arî 122 +_vie 121 +S 121 +_T 120 +îju 120 +teik 120 +cija 119 +rb 119 +_ð 119 +jâ_ 119 +nas_ 118 +tâj 118 +vçrt 118 +iec 118 +_la 117 +îd 116 +_vai 116 +îjum 116 +vien 116 +als 116 +_lî 116 +apîr 115 +rts 115 +isi 115 +pîr 115 +papî 115 +papîr 115 +apî 115 +tsp 115 +mç 114 +im 114 +be 114 +is_ 114 +alst 114 +_ja 114 +rtspa 113 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/lithuanian.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/lithuanian.lm new file mode 100644 index 0000000..982f3dc --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/lithuanian.lm @@ -0,0 +1,400 @@ +_ 23070 +i 8196 +a 7763 +s 5179 +e 3458 +o 3425 +u 3371 +t 3344 +r 3240 +n 3070 +k 3019 +l 2060 +p 1889 +s_ 1756 +m 1680 +d 1640 +v 1590 +, 1501 +,_ 1497 +ó 1400 +g 1302 +j 1200 +o_ 1138 +. 1128 +ai 1113 +÷ 1075 +_p 1047 +_k 1035 +i_ 990 +._ 984 +as 975 +b 937 +au 903 +is 863 +_n 815 +ka 811 +si 804 +_s 799 +ia 796 +ý 759 +ta 735 +ie 731 +ti 728 +y 721 +_t 711 +in 697 +_i 686 +us 675 +pa 658 +ir 640 +ar 633 +ù 620 +_a 617 +r_ 609 +ne 583 +a_ 578 +ri 569 +_v 558 +_pa 541 +al 540 +ra 531 +li 522 +Ý 509 +u_ 493 +vi 490 +_ka 489 +da 487 +_ne 482 +_j 481 +en 478 +ù_ 445 +os 444 +ki 442 +õ 441 +an 440 +ik 434 +ma 433 +as_ 430 +st 420 +_d 420 +ai_ 417 +s,_ 396 +am 396 +is_ 396 +s, 396 +_ir 390 +jo 387 +ir_ 385 +at 384 +_ir_ 383 +i÷ 381 +ni 377 +ga 376 +_b 367 +na 366 +e_ 365 +to 352 +pr 337 +_g 332 +_m 332 +û 328 +ß 326 +io 323 +ei 323 +Ý_ 321 +su 320 +ßi 320 +uo 319 +la 317 +er 303 +va 299 +vo 298 +ýi 293 +es 291 +- 290 +ó_ 286 +-_ 285 +_vi 284 +_- 283 +ko 283 +_-_ 283 +iau 281 +sa 278 +s. 278 +iu 276 +et 274 +nu 265 +ja 262 +õ_ 262 +_ta 262 +s._ 259 +el 258 +ój 258 +os_ 256 +im 255 +it 254 +_pr 253 +no 252 +av 251 +ur 251 +_÷ 248 +mi 246 +ve 245 +ak 245 +ku 243 +ek 241 +tu 241 +_ý 241 +ad 241 +ñ 238 +_l 238 +_i÷ 236 +us_ 236 +_su 232 +oj 231 +au_ 231 +ba 224 +nt 218 +me 214 +te 210 +jo_ 208 +ro 205 +ós 204 +iù 203 +tai 203 +_õ 201 +ló 201 +pas 200 +ip 198 +iai 197 +di 195 +usi 194 +vo_ 193 +kai 190 +i, 189 +i,_ 189 +sk 187 +_r 186 +aus 184 +ap 183 +gi 182 +mo 182 +uk 181 +t_ 180 +_da 177 +be 176 +ien 176 +o, 174 +il 174 +o,_ 173 +ti_ 173 +re 172 +_nu 171 +ßia 171 +_pas 169 +pri 169 +÷_ 169 +ok 168 +dó 166 +ól 162 +bu 161 +÷i 160 +on 160 +asi 159 +id 158 +ul 157 +ji 157 +aip 156 +ia_ 155 +_sa 154 +ot 154 +gal 153 +nk 153 +om 152 +p_ 151 +_pri 151 +od 151 +vis 150 +_at 150 +vie 150 +uv 150 +ab 150 +iù_ 149 +ama 149 +nó 149 +A 149 +sta 148 +kr 148 +_A 145 +ais 144 +rt 143 +J 142 +_J 142 +ójo 142 +_õ_ 141 +K 140 +_K 139 +pi 139 +avo 139 +ng 139 +mas 138 +du 138 +ug 137 +_ga 137 +ol 136 +tik 135 +ali 135 +.. 135 +_vis 135 +iek 134 +ini 133 +kad 133 +a, 133 +le 133 +kó 133 +T 133 +tó 132 +i. 132 +_T 131 +dý 131 +a,_ 131 +go 131 +ip_ 131 +aip_ 131 +ró 129 +a÷ 129 +dýi 129 +ke 128 +k_ 128 +d_ 127 +ad_ 127 +_ti 127 +_ma 126 +_va 125 +i._ 124 +z 123 +÷k 123 +iau_ 121 +m_ 120 +kar 119 +um 119 +tù 119 +_kad 118 +uý 117 +tr 117 +_kai 117 +as, 116 +og 116 +kad_ 116 +as,_ 116 +_ji 116 +rie 115 +yt 114 +_ja 114 +_ko 114 +vó 114 +ys 114 +jau 113 +ar_ 113 +pra 112 +aý 112 +ant 112 +kl 111 +tas 111 +gu 111 +_ku 110 +si_ 110 +pe 109 +eb 109 +N 109 +ójo_ 108 +_kad_ 108 +se 108 +_ki 108 +or 107 +ly 107 +lo 107 +iai_ 107 +_la 106 +ts 106 +ñs 106 +ig 105 +_N 105 +ut 105 +_u 105 +ós_ 105 +avo_ 104 +ie_ 104 +a. 104 +kt 104 +em 103 +do 103 +je 102 +ks 102 +ats 101 +_be 101 +ris 101 +l_ 101 +_vie 101 +tin 101 +ag 100 +dam 100 +_st 100 +a._ 99 +_bu 99 +? 99 +V 98 +io_ 98 +kas 98 +_jo 98 +vien 97 +_gal 97 +ót 97 +kia 97 +lia 96 +c 96 +uri 96 +_V 96 +?_ 96 +uvo 95 +ru 95 +ty 95 +ep 94 +nd 94 +lai 94 +_tai 94 +ju 93 +man 92 +o. 92 +buv 92 +tÝ 92 +_÷i 91 +i÷_ 91 +_i÷_ 91 +i÷k 90 +o._ 90 +_to 90 +bi 90 +up 89 +po 89 +rs 89 +_prie 88 +ù,_ 88 +aik 88 +ui 88 +_tik 88 +ij 88 +ù, 88 +pat 88 +prie 88 +I 87 +ies 87 +tai_ 87 +n_ 87 +pasi 87 +ius 87 +÷t 87 +eik 86 +_me 86 +ina 86 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/norwegian.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/norwegian.lm new file mode 100644 index 0000000..8c27ca2 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/norwegian.lm @@ -0,0 +1,400 @@ +_ 22970 +e 6833 +n 4206 +r 3516 +t 3112 +a 2587 +s 2440 +i 2112 +l 1901 +o 1900 +n_ 1875 +r_ 1761 +k 1713 +g 1630 +en 1615 +m 1508 +e_ 1450 +d 1444 +er 1436 +h 1306 +t_ 1300 +_h 1180 +_s 1148 +er_ 1105 +v 982 +en_ 976 +an 919 +. 901 +._ 791 +_. 781 +et 770 +g_ 762 +_._ 726 +å 725 +u 719 +f 709 +p 702 +ha 682 +_ha 672 +de 657 +te 651 +_e 621 +et_ 614 +re 581 +ne 565 +_o 554 +an_ 544 +ke 534 +_, 522 +,_ 522 +, 522 +_,_ 522 +_f 519 +_m 515 +or 503 +_d 483 +_i 480 +å_ 479 +se 476 +m_ 469 +nn 454 +b 449 +me 441 +ø 434 +_a 413 +st 404 +_t 398 +og 380 +_v 377 +_og 366 +ar 364 +el 364 +le 361 +i_ 356 +om 353 +og_ 351 +_og_ 351 +li 350 +_k 346 +_de 339 +ge 339 +han 337 +y 333 +_han 332 +ve 330 +kk 323 +in 311 +_b 307 +fo 301 +j 301 +il 298 +_H 291 +H 291 +han_ 288 +_han_ 288 +for 287 +ik 281 +l_ 278 +kke 277 +tt 276 +ti 270 +ne_ 270 +d_ 269 +ed 269 +om_ 268 +nne 266 +_me 264 +ng 257 +_er 257 +_fo 256 +eg 256 +_se 256 +_g 256 +un 255 +ig 255 +sk 253 +_er_ 252 +_p 252 +_for 250 +ke_ 249 +_n 238 +_l 233 +al 232 +ør 222 +s_ 221 +ar_ 215 +at 214 +_en 211 +he 211 +pe 209 +_i_ 208 +am 200 +es 200 +si 200 +enn 197 +det 195 +or_ 193 +vi 190 +ns 189 +ikk 188 +det_ 185 +so 185 +un_ 183 +il_ 181 +nd 181 +te_ 181 +"_ 180 +" 180 +_"_ 180 +_" 180 +em 179 +_ti 176 +kke_ 176 +lig 174 +ten 174 +Ha 173 +_Ha 173 +re_ 172 +ikke 168 +je 165 +Han 165 +ter 165 +_Han 165 +eg_ 164 +på 164 +_på 163 +_si 163 +_å 163 +_Han_ 162 +Han_ 162 +på_ 162 +_på_ 161 +til 160 +som 160 +_so 159 +den 159 +_det 157 +ed_ 155 +ll 155 +_ik 155 +rt 155 +som_ 153 +ra 152 +a_ 152 +har 152 +nt 152 +de_ 152 +tr 151 +v_ 151 +_har 151 +ka 151 +ig_ 150 +_som 150 +for_ 150 +_som_ 150 +_en_ 149 +hu 149 +_ikk 148 +_ham 148 +ham 148 +ste 148 +_det_ 148 +_ikke 148 +enne 148 +ikke_ 148 +har_ 147 +nge 147 +D 147 +_har_ 147 +_D 147 +am_ 147 +ere 147 +ham_ 146 +_ham_ 146 +it 145 +_he 144 +_til 144 +av 143 +va 140 +men 140 +år 140 +_ve 140 +_hu 139 +ta 139 +pen 137 +sp 137 +_st 135 +tte 135 +la 135 +_E 133 +E 133 +den_ 130 +is 130 +til_ 128 +_r 128 +tt_ 128 +år_ 127 +k_ 124 +_å_ 124 +ri 124 +_til_ 124 +at_ 123 +ene 123 +seg 123 +_av 123 +med 122 +_vi 122 +_seg 122 +seg_ 121 +_seg_ 121 +_for_ 120 +nne_ 120 +ut 120 +_u 119 +mm 119 +mme 119 +De 118 +_De 118 +_at 118 +_hun 117 +hun 117 +ko 117 +be 116 +_at_ 115 +ter_ 115 +pen_ 114 +ker 113 +hun_ 113 +_hun_ 113 +on 111 +lig_ 111 +.. 110 +hen 107 +_med 107 +rs 106 +ser 106 +med_ 105 +_men 104 +_hen 104 +_sk 104 +_med_ 104 +ak 103 +ans 103 +ker_ 102 +av_ 101 +_ka 101 +no 100 +ver 100 +ler 99 +J 99 +spe 99 +ten_ 99 +_J 99 +ene_ 98 +ld 98 +hv 98 +_av_ 98 +ger 97 +ni 96 +gen 96 +ie 95 +ser_ 94 +_et 94 +spen 94 +_hv 94 +men_ 93 +Espe 92 +Es 92 +_Esp 92 +_Es 92 +_Espe 92 +Esp 92 +_al 92 +Espen 92 +lle 89 +rem 89 +id 89 +fø 89 +ei 88 +inn 88 +rd 88 +enne_ 88 +_henn 87 +henne 87 +henn 87 +kt 86 +spen_ 86 +_om 86 +ler_ 86 +da 86 +ett 86 +itt 86 +bl 85 +to 85 +_Je 84 +ger_ 84 +Je 84 +æ 84 +ma 83 +ing 83 +ær 83 +ns_ 83 +eli 82 +ang 82 +_be 82 +så 82 +_den 82 +pp 81 +rk 81 +dr 81 +oe 81 +ss 81 +_fø 80 +ek 80 +le_ 79 +_no 79 +kj 78 +elig 78 +nes 78 +nn_ 77 +nk 77 +fr 77 +sl 77 +my 77 +kan 77 +så_ 76 +as 76 +_om_ 76 +_kan 75 +_ko 75 +_bl 73 +Hu 73 +nen 73 +_Hu 73 +eng 73 +gj 73 +rt_ 72 +ge_ 72 +ba 72 +lv 71 +rer 71 +nde 71 +ls 70 +lo 70 +ga 70 +_noe 70 +ro 70 +_den_ 70 +_ut 70 +noe 70 +Hun 69 +Hun_ 69 +_in 69 +_Hun 69 +_Hun_ 69 +ren 68 +øre 68 +ør_ 68 +sen 68 +sa 67 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/polish.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/polish.lm new file mode 100644 index 0000000..4490de6 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/polish.lm @@ -0,0 +1,400 @@ +_ 31480 +a 7945 +i 7766 +e 7462 +o 6838 +z 5104 +n 5077 +r 4178 +w 4139 +s 3596 +c 3580 +y 3569 +t 3381 +d 3027 +k 2819 +p 2639 +m 2494 +ie 2484 +u 2016 +l 1947 +j 1932 +ni 1930 +e_ 1746 +_p 1712 +³ 1649 +a_ 1496 +o_ 1431 +, 1368 +,_ 1366 +b 1296 +_w 1257 +g 1249 +i_ 1140 +. 1118 +_s 1045 +ze 1041 +._ 1035 +_n 997 +nie 958 +cz 956 +rz 952 +h 950 +_z 933 +ê 918 +ow 911 +ie_ 902 +y_ 899 +na 885 +ch 871 +po 864 +pr 863 +wi 851 +st 847 +¿ 835 +± 832 +an 814 +ó 800 +ra 778 +zy 766 +ia 726 +za 718 +_t 699 +wa 692 +ro 692 +_d 683 +_pr 675 +¶ 661 +w_ 658 +sz 652 +_po 649 +_o 628 +m_ 613 +li 613 +dz 611 +ki 611 +en 609 +mi 593 +ta 571 +ci 564 +ej 562 +nie_ 558 +_m 553 +_k 549 +ar 543 +go 541 +_i 540 +em 532 +od 525 +yc 520 +a³ 511 +rze 508 +do 504 +eg 503 +ko 502 +ac 482 +to 478 +_na 467 +_ni 467 +h_ 466 +ch_ 466 +æ 465 +iê 461 +_b 458 +on 458 +u_ 458 +zi 454 +ka 450 +er 448 +sk 447 +si 447 +wy 444 +te 437 +ak 434 +ê_ 431 +_j 429 +je 429 +z_ 427 +ny 422 +aw 422 +ne 420 +ów 418 +_w_ 415 +_c 414 +ego 412 +prz 412 +_r 410 +al 407 +³a 405 +" 405 +re 405 +es 401 +_nie 396 +dzi 394 +ty 389 +j_ 380 +ic 380 +_prz 379 +ad 367 +ej_ 364 +le 359 +æ_ 358 +ed 354 +ych 346 +_za 346 +_do 344 +zn 344 +go_ 344 +ani 343 +_i_ 342 +no 339 +or 337 +³o 336 +tr 334 +P 330 +os 329 +am 329 +da 328 +ec 327 +ol 325 +±_ 325 +by 322 +ego_ 321 +at 321 +¿e 319 +ym 317 +wie 314 +³_ 312 +- 310 +na_ 309 +_si 303 +W 301 +as 301 +wo 300 +pa 299 +siê 295 +nia 293 +owa 292 +o¶ 286 +_P 283 +el 282 +_siê 279 +ja 278 +rzy 276 +prze 276 +_wy 275 +iê_ 269 +in 267 +_- 267 +de 267 +kie 267 +dn 264 +ob 262 +_u 261 +ych_ 260 +-_ 258 +ez 257 +_-_ 256 +¶c 255 +ws 255 +¶ci 254 +em_ 253 +_siê_ 253 +siê_ 253 +_nie_ 253 +kt 252 +ski 252 +we 251 +_g 251 +_W 250 +t_ 249 +_prze 249 +_je 248 +aj 247 +_a 247 +¿e_ 246 +_¿ 244 +ia_ 243 +eni 241 +om 240 +la 240 +k_ 235 +mo 235 +f 234 +pi 232 +is 231 +cze 231 +_z_ 230 +ñ 228 +nt 227 +ce 224 +sta 221 +ry 220 +ma 219 +cj 219 +zie 218 +ek 216 +oc 213 +dy 212 +owi 208 +sp 208 +K 208 +tó 205 +_" 204 +ud 203 +S 202 +ier 202 +pra 202 +czn 201 +ys 200 +nia_ 199 +j± 198 +_¿e 196 +oz 194 +N 192 +zo 191 +dzie 190 +ku 190 +ów_ 189 +czy 189 +_mi 188 +_¿e_ 187 +mie 186 +do_ 186 +iej 185 +ym_ 185 +_do_ 184 +cy 184 +_pa 183 +y³ 182 +_na_ 181 +zy_ 181 +ew 180 +_l 180 +_cz 178 +_by 178 +ru 177 +to_ 175 +±c 175 +_wi 175 +ln 174 +_K 171 +ok 170 +ot 170 +raw 169 +nych 168 +nyc 168 +az 168 +ik 167 +bi 167 +i,_ 166 +i, 166 +_te 165 +tu 163 +wan 163 +et 162 +J 162 +ór 161 +cie 160 +_od 160 +ba 160 +oj 159 +o¶c 158 +i³ 158 +_ro 158 +og 158 +mu 158 +A 158 +o¶ci 158 +d_ 157 +tw 156 +io 155 +gr 155 +_J 155 +_N 155 +_to 155 +us 155 +¿_ 154 +aæ 154 +ach 154 +yd 153 +_kt 153 +_ko 152 +_st 152 +pow 151 +yt 150 +kr 149 +_S 149 +a³_ 149 +ak_ 149 +li_ 148 +T 148 +ur 148 +sa 148 +op 147 +yw 147 +ent 147 +bo 146 +_sp 145 +O 145 +a,_ 144 +a, 144 +iem 144 +któ 143 +praw 143 +wn 142 +tór 142 +i± 141 +³y 141 +zu 141 +dni 140 +im 139 +icz 139 +ró 139 +³e 138 +któr 137 +my 137 +est 136 +awi 135 +przy 134 +nych_ 134 +e,_ 132 +e, 132 +ki_ 132 +pro 131 +_któ 131 +_któr 131 +_przy 130 +_ja 129 +szy 127 +ia³ 127 +Po 127 +ania 127 +M 126 +ze_ 125 +ne_ 125 +ñs 124 +_ty 124 +sze 124 +a¿ 124 +nn 124 +pod 124 +aæ_ 122 +B 122 +za_ 122 +cza 122 +³o_ 122 +Z 122 +_to_ 121 +iu 120 +zc 119 +esz 119 +skie 118 +i. 118 +_ka 117 +so 117 +trz 117 +o¿ 116 +ieg 116 +nik 116 +ga 116 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/portuguese.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/portuguese.lm new file mode 100644 index 0000000..4034154 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/portuguese.lm @@ -0,0 +1,400 @@ +_ 35328 +a 10423 +e 10132 +o 8919 +s 6795 +r 6033 +i 5443 +n 4588 +d 4531 +t 4217 +m 3476 +u 3404 +o_ 3240 +a_ 3029 +e_ 2879 +c 2756 +s_ 2461 +_d 2379 +l 2307 +p 2242 +_a 1753 +de 1751 +, 1660 +,_ 1658 +_e 1454 +es 1447 +os 1412 +ra 1343 +_p 1328 +nt 1302 +_de 1248 +do 1215 +en 1176 +re 1150 +as 1123 +v 1115 +m_ 1113 +de_ 1096 +er 1082 +g 1053 +_c 1047 +da 1008 +co 986 +os_ 975 +te 974 +ar 950 +or 943 +q 938 +qu 938 +_s 908 +ta 902 +_de_ 901 +_o 858 +se 841 +ue 831 +to 799 +ad 777 +. 761 +que 752 +em 751 +an 748 +f 746 +r_ 745 +b 732 +st 718 +is 716 +al 712 +_qu 706 +_q 706 +in 701 +as_ 696 +ã 695 +do_ 685 +ent 678 +ão 677 +_n 671 +_co 660 +_a_ 654 +_m 646 +on 645 +ç 624 +ri 623 +_que 619 +ma 602 +po 581 +ia 580 +ão_ 575 +._ 573 +na 572 +me 564 +ro 554 +_t 544 +pa 533 +da_ 528 +h 523 +ue_ 515 +ca 511 +que_ 509 +nte 503 +no 499 +tr 498 +am 496 +em_ 491 +_que_ 487 +_se 485 +om 471 +io 460 +_do 459 +ti 448 +ci 445 +_da 444 +nd 442 +ei 435 +ra_ 435 +pr 427 +_r 423 +_e_ 420 +_f 420 +ss 412 +es_ 412 +el 407 +id 406 +_o_ 399 +_pa 390 +um 379 +pe 378 +_po 376 +la 374 +ir 371 +á 371 +ic 362 +di 362 +li 359 +é 359 +_re 353 +ve 353 +mo 350 +s, 349 +s,_ 349 +ou 347 +com 340 +sa 338 +si 338 +men 337 +rt 331 +_i 330 +con 330 +o, 327 +_da_ 326 +o,_ 326 +se_ 325 +_com 325 +ado 323 +to_ 322 +ai 322 +it 320 +A 319 +ec 316 +dos 316 +_em 312 +ção 310 +aç 310 +çã 310 +ara 305 +so 299 +tu 299 +res 297 +im 296 +_pr 295 +mi 293 +ua 292 +nto 291 +ment 290 +í 290 +par 288 +_do_ 287 +ce 286 +est 286 +u_ 284 +ente 284 +S 278 +l_ 278 +_u 278 +" 276 +ni 276 +z 274 +sta 273 +nc 272 +_em_ 270 +P 269 +ção_ 267 +_v 267 +at 267 +dos_ 266 +_es 262 +« 259 +_« 259 +te_ 258 +» 257 +va 255 +le 252 +ur 252 +_um 252 +vi 251 +_par 250 +a, 247 +a,_ 247 +_con 247 +ant 242 +lo 240 +ia_ 240 +gu 237 +ar_ 235 +ac 235 +e,_ 234 +e, 234 +no_ 232 +eg 232 +il 232 +ns 232 +er_ 231 +_ma 230 +por 230 +_in 228 +_l 226 +ó 225 +ont 224 +_no 223 +_P 222 +tra 220 +E 219 +ida 218 +is_ 217 +ol 216 +açã 215 +ter 215 +ação 215 +_A 211 +un 211 +- 210 +_te 210 +or_ 209 +ma_ 208 +_pe 208 +ara_ 208 +C 206 +ist 202 +para 202 +nta 201 +ais 201 +ut 198 +nte_ 198 +j 197 +dad 196 +_na 195 +am_ 195 +ade 193 +ica 191 +x 190 +al_ 189 +O 188 +des 187 +_para 187 +ada 187 +nh 186 +_se_ 186 +mp 185 +ndo 184 +R 183 +_por 181 +ação_ 181 +para_ 179 +eir 177 +ui 177 +vo 177 +ou_ 177 +ta_ 177 +M 176 +ria 175 +tos 175 +rr 174 +D 174 +io_ 174 +br 174 +_di 173 +õ 173 +õe 173 +fo 173 +I 172 +ões 172 +_C 171 +mo_ 171 +ov 170 +pro 169 +_os_ 169 +_os 169 +das 167 +iv 166 +uma 165 +gr 165 +su 164 +fi 164 +um_ 162 +na_ 162 +ga 162 +ais_ 161 +_S 161 +lh 159 +ort 159 +cia 158 +.. 157 +_est 156 +cont 156 +ig 155 +á_ 154 +ran 154 +ça 154 +om_ 153 +_en 152 +dade 152 +_as 152 +ho 152 +ntr 151 +nto_ 151 +fe 150 +N 149 +das_ 149 +uma_ 149 +ess 149 +é_ 148 +ndo_ 147 +ob 147 +»_ 147 +ul 146 +ente_ 146 +go 146 +ento 144 +ver 144 +_des 144 +gi 144 +ha 142 +cu 142 +idad 142 +av 141 +ões_ 141 +_pro 141 +ura 141 +ap 139 +_com_ 139 +_ca 139 +com_ 139 +ao 139 +ne 138 +od 138 +_" 137 +_M 137 +pre 137 +ras 136 +_me 136 +_ao 136 +_no_ 134 +oc 134 +str 133 +tes 133 +_b 133 +and 133 +_g 133 +ro_ 133 +omo 133 +_dos 132 +_fo 132 +_dos_ 132 +rn 132 +mento 131 +ito 131 +ev 131 +rio 130 +ass 130 +eu 130 +be 128 +os, 128 +os,_ 128 +sp 127 +_uma 127 +ep 126 +tad 125 +s. 125 +_uma_ 125 +_E 125 +idade 124 +_um_ 124 +nã 124 +não 124 +ct 123 +ram 123 +ado_ 123 +ela 123 +omo_ 121 +iz 121 +_an 121 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/romanian.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/romanian.lm new file mode 100644 index 0000000..65b8e75 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/romanian.lm @@ -0,0 +1,400 @@ +_ 20674 +a 6376 +e 5815 +i 5746 +t 3396 +r 3280 +n 3103 +u 2835 +s 2611 +c 2582 +e_ 2235 +l 2224 +o 2149 +a_ 1974 +d 1629 +m 1528 +p 1410 +i_ 1358 +in 1308 +_c 1167 +_s 1118 +_d 999 +re 905 +ar 898 +, 791 +,_ 786 +_p 785 +de 771 +_a 754 +te 687 +_i 667 +at 654 +ti 645 +ca 639 +n_ 630 +ta 617 +si 614 +_de 609 +f 606 +st 583 +ri 581 +u_ 567 +nt 553 +. 542 +ra 540 +_m 534 +g 528 +v 516 +ul 516 +de_ 513 +_in 503 +b 492 +_de_ 474 +._ 472 +le 459 +l_ 444 +un 443 +_si 440 +es 437 +tr 426 +ea 420 +t_ 412 +ce 412 +ma 407 +cu 402 +er 398 +_ca 397 +si_ 388 +_f 387 +_l 383 +z 382 +la 381 +ne 370 +sa 364 +as 360 +_e 357 +in_ 356 +an 352 +it 351 +te_ 346 +or 345 +el 345 +ci 339 +_si_ 333 +_n 330 +are 324 +pe 319 +re_ 317 +al 310 +_t 309 +se 304 +ic 295 +ie 290 +_u 290 +ul_ 290 +ni 289 +int 285 +_o 280 +en 279 +ta_ 279 +ur 261 +pa 256 +co 255 +_pe 254 +ia 252 +mi 251 +pr 249 +_ma 249 +oa 249 +me 246 +lu 246 +li 241 +im 238 +_in_ 237 +da 237 +na 237 +_sa 235 +ac 234 +- 234 +ii 232 +est 231 +r_ 231 +h 230 +_cu 230 +le_ 229 +ai 229 +ca_ 227 +il 226 +ru 223 +sc 223 +_v 221 +nu 220 +tu 220 +_un 220 +nd 220 +di 219 +are_ 216 +to 215 +am 214 +on 213 +o_ 208 +is 208 +sa_ 203 +la_ 200 +_b 200 +ste 195 +et 194 +ec 191 +_r 186 +car 185 +ui 180 +un_ 179 +lo 178 +cu_ 177 +ei 176 +e, 175 +e,_ 175 +pe_ 171 +m_ 167 +_la 166 +a, 165 +a,_ 164 +_ce 164 +rt 163 +_co 163 +ent 162 +ro 162 +ele 162 +_pe_ 160 +po 160 +ea_ 159 +" 158 +ntr 158 +_cu_ 158 +_pr 157 +ut 157 +nc 156 +ata 155 +care 154 +um 153 +au 151 +va 151 +_o_ 150 +_car 150 +ii_ 145 +ind 145 +_un_ 144 +os 144 +ad 141 +_la_ 140 +I 140 +este 138 +ste_ 138 +care_ 138 +ir 137 +ga 136 +ap 136 +ol 136 +ra_ 136 +_di 134 +D 134 +_care 133 +se_ 133 +om 133 +ara 133 +ati 133 +fi 133 +_sa_ 131 +zi 130 +vi 130 +_ca_ 129 +_se 128 +_nu 128 +ai_ 127 +ch 127 +pi 124 +ve 123 +fa 122 +ot 121 +_a_ 120 +este_ 120 +du 119 +ine 119 +s_ 118 +fo 118 +_ci 118 +ui_ 118 +ba 118 +i, 117 +i,_ 116 +ne_ 115 +us 115 +_g 115 +a. 115 +fe 114 +A 114 +pu 114 +ce_ 113 +ar_ 113 +_pa 113 +oc 112 +sta 112 +lui 112 +ns 112 +em 112 +' 112 +oar 112 +din 111 +iu 111 +_int 111 +ate 111 +mu 111 +hi 110 +ele_ 110 +mp 109 +_D 109 +S 109 +sti 108 +bi 108 +ata_ 107 +ti_ 107 +tra 107 +C 107 +c_ 106 +tre 106 +_al 105 +rea 105 +mai 105 +j 104 +a._ 104 +gi 104 +e. 103 +d_ 103 +_fa 103 +E 102 +mo 102 +at_ 101 +_e_ 101 +nte 101 +lt 101 +sp 101 +za 100 +mai_ 100 +su 99 +na_ 98 +tat 97 +sin 97 +ez 96 +tru 96 +e._ 96 +ie_ 96 +ia_ 96 +_re 96 +tul 96 +_fo 96 +ina 95 +art 95 +_C 95 +no 95 +nu_ 94 +_es 94 +_po 94 +cr 94 +inc 93 +_da 92 +_mai 92 +lui_ 92 +_din 92 +_est 92 +pre 91 +_mai_ 91 +io 91 +chi 91 +ge 90 +pri 90 +eu 90 +uri 90 +az 90 +_nu_ 89 +_me 89 +ct 89 +au_ 88 +esc 88 +ev 88 +ei_ 88 +min 87 +ace 87 +op 86 +ng 86 +ici 86 +_lu 85 +ari 85 +_mi 84 +ita 84 +_S 84 +_tr 84 +ere 83 +or_ 83 +ast 83 +ist 83 +nt_ 83 +_se_ 82 +ou 82 +tin 82 +intr 82 +con 82 +do 81 +_fi 81 +str 81 +am_ 80 +rat 80 +ru_ 80 +ri_ 80 +par 80 +oi 80 +uc 79 +ze 79 +pl 79 +res 78 +_ac 77 +ulu 77 +din_ 76 +va_ 76 +ada 76 +ului 75 +_con 75 +id 75 +inte 74 +ile 73 +cit 73 +_din_ 73 +lor 73 +_" 72 +ig 72 +rin 72 +da_ 72 +_st 72 +-_ 71 +_- 71 +it_ 71 +ani 71 +nd_ 71 +ci_ 70 +ag 70 +eri 70 +i. 70 +tru_ 70 +_ne 70 +rm 70 +P 69 +_este 69 +nta 69 +bu 69 +une 69 +ma_ 69 +nti 69 +imp 68 +_-_ 68 +iv 68 +ind_ 68 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/russian-iso8859_5.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/russian-iso8859_5.lm new file mode 100644 index 0000000..c0c79cc --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/russian-iso8859_5.lm @@ -0,0 +1,400 @@ +_ 76249 +Þ 19732 +Õ 16714 +Ð 14389 +Ø 13942 +â 13160 +Ý 12444 +á 9867 +à 8461 +Ò 7895 +Û 7330 +Ú 6498 +Ü 5935 +. 5725 +ã 5287 +Ô 5019 +ß 4877 +ï 4083 +, 3899 +,_ 3878 +ë 3656 +ì 3376 +Ø_ 3167 +_ß 3144 +Õ_ 3135 +Þ_ 3098 +- 3019 +× 2983 +_Ò 2952 +._ 2930 +_á 2919 +ç 2887 +Ó 2876 +Ñ 2797 +áâ 2672 +_Ý 2631 +âÞ 2585 +.. 2407 +_Ø 2316 +ÝÞ 2300 +-_ 2294 +Ù 2281 +Ð_ 2249 +ÝÐ 2057 +ï_ 2029 +ÞÒ 1981 +ÝØ 1950 +_â 1944 +å 1874 +ÕÝ 1856 +_Þ 1774 +... 1744 +àÐ 1709 +ÝÕ 1685 +ßÞ 1636 +_- 1625 +ÚÞ 1616 +âÕ 1595 +àÞ 1584 +_Ú 1558 +_-_ 1531 +Ù_ 1521 +Õâ 1518 +Ö 1509 +_Ø_ 1454 +âÐ 1433 +ÐÝ 1419 +Õà 1396 +Þâ 1389 +ì_ 1381 +ÓÞ 1375 +ÐÛ 1370 +_ßÞ 1364 +àÕ 1345 +ÚÐ 1338 +ßà 1337 +ÒÐ 1329 +âØ 1306 +ÛØ 1300 +_Ô 1297 +_Ü 1290 +Õá 1284 +ÒÞ 1271 +çÕ 1256 +Þà 1245 +.... 1232 +âì 1219 +Þá 1212 +è 1192 +î 1187 +Ò_ 1168 +..... 1167 +ÞÝ 1147 +ÐÚ 1144 +æ 1109 +ÞÓ 1101 +ÛÞ 1099 +â_ 1093 +àØ 1076 +Ü_ 1074 +_ßà 1063 +ÞÛ 1062 +Ûì 1045 +_ÝÕ 1034 +ÕÛ 1029 +_Ñ 1026 +ØÝ 1000 +ÞÔ 998 +ÞÜ 996 +ÜÕ 993 +ë_ 975 +ÒÕ 968 +áÚ 968 +_ÝÐ 966 +ÔÕ 946 +Ýë 943 +_à 931 +_ç 923 +Ðâ 913 +ÕÜ 910 +ã_ 907 +×Ð 898 +å_ 898 +ÛÕ 889 +âÞ_ 881 +Øâ 878 +ÞÙ 875 +áÕ 862 +_Ò_ 833 +_× 816 +ÚØ 816 +âà 807 +" 786 +âì_ 769 +ÕÔ 767 +ÝÕ_ 762 +áï 754 +ÛÐ 748 +ÞÑ 747 +ÜÞ 741 +ÔÐ 730 +ÓÞ_ 715 +Ú_ 713 +Øá 711 +_ã 702 +ÞÙ_ 697 +ØÛ 694 +ÜÐ 692 +ÝÝ 687 +ÔÞ 662 +Ðá 660 +ÐÜ 656 +Øï 649 +ÖÕ 646 +Ð× 638 +áÞ 629 +ÝÐ_ 619 +_Ó 615 +ÜØ 612 +_Ð 610 +í 609 +Òá 608 +.._ 605 +Òë 604 +ÞÓÞ 604 +ØÜ 604 +_ÚÞ 600 +ÐÒ 597 +áÛ 594 +ØÕ 593 +_ÝÕ_ 589 +_Õ 587 +_âÕ 583 +âã 583 +Øç 583 +àã 575 +Þáâ 571 +é 571 +Û_ 570 +_í 569 +_ï 559 +° 556 +ÕÝØ 544 +Ø× 540 +ÕÚ 536 +ÞÒÐ 533 +ä 525 +: 519 +² 513 +ÐÝØ 511 +_Òá 510 +ØÙ 510 +½ 508 +_ÚÐ 508 +! 503 +? 501 +ÔØ 498 +ÛØ_ 489 +¿ 488 +ßàÞ 486 +_àÐ 485 +áØ 484 +Øà 484 +_áâ 484 +ìÝ 484 +ÛìÝ 484 +:_ 484 +áï_ 480 +_×Ð 477 +ÑÞ 470 +_Û 469 +..._ 465 +Ñë 464 +Øå 464 +¸ 462 +ÕÓ 461 +âÒ 459 +ÝØï 458 +ïâ 454 +çâ 454 +íâ 445 +çÕá 442 +_âÞ 442 +Øï_ 441 +ØÚ 440 +ÒØ 437 +ÐÚ_ 436 +áâÐ 436 +ÞÓÞ_ 435 +_² 434 +ØçÕ 433 +æØ 431 +çâÞ 431 +ëå 429 +_íâ 429 +Á 425 +_çâ 424 +_° 424 +î_ 423 +ßÕ 422 +Ýï 422 +_çâÞ 422 +Ûï 419 +ÒáÕ 418 +Ôã 418 +ÕáÚ 415 +Ýâ 413 +ÚÐÚ 411 +áâÞ 411 +_Òë 409 +Ýã 408 +âá 406 +Ý_ 406 +_¿ 401 +¼ 401 +ÝÞ_ 399 +_ßàÞ 398 +_. 397 +àÞÒ 396 +æÕ 396 +Úâ 394 +Õáâ 394 +_" 393 +èÕ 393 +á_ 392 +_Þâ 392 +¾ 391 +_ÝÐ_ 391 +àÕÔ 391 +çÕáÚ 390 +Þ- 390 +ÒÐÝ 388 +Ð, 385 +ÐÔ 384 +Ðï 384 +_ï_ 383 +Ð,_ 383 +âë 383 +?_ 383 +_ÞÑ 380 +_ÒáÕ 380 +_âÐ 378 +_ÚÐÚ 376 +åÞ 375 +âÐÚ 375 +ÐÛì 374 +ÞÖ 373 +ëå_ 372 +ÞÒÞ 372 +ØÒ 371 +_ÒÞ 369 +Üã 369 +_½ 369 +ÕÙ 368 +ßàÕ 368 +×Ý 366 +ØçÕá 365 +ßØ 365 +ÕÓÞ 362 +_áÞ 360 +ÞÕ 360 +!_ 360 +Ðâì 360 +áâØ 358 +Øå_ 358 +âÝ 358 +ÜÕÝ 358 +âáï 356 +ØÕ_ 356 +ØçÕáÚ 354 +ÑÕ 352 +_Ñë 352 +áâà 349 +Úã 349 +_ÜÞ 348 +Õâ_ 348 + 346 +_ÜÕ 344 +ÕÒ 344 +ßàØ 343 +çØ 342 +ÜÝ 341 +ÝØï_ 339 +Ðà 338 +ÝÝÞ 337 +ÞÒÐÝ 334 +Úá 334 +ãà 328 +_çÕ 328 +ÞÛì 328 +ãâ 327 +çâÞ_ 324 +ÞÜ_ 323 +Þß 323 +àÜ 322 +°_ 322 +_çâÞ_ 322 +íâÞ 322 +Þç 321 +Þ,_ 320 +Þ, 320 +áÚÞ 319 +ÚÞÝ 319 +ÛÞÒ 318 +ëÙ 318 +ãá 317 +Þâ_ 316 +ØàÞ 315 +áâÒ 314 +Ø, 314 +ØÙ_ 313 +áá 313 +Ø,_ 313 +âÞÜ 312 +ÐÕ 312 +ÕÝÝ 311 +Õ× 311 +ÝÞÙ 311 +_íâÞ 310 +º 309 +áÐ 309 +àÐ× 309 +Õß 309 +_ÔÞ 308 +ÞÛÞ 308 +áâì 308 +ãÔ 307 +ÔÕÛ 307 +_¸ 305 +ÐÑ 305 +áì 303 +ÐÛìÝ 302 +ÞÚ 300 +áÚØ 300 +Ýëå 300 +_ßàØ 298 +çÐ 297 +_Ö 297 +Õ, 297 +Õ,_ 297 +_°_ 296 +_ÝØ 296 +_._ 295 +âáï_ 295 +ØØ 294 +×ÝÐ 293 +ï, 292 +ï,_ 292 +_ßàÕ 291 +_Á 290 +ÝÞÙ_ 290 +Ðï_ 288 +_¾ 288 +ÐÛØ 286 +ÖÕ_ 285 +áß 285 +Øáâ 285 +Ýëå_ 285 +×_ 283 +_¼ 283 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/russian-koi8_r.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/russian-koi8_r.lm new file mode 100644 index 0000000..470b150 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/russian-koi8_r.lm @@ -0,0 +1,400 @@ +_ 28256 +Ï 8957 +Å 7206 +Á 6230 +É 5966 +Ô 5385 +Î 5338 +Ó 4464 +Ò 3984 +× 3504 +Ì 3335 +Ë 2700 +Í 2441 +Ð 2324 +Ä 2230 +Õ 1840 +Ñ 1562 +Ù 1540 +_Ð 1505 +, 1492 +,_ 1492 +Ø 1437 +Ï_ 1423 +Å_ 1335 +ÓÔ 1286 +Ú 1283 +Ç 1233 + 1232 +É_ 1193 +ÔÏ 1175 +_Ó 1146 +Þ 1143 +_× 1118 +_Î 1062 +Á_ 1032 +. 999 +ÎÏ 996 +ÅÎ 920 +Ï× 911 +._ 908 +Ê 907 +ÎÁ 893 +ÒÏ 869 +ÒÁ 851 +ÎÉ 844 +Ñ_ 808 +ÐÒ 786 +ÐÏ 775 +ËÏ 768 +Ö 763 +_Ï 735 +ÎÅ 730 +ÏÓ 723 +_É 721 +È 696 +ÒÅ 667 +_ÐÒ 629 +_Ë 626 +×_ 621 +ÔÅ 620 +Ø_ 616 +×Ï 599 +Ê_ 597 +_ÐÏ 592 +ÇÏ 589 +ÅÒ 584 +ÌÉ 579 +ÔÁ 576 +ÅÔ 566 +Í_ 562 +ÅÓ 548 +ÏÒ 545 +ÅÌ 545 +ÁÌ 544 +×Á 535 +ÔØ 533 +ÌÅ 528 +_Ä 522 +ÏÍ 520 +ËÁ 520 +À 518 +Û 510 +_Ô 507 +ÏÔ 502 +ÏÌ 500 +ÁÎ 498 +ÌØ 486 +ÏÄ 476 +ÁÔ 475 +ÔÉ 471 +ÉÔ 458 +ÏÎ 457 +ÏÇ 450 +à 450 +ÌÏ 449 +Ô_ 448 +_ÎÁ 447 +ÎÙ 443 +ÄÅ 442 +_Í 438 +ÌÁ 431 +_×_ 430 +ÓË 428 +_ÎÅ 424 +ÒÉ 400 +ÅÍ 396 +_ 392 +_Þ 388 +ÞÅ 388 +ÁË 388 +_É_ 385 +_Ò 382 +ÔÏ_ 381 +ÉÎ 380 +ÍÅ 374 +ÄÁ 362 +Ù_ 361 +×Å 350 +ÔØ_ 348 +ÐÒÏ 347 +ÏÊ 346 +ÚÁ 338 +È_ 336 +ÁÓ 335 +Ï 328 +ÓÑ 326 +ÉÍ 323 +ÔÒ 321 +ÎÁ_ 321 +ÓÏ 320 +ÅÄ 320 +ÏÓÔ 318 +ÉÅ 318 +ÍÏ 317 +ÎÎ 316 +ÓÅ 314 +- 314 +Á× 309 +ÖÅ 308 +Õ_ 307 +ËÉ 306 +ÎÅ_ 305 +ÇÏ_ 302 +_Ú 300 +ÉÌ 295 +_ÐÒÏ 291 +Ý 289 +Ô× 288 +ÉÓ 285 +_Õ 275 +_ËÏ 274 +ÅÎÉ 274 +Ü 273 +ÎÏ_ 272 +ÉÒ 271 +_Ç 271 +ÁÚ 267 +ÁÒ 266 +ÄÉ 265 +ÏÊ_ 264 +ÏÇÏ 263 +ÁÍ 260 +ÐÅ 258 +×Ù 255 +ÍÉ 254 +ÄÏ 254 +ÓÔ× 247 +ÉÚ 246 +ÃÉ 246 +î 244 +Æ 240 +_Ü 239 +_Á 239 +Ë_ 238 +ó 237 +ÅÓÔ 237 +_ÎÅ_ 236 +ÂÙ 234 +ÉÑ 234 +ÒÕ 229 +ÅË 228 +ÓÉ 226 +ÔÅÌ 224 +ÉË 224 +ÌÉ_ 222 +ÅÊ 222 +ÓÑ_ 222 +ÎÔ 220 +ØÎ 218 +ÞÔ 216 +ÌØÎ 216 +ÏÅ 214 +ÍÁ 213 +_ÚÁ 211 +Ï×Á 211 +ÂÏ 210 +_Ì 210 +ÞÁ 209 +_î 208 +ÓÌ 205 +ÞÔÏ 204 +_ÞÔ 204 +ÅÔ_ 203 +_ÞÔÏ 203 +ÜÔ 202 +Ó_ 202 +×É 201 +ÁÑ 199 +ÅÎÎ 199 +ÔÏÒ 199 +_ÎÁ_ 199 +ÓÔÁ 198 +ÏÖ 198 +ÉÅ_ 197 +_ó 197 +_ÓÏ 195 +ÐÒÉ 194 +ËÔ 193 +Ì_ 193 +×Ó 191 +ÏÍ_ 190 +ÏÇÏ_ 187 +_Ö 187 +ÅÇ 186 +_ÔÏ 186 +ÁÄ 186 +_ÒÁ 185 +_ÜÔ 184 +_ËÁ 184 +ÓÔÉ 183 +_Å 182 +Å× 182 +ÔÓ 181 +_ÓÔ 180 +ÌÑ 180 +ÔÎ 180 +ÓÐ 173 +ÉÉ 172 +ÏÞ 172 +À_ 172 +ÐÒÅ 172 +ÏË 172 +ÁÔØ 171 +ÂÉ 171 +ÛÅ 170 +ÁÅ 169 +á 169 +ÏÒÏ 168 +ÙÈ 167 +Ï×Ï 166 +ÏÌØ 166 +ÁÎÉ 165 +ÞÔÏ_ 164 +_ÞÔÏ_ 163 +÷ 163 +ÁÑ_ 163 +ÉÈ 162 +Ï,_ 160 +Ï, 160 +ÓÓ 160 +ÅÚ 159 +ÎÉÅ 158 +ÚÎ 157 +ÜÔÏ 157 +ÄÎ 156 +ÒÏ× 156 +ð 155 +Á, 155 +ÓËÏ 155 +_×Ï 155 +Á,_ 155 +_ÂÙ 154 +ÙÅ 154 +ÝÅ 154 +_Ï 154 +É,_ 153 +É, 153 +ÎÎÏ 152 +_ÐÒÉ 151 +ÔÙ 150 +ÓÔÏ 150 +ÉÑ_ 150 +ÍÕ 150 +É× 150 +_- 149 +ÒÅÄ 148 +ÉÔÅ 147 +_ÜÔÏ 146 +ÍÅÎ 146 +ÏÐ 146 +_ÐÒÅ 145 +€ 145 +ÉÊ 145 +ÅÌØ 145 +_÷ 144 +_Ó_ 144 +ÉÞ 144 +_€_ 144 +_€ 144 +€_ 144 +ÈÏ 143 +ÅÇÏ 143 +ÑÔ 142 +ÔÓÑ 142 +ÐÅÒ 142 +ÙÊ 142 +ÐÁ 141 +ÏÔÏ 140 +-_ 140 +ÁÐ 139 +ÏÚ 139 +ÓËÉ 138 +ÙÈ_ 138 +ï 137 +ÓÁ 137 +ÙÅ_ 137 +_ð 136 +Å, 136 +Å,_ 136 +ÒÙ 136 +Î_ 135 +_á 135 +ÇÉ 134 +_×Ù 134 +ÓÔØ 134 +ÁÓÔ 133 +ÖÅ_ 133 +ÞÉ 133 +ÎÉÑ 133 +ÕÔ 133 +ÁÌÉ 132 +_-_ 131 +ËÕ 131 +ÓØ 131 +_ÄÏ 129 +ÄÕ 129 +ÒÁÚ 129 +ÖÎ 129 +ÁÅÔ 129 +_ÍÏ 127 +ÖÉ 127 +_ÄÅ 127 +ÓÔÒ 127 +ØÎÏ 126 +ÔÕ 126 +_×Ó 126 +ÌØÎÏ 126 +ÌÅÎ 125 +ÁÌØ 125 +Ï×_ 124 +×Ì 123 +É 123 +ÁË_ 123 +_ÐÅ 123 +ÔÅÌØ 123 +Ú_ 122 +×Î 122 +ÁÀ 122 +ÅÎÔ 121 +ÐÏÌ 121 +ÉÈ_ 121 +ÙÊ_ 121 +ÓÎ 121 +ÎÏÇ 121 +ÃÅ 120 +_ÏÔ 120 +ÅÍ_ 119 +ÉÏ 119 +_ÔÅ 118 +ËÁË 118 +_ÎÏ 117 +ÉÉ_ 117 +ÉÔØ 117 +ë 116 +_ÉÚ 116 +ÕÓ 116 +ÎÏÓ 115 +ÂÅ 115 +ÕÄ 115 +ÅÒÅ 114 +ÂÌ 114 +ÉÔÅÌ 113 +ÅÇÏ_ 113 +ÙÍ 113 +Á 113 +ÎØ 113 +ÎÏÊ 112 +ÎÉÅ_ 112 +_Æ 112 +ÒÏÓ 111 +ËÒ 111 +_ËÁË 111 +ÛÉ 111 +Í, 111 +ÎÏ× 111 +Í,_ 111 +ÔÏÍ 110 +ÅÅ 110 +ÔÏ× 109 +Ó× 109 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/russian-windows1251.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/russian-windows1251.lm new file mode 100644 index 0000000..1450858 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/russian-windows1251.lm @@ -0,0 +1,400 @@ +_ 21836 +î 5818 +à 4506 +å 4258 +è 3769 +ò 3394 +í 3254 +ñ 2594 +ë 2470 +ð 2346 +â 2227 +ê 1798 +ì 1709 +ó 1673 +ä 1638 +ï 1377 +, 1187 +,_ 1172 +î_ 1160 +ÿ 1059 +ü 1024 +û 1006 +å_ 966 +á 945 +_ï 937 +ç 910 +_í 907 +è_ 896 +òî 878 +ã 856 +_ñ 828 +_â 818 +à_ 801 +÷ 795 +. 789 +._ 761 +ñò 655 +íå 617 +_è 616 +íà 575 +ø 568 +é 565 +ïî 549 +ðà 526 +íî 524 +ÿ_ 522 +_ò 521 +_î 497 +_ä 496 +æ 484 +_ïî 477 +_ê 477 +ãî 472 +àë 470 +ü_ 461 +íè 456 +îâ 454 +êî 452 +ðî 432 +êà 431 +ëè 425 +õ 413 +òà 403 +åí 402 +_ì 396 +_á 396 +âî 395 +îë 388 +òî_ 384 +é_ 383 +_íå 378 +_è_ 375 +îð 369 +âà 367 +_íà 365 +ì_ 364 +îì 363 +ïð 357 +ó_ 357 +åë 353 +åð 352 +ëà 350 +èò 344 +îñ 344 +ë_ 343 +òü 338 +äå 337 +ëî 334 +ðè 330 +ðå 328 +èë 326 +àê 326 +îò 323 +- 322 +îí 320 +åò 317 +þ 312 +àí 308 +âå 308 +â_ 302 +_÷ 299 +ò_ 296 +çà 292 +íå_ 292 +òå 291 +äà 291 +_ç 291 +îä 286 +àð 283 +àò 283 +_ïð 274 +åñ 264 +ìî 263 +û_ 260 +îã 253 +_- 245 +_ó 245 +ê_ 244 +îá 240 +ãî_ 238 +ñÿ 235 +_íå_ 235 +ìå 233 +ëü 229 +-_ 225 +ñê 219 +_â_ 217 +åì 217 +íû 215 +îé 215 +ñå 211 +áû 211 +êè 211 +÷ò 209 +òü_ 209 +÷å 208 +_ã 206 +Í 206 +äî 205 +ö 205 +÷òî 203 +èí 203 +àñ 202 +_-_ 202 +_÷ò 199 +_÷òî 199 +òè 197 +àâ 197 +íà_ 197 +_å 195 +åä 192 +_ð 191 +æå 190 +àì 190 +åã 188 +àç 188 +òð 185 +_òî 184 +_Í 183 +èì 182 +_çà 181 +äè 175 + 174 +_êî 172 +ëå 170 +_ 169 +îé_ 168 +! 168 +÷òî_ 165 +ìó 165 +íî_ 164 +èñ 164 +í_ 164 +ìè 163 +ñòà 163 +ù 162 +_÷òî_ 162 +_áû 159 +ìà 158 +ðó 157 +âû 156 +âè 154 +âñ 154 +åãî 153 +èê 153 +èç 153 +ñü 153 +àø 152 +ûë 150 +_íà_ 149 +ñ_ 148 +òâ 148 +_ñò 146 +ñÿ_ 146 +ëè_ 146 +_ÿ 144 +îãî 143 +øå 141 +õ_ 141 +àê_ 141 +!_ 139 +ñî 139 +êó 139 +áî 137 +ïðî 136 +àòü 136 +åãî_ 135 +_êà 134 +_ìî 131 +èå 131 +îñò 130 +îì_ 129 +î, 128 +_ãî 128 +î,_ 127 +èâ 127 +ñë 126 +óò 126 +_òà 126 +íí 125 +àä 125 +Ñ 124 +íó 123 +î÷ 122 +_âû 122 +_âñ 121 +_îí 120 +áûë 120 +ïà 120 +óä 120 +_Ñ 119 +ïðè 119 +îâî 119 +õî 118 +ý 117 +_áûë 117 +è, 115 +åé 115 +_äî 115 +àë_ 114 +_æ 114 +è,_ 114 +_à 113 +_ý 113 +îå 112 +åñò 112 +îðî 110 +çí 110 +_äå 110 +øè 109 +èä 109 +ñòî 109 +_ïðî 109 +_âî 108 +àëè 108 +íÿ 107 +øà 107 +ýò 107 +îæ 106 +à, 106 +Ï 106 +ûé 105 +îëü 105 +óñ 105 +_ýò 105 +_ïðè 104 +èõ 104 +ñü_ 104 +ñè 104 +îï 104 +Ì 103 +à,_ 103 +àÿ 103 +åç 102 +äåë 102 +_ðà 102 +_Ï 101 +îâà 101 +óæ 101 +âàë 101 +þ_ 101 +êàê 100 +_ÿ_ 100 +ó, 100 +æå_ 100 +ñòâ 100 +äí 100 +÷è 100 +òó 100 +_õ 100 +_Ì 99 +ò, 99 +îê 99 +èòü 99 +åò_ 99 +_ñî 99 +ëÿ 98 +àå 98 +_îò 98 +îãî_ 98 +Ê 97 +âîð 97 +òí 97 +_ë 97 +ó,_ 97 +äó 96 +_äà 96 +ò,_ 96 +áà 96 +ïå 96 +ëà_ 95 +áó 95 +áå 94 +ìó_ 94 +_ìå 94 +÷à 94 +âñå 93 +òû 93 +êà_ 92 +_êàê 91 +ìí 91 +òñ 90 +íü 90 +_îá 90 +? 90 +ðàç 89 +òàê 89 +_ñ_ 89 +ñà 89 +å, 89 +æè 88 +ô 88 +_òàê 88 +èÿ 88 +è÷ 88 +îí_ 87 +ìåí 87 +å,_ 87 +ûé_ 86 +ë, 86 +ë,_ 86 +òîì 86 +ðàí 86 +ýòî 86 +Íó 86 +È 86 +öè 85 +èå_ 85 +âåð 85 +ñâ 84 +_îí_ 84 +_âñå 84 +ðû 84 +_ýòî 84 +_È 84 +ç_ 83 +ïè 83 +ëó 83 +À 83 +åíè 82 +èë_ 82 +" 82 +ïîë 82 +àòü_ 81 +òîð 81 +èëè 81 +êð 81 +ëñ 81 +òåë 81 +åíí 81 +îòî 80 +äà_ 79 +èòå 79 +ñòð 79 +îâîð 79 +ãîâ 79 +îðè 79 +àíè 79 +_Íó 78 +ëñÿ 78 +_íè 78 +è. 77 +_ñâ 77 +è._ 76 +à. 76 +_èç 76 +èø 76 +ùå 76 +ÿò 76 +îëî 76 +ü, 75 +Î 75 +êè_ 75 +ü,_ 75 +ëî_ 75 +îç 74 +_åã 74 +ëüí 74 +üí 74 +ûå 74 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/serbian-ascii.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/serbian-ascii.lm new file mode 100644 index 0000000..9471be6 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/serbian-ascii.lm @@ -0,0 +1,400 @@ +_ 34122 +a 9113 +o 8135 +i 7736 +e 7535 +n 5207 +s 4860 +j 3995 +t 3797 +r 3660 +u 3224 +l 3065 +d 3061 +e_ 2941 +v 2786 +a_ 2746 +k 2701 +m 2492 +o_ 2328 +y 2238 +p 2151 +_s 2148 +i_ 2094 +je 1887 +c 1854 +z 1731 +_n 1437 +_p 1432 +g 1418 +b 1368 +u_ 1333 +je_ 1237 +, 1226 +,_ 1214 +_i 1130 +st 1105 +na 1076 +. 1056 +_d 1033 +._ 1030 +_j 967 +ra 934 +ko 908 +ni 900 +cy 893 +sy 875 +_je 871 +_o 824 +ta 799 +no 780 +_u 777 +re 766 +_b 764 +_k 763 +da 760 +ne 754 +li 750 +ti 745 +se 722 +po 713 +to 713 +_je_ 696 +an 688 +ja 683 +pr 665 +va 651 +lo 634 +_z 626 +m_ 625 +is 625 +il 622 +ov 621 +la 621 +_m 615 +bi 604 +_t 603 +_po 594 +en 586 +_se 578 +os 578 +in 576 +od 576 +ka 552 +ve 548 +ij 538 +_pr 536 +al 536 +vo 535 +om 530 +_i_ 525 +nj 515 +ed 509 +_na 507 +na_ 503 +og 499 +oj 498 +ma 493 +_bi 492 +on 489 +ak 482 +im 481 +ye 481 +ro 480 +vi 473 +sa 469 +ri 464 +da_ 451 +av 450 +at 449 +se_ 447 +es 446 +h 443 +ao 441 +ji 437 +yi 436 +_da 433 +ad 432 +_se_ 430 +lj 428 +zy 426 +za 426 +_ne 425 +de 422 +tr 417 +cj 415 +_u_ 414 +_c 412 +le 402 +_v 397 +ar 390 +_g 390 +ic 384 +n_ 382 +ju 379 +lo_ 377 +aj 376 +_ko 369 +ao_ 366 +ek 361 +_da_ 359 +et 356 +go 354 +iz 346 +_za 345 +_r 344 +or 342 +mo 341 +el 340 +as 339 +ik 336 +te 332 +_sa 329 +d_ 323 +am 320 +me 318 +sto 317 +di 315 +ec 311 +ol 310 +a,_ 307 +a, 307 +_ni 302 +ya 296 +do 295 +yt 294 +su 292 +syt 289 +li_ 288 +sta 286 +ije 284 +ko_ 277 +ti_ 277 +la_ 277 +ga 276 +bil 275 +no_ 274 +a. 273 +nu 272 +a._ 271 +ne_ 271 +om_ 268 +_cy 266 +_na_ 263 +_bil 263 +sv 263 +ru 259 +to_ 256 +_od 253 +cyi 253 +nje 251 +it 251 +pa 250 +az 248 +e,_ 245 +e, 245 +ob 244 +dn 243 +ac 242 +ost 242 +k_ 240 +iv 239 +io 238 +_su 238 +_iz 237 +ilo 235 +_sv 234 +_ka 233 +koj 231 +mi 229 +im_ 229 +ije_ 227 +g_ 226 +em 223 +su_ 223 +ih 223 +ji_ 221 +kr 220 +ut 220 +_koj 220 +V 218 +_st 218 +ye_ 217 +_l 214 +_V 213 +ovo 211 +j_ 210 +uc 208 +ja_ 208 +h_ 207 +nij 206 +sk 206 +ot 203 +io_ 203 +gl 203 +_do 201 +ok 200 +ns 199 +ilo_ 199 +er 197 +ih_ 195 +pre 193 +ci 193 +og_ 193 +ki 192 +sl 191 +t_ 189 +ni_ 189 +_a 189 +vr 188 +ati 187 +_su_ 186 +nije 181 +pro 181 +be 180 +yn 179 +cye 178 +ju_ 178 +ku 177 +isy 177 +ta_ 174 +sye 172 +_tr 172 +O 172 +jen 172 +_to 171 +pi 168 +_pre 168 +S 168 +ima 167 +nije_ 167 +_mo 166 +eg 166 +e._ 164 +za_ 164 +e. 164 +_pro 164 +gov 163 +N 162 +dr 162 +ako 162 +tv 162 +_S 160 +P 159 +ma_ 159 +_on 159 +sp 158 +nst 158 +anj 158 +dj 157 +oc 157 +_sy 156 +ev 155 +ce 155 +lik 154 +_nij 153 +_N 152 +ist 151 +_P 151 +_nije 151 +- 151 +ba 150 +jed 150 +sti 150 +ova 149 +_is 148 +id 148 +ton 148 +ke 147 +pos 147 +od_ 147 +osy 146 +Vi 146 +ila 145 +ins 145 +bo 145 +_Vi 145 +ir 144 +_za_ 144 +oz 144 +ecj 144 +cje 143 +on_ 143 +zn 142 +_O 141 +us 141 +i, 141 +i,_ 141 +mu 140 +inst 140 +cya 140 +oji 139 +esy 139 +icy 139 +lja 138 +_go 138 +i. 138 +_re 137 +_bilo 137 +edn 137 +acy 137 +rat 137 +bilo 137 +ali 136 +ecy 136 +ija 135 +pri 135 +ad_ 135 +lic 135 +i._ 135 +Vins 134 +Vin 134 +ston 134 +Vinst 134 +ga_ 134 +nston 134 +insto 134 +nsto 134 +_Vins 133 +_Vin 133 +zi 132 +ran 131 +le_ 130 +ili 130 +bilo_ 130 +_pos 129 +ila_ 129 +est 128 +_ve 128 +tre 128 +zye 127 +_nj 127 +si 126 +f 126 +alo 125 +ako_ 125 +tra 125 +sa_ 125 +pu 124 +ud 124 +z_ 124 +_ra 124 +iti 124 +_de 124 +odi 123 +T 123 +-_ 122 +o,_ 121 +o, 121 +du 121 +rs 121 +B 120 +ka_ 119 +red 119 +_od_ 118 +an_ 118 +nu_ 118 +iko 117 +dno 117 +_pa 117 +s_ 116 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/slovak-ascii.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/slovak-ascii.lm new file mode 100644 index 0000000..29c8736 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/slovak-ascii.lm @@ -0,0 +1,400 @@ +_ 20064 +a 4991 +o 4983 +e 3838 +n 3342 +i 3317 +r 2583 +s 2501 +v 2383 +t 2325 +c 1918 +k 1912 +l 1888 +d 1736 +u 1725 +p 1543 +a_ 1527 +y 1371 +m 1339 +z 1227 +h 1194 +e_ 956 +_p 881 +_s 828 +o_ 814 +na 809 +b 808 +_v 798 +j 797 +. 796 +ov 795 +._ 785 +st 687 +i_ 665 +, 657 +,_ 657 +_n 625 +ch 623 +u_ 618 +ro 617 +po 598 +_o 546 +ne 529 +en 520 +v_ 519 +_a 516 +ra 506 +pr 488 +y_ 481 +od 476 +_z 467 +ie 462 +ni 448 +an 447 +vy 434 +to 433 +h_ 431 +_na 429 +re 416 +ch_ 404 +ho 401 +al 399 +ci 394 +va 387 +na_ 386 +_pr 385 +_d 384 +_k 378 +la 377 +ko 375 +do 374 +_po 373 +si 353 +_t 346 +_r 337 +os 336 +no 334 +in 328 +tr 324 +om 321 +_v_ 320 +ny 319 +m_ 319 +ri 317 +S 306 +ac 302 +sa 300 +ti 300 +_m 298 +za 298 +er 291 +ia 290 +ce 290 +li 289 +yc 286 +ych 285 +ed 284 +at 281 +ob 281 +ak 280 +_na_ 280 +il 279 +_, 279 +_,_ 279 +ok 277 +sk 268 +ych_ 265 +_c 262 +mi 261 +ol 260 +me 260 +l_ 259 +t_ 259 +ku 258 +ta 256 +le 256 +_b 254 +or 252 +_a_ 250 +lo 247 +oc 246 +vo 246 +es 244 +ve 242 +_vy 240 +on 238 +_sa 231 +as 231 +da 230 +aj 228 +av 218 +el 216 +ova 216 +ic 215 +ne_ 209 +_do 208 +sa_ 207 +ka 205 +_sa_ 204 +te 203 +j_ 201 +_ro 199 +P 198 +_za 196 +ky 196 +_S 195 +je 194 +ar 193 +_. 193 +it 192 +s_ 192 +em 191 +ej 191 +ur 190 +ad 189 +_o_ 187 +_._ 187 +ov_ 185 +de 180 +_% 179 +om_ 179 +% 179 +_u 174 +pre 173 +dn 173 +D 172 +rok 170 +ie_ 170 +sp 169 +pri 167 +_pre 167 +am 165 +- 164 +ke 164 +eh 162 +oz 161 +k_ 160 +ost 160 +_j 156 +f 155 +zn 153 +g 152 +kt 152 +ho_ 151 +eho 151 +hod 150 +ku_ 148 +is 148 +zi 147 +cn 147 +eho_ 146 +ej_ 145 +az 145 +tu 145 +_pri 144 +cen 144 +_st 143 +ma 142 +ast 141 +_ce 140 +rov 140 +la_ 138 +ot 138 +nych 135 +nyc 135 +_ob 133 +z_ 133 +nych_ 131 +N 130 +li_ 129 +ani 129 +co 128 +nt 128 +ny_ 127 +E 125 +_ne 124 +) 123 +_( 123 +sti 123 +A 123 +( 123 +cho 122 +vi 122 +_sp 122 +di 120 +pa 120 +n_ 119 +ju 118 +ys 117 +bo 117 +_P 116 +_tr 115 +V 114 +je_ 114 +ln 114 +_i 113 +ze 113 +spo 112 +_N 112 +nd 111 +nu 111 +so 111 +red 110 +vn 110 +kl 110 +kov 110 +_cen 110 +_rok 109 +tn 109 +du 109 +nc 109 +ap 109 +d_ 108 +van 108 +ca 108 +M 108 +chod 107 +ti_ 107 +U 106 +_ak 106 +ru 105 +sta 105 +ym 105 +_- 104 +et 103 +_h 102 +est 102 +_je 102 +nos 101 +aci 101 +us 100 +dov 100 +pod 100 +_to 100 +tor 99 +uc 99 +ras 98 +ky_ 98 +_s_ 98 +_mi 97 +* 97 +uj 97 +nost 97 +vys 97 +ovy 97 +ez 97 +oku 96 +_V 96 +op 96 +bc 96 +rast 96 +se 95 +B 95 +roku 95 +kto 94 +ove 94 +by 94 +-_ 94 +_ko 93 +obc 92 +nie 91 +ia_ 91 +ka_ 91 +*_ 90 +ali 90 +lo_ 89 +ovan 89 +to_ 88 +iz 88 +_bo 88 +_l 88 +odo 87 +bch 87 +bchod 87 +bcho 87 +sl 86 +st_ 86 +pred 86 +C 86 +pol 85 +_pred 85 +R 85 +ik 84 +uro 84 +pi 84 +ek 84 +zo 83 +eni 83 +obch 83 +cie 83 +oku_ 83 +obcho 83 +ns 83 +roku_ 82 +ii 82 +tv 82 +ba 82 +ent 82 +_spo 81 +tov 81 +pe 81 +kon 80 +kc 80 +ec 80 +kci 80 +ck 80 +x 79 +osti 79 +_Sk 79 +mi_ 79 +_in 79 +Sk 79 +sia 79 +br 78 +rh 78 +val 78 +olo 77 +_pod 77 +%_ 77 +_%_ 77 +bu 77 +_f 77 +iv 77 +_obc 77 +_obch 77 +eb 76 +str 76 +nej 76 +_D 76 +ni_ 75 +ou 75 +im 75 +ena 74 +tre 74 +_A 74 +mo 74 +su 74 +rz 73 +_trh 73 +trh 73 +_U 73 +al_ 73 +_ra 73 +_e 72 +_C 72 +sti_ 72 +zv 72 +te_ 72 +cno 72 +oj 72 +ktor 71 +_roku 71 +ocn 71 +ina 71 +sil 71 +nov 71 +alo 71 +odn 70 +nan 70 +oh 70 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/slovak-windows1250.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/slovak-windows1250.lm new file mode 100644 index 0000000..7b5dc93 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/slovak-windows1250.lm @@ -0,0 +1,400 @@ +_ 8202 +o 2145 +a 1912 +e 1763 +i 1491 +n 1415 +r 1256 +t 1127 +v 1080 +s 1004 +k 824 +d 739 +p 739 +l 735 +m 685 +c 620 +u 597 +h 531 +a_ 467 +j 449 +_p 445 +z 439 +e_ 412 +á 402 +_v 369 +. 361 +_s 359 +ov 330 +b 327 +st 312 +y 309 +pr 307 +._ 300 +o_ 297 +í 278 +, 268 +,_ 260 +to 258 +è 256 +_a 254 +ý 253 +i_ 252 +_pr 246 +ch 242 +re 233 +_z 223 +ra 220 +_n 217 +ne 214 +ie 214 +po 214 +en 208 +ro 205 +or 204 +é 199 +u_ 197 +an 197 +ko 194 +na 189 +ni 187 +va 183 + 182 +ú 180 +os 179 +v_ 176 +ž 173 +_o 171 +ho 170 +ia 168 +no 166 +li 166 +h_ 166 +ed 164 +j_ 161 +om 160 +_k 160 +š 158 +ch_ 158 +ti 155 +y_ 148 +m_ 147 +ej 147 +_po 145 +ci 145 +_d 140 +_ 139 +do 138 +_t 137 +_m 134 +ri 129 +mi 129 +od 128 +te 124 +_a_ 124 +la 122 +al 121 +aj 120 +ej_ 120 +vo 119 +ol 119 +in 118 +ve 117 +me 117 +tr 116 +sk 116 +ova 116 +S 111 +er 110 +ob 110 +_na 109 +ad 107 +je 106 +at 104 +_v_ 103 +_r 102 +ic 101 +ých 100 +pre 100 +ýc 100 +av 98 +es 96 +ta 95 +dn 94 +ho_ 94 +lo 94 +é_ 93 +_pre 93 +it 93 +V 92 +de 92 +kt 89 +ný 89 +za 88 +A 87 +le 86 +ých_ 86 +ok 86 +ost 85 +vi 84 +ie_ 83 +ak 82 +P 82 +né 81 +R 80 +sa 80 +as 79 +èi 78 +na_ 77 +a 77 +í_ 77 +¾ 76 +ar 75 +di 75 +_S 74 +om_ 74 +_V 73 +_do 73 +_za 72 +- 72 +ck 71 +vy 71 +ka 71 +f 70 +tor 70 +am 70 +on 70 +_- 69 +_P 69 +M 68 +_i 68 +_sa 68 +nos 68 +ní 68 +ác 67 +a_ 67 +sl 66 +il 66 +rá 66 +_c 66 +_b 66 +_-_ 64 +sa_ 64 +-_ 64 +kto 64 +_j 64 +ani 64 +kr 64 +sti 63 +ou 63 +ot 63 +ne_ 63 +_sa_ 62 +vý 62 +_na_ 62 +red 62 +ku 61 +is 61 +ná 60 +ý_ 60 +so 60 +sp 60 +_st 59 +g 59 +tn 59 +str 58 +že 58 +nt 58 +et 57 +pra 57 +ke 57 +ov_ 57 +_vy 57 +_M 57 +nej 56 +tu 56 +l_ 56 +_je 56 +nie 56 +èn 56 +k_ 56 +pe 56 +_h 55 +oz 55 +ú_ 55 +est 55 +_è 55 +va 55 +ma 54 +né_ 53 +tá 53 +.. 53 +rí 52 +ran 52 +bo 51 +nej_ 51 +ick 51 +ti_ 51 +ia_ 51 +ktor 51 +K 51 +O 51 +T 51 +_ne 51 +ou_ 50 +I 50 +oc 50 +to_ 50 +vn 50 +sta 50 +_. 50 +da 50 +éh 49 +ého 49 +N 49 +_ro 49 +_ko 49 +ac 49 +ek 49 +li_ 49 +èa 49 +rov 49 +oj 48 +s_ 48 +s 48 +ého_ 48 +va_ 48 +je_ 48 +zá 47 +ik 47 +mo 47 +mi_ 47 +si 47 +_kto 46 +_sp 46 +_kt 46 +E 46 +_ktor 46 +eb 46 +nýc 45 +_u 45 +el 45 +B 45 +ných 45 +pro 45 +eni 44 +_ž 44 +em 44 +kon 44 +pa 44 +ky 44 +uj 44 +že_ 44 +ova 44 +cie 44 +hr 44 +ký 44 +ných_ 43 +pred 43 +zo 43 +ln 43 +oè 43 +tov 43 +nu 43 +eè 43 +íc 42 +ál 42 +ým 42 +pri 42 +_to 42 +lá 41 +ce 41 +áv 41 +eh 41 +_pro 41 +rav 41 +kej 41 +ns 41 +ali 41 +oli 40 +á_ 40 +_pri 40 +oh 40 +ud 40 +_ak 40 +ent 40 +e¾ 40 +prav 39 +_pred 39 +ži 39 +zn 39 +ny 39 +ove 39 +pol 39 +ru 39 +a, 39 +ah 39 +kej_ 39 +a,_ 38 +z_ 38 +aj_ 38 +r_ 38 +i 38 +ova_ 38 +tre 38 +pod 37 +_zá 37 +_ob 37 +nost 37 +sti_ 37 +van 37 +up 37 +osti 36 +áci 36 +_že 36 +jú 36 +co 36 +_str 36 +ši 36 +_ma 36 +ut 36 +nsk 36 +by 36 +_ve 35 +ko_ 35 +de_ 35 +èia 35 +_aj 35 +_aj_ 35 +op 35 +_pod 34 +prí 34 +_in 34 +ez 34 +odn 34 +dne 34 +Z 34 +tra 34 +bn 34 +ád 34 +_že_ 34 +_vo 34 +èas 34 +át 34 +d_ 34 +ô 34 +sto 34 +ky_ 34 +ir 33 +_z_ 33 +nie_ 33 +št 33 +ven 33 +i_ 33 +_s_ 33 +_B 33 +še 33 +ens 33 +spo 32 +eho 32 +lad 32 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/slovenian-ascii.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/slovenian-ascii.lm new file mode 100644 index 0000000..78c397e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/slovenian-ascii.lm @@ -0,0 +1,400 @@ +_ 25262 +e 6217 +a 5964 +i 5611 +o 5538 +n 4132 +s 3349 +l 3268 +r 2913 +t 2777 +j 2672 +v 2282 +k 2175 +e_ 1958 +d 1953 +p 1786 +a_ 1700 +y 1623 +m 1559 +o_ 1542 +z 1521 +i_ 1462 +_s 1433 +je 1383 +, 1278 +,_ 1278 +b 1230 +c 1137 +_p 1130 +_n 1032 +je_ 997 +u 986 +_j 972 +g 933 +_je 877 +cy 848 +_je_ 842 +_v 793 +il 786 +ni 782 +st 779 +na 743 +ra 726 +. 723 +._ 716 +_z 713 +in 691 +_k 685 +_b 667 +al 640 +h 627 +po 607 +ti 584 +pr 584 +ko 584 +_d 582 +el 579 +n_ 579 +la 577 +lo 573 +l_ 571 +_t 567 +se 567 +ne 562 +_i 556 +no 549 +en 546 +_o 534 +re 524 +bi 514 +li 512 +ov 496 +sy 458 +_na 457 +te 453 +da 451 +_po 440 +_bi 437 +ye 436 +to 424 +ri 420 +an 420 +_pr 417 +ve 410 +nj 404 +ka 403 +_m 394 +le 385 +ja 377 +va 374 +de 374 +is 371 +ed 364 +v_ 362 +za 361 +in_ 354 +bil 353 +_se 351 +aj 347 +ga 344 +ar 343 +od 339 +_in 338 +_in_ 333 +tr 332 +os 332 +_bil 332 +ta 328 +vo 327 +ki 324 +ro 324 +et 320 +so 315 +em 313 +lo_ 311 +na_ 306 +av 305 +ih 305 +yi 304 +h_ 295 +at 294 +m_ 293 +ek 292 +ol 289 +se_ 289 +as 284 +lj 281 +_za 277 +ob 275 +om 273 +me 273 +zy 272 +mi 268 +eg 265 +_v_ 263 +_g 260 +or 260 +es 259 +_se_ 258 +do 255 +ni_ 255 +ga_ 253 +oc 251 +il_ 250 +vi 249 +ak 248 +no_ 243 +da_ 241 +pa 240 +_ne 238 +ot 238 +_so 238 +ocy 237 +ya 237 +la_ 234 +li_ 234 +ih_ 231 +_c 229 +az 229 +ik 228 +on 225 +ki_ 224 +go 223 +im 223 +sk 223 +mo 221 +cye 219 +ti_ 217 +ji 216 +_da 216 +iz 215 +ko_ 214 +ic 213 +_l 209 +u_ 209 +pre 208 +_r 208 +_ko 208 +t_ 207 +z_ 206 +er 206 +so_ 206 +ilo 203 +r_ 201 +j_ 199 +ad 195 +cyi 193 +_na_ 193 +sa 191 +ev 191 +i, 188 +i,_ 188 +it 187 +sto 186 +_da_ 184 +_ni 183 +_so_ 182 +_ve 182 +nje 181 +a, 181 +kr 181 +a,_ 181 +dn 177 +_st 177 +di 176 +ega 176 +og 174 +o,_ 174 +o, 174 +ilo_ 172 +_ki 171 +ma 170 +- 170 +ij 169 +_cy 169 +ost 169 +e, 168 +e,_ 168 +ne_ 168 +ok 166 +ke 165 +_pre 165 +del 165 +yn 165 +al_ 165 +bo 164 +_pa 163 +_ki_ 163 +am 159 +ns 158 +ye_ 156 +sp 155 +em_ 154 +_ka 154 +_te 153 +_iz 152 +ega_ 151 +_ob 150 +br 149 +ec 149 +pri 148 +ap 147 +ez 147 +ali 147 +raz 144 +jo 142 +to_ 141 +d_ 138 +a._ 137 +a. 137 +cya 137 +ova 136 +anj 136 +el_ 135 +V 135 +si 134 +sta 134 +_pri 132 +_to 131 +_a 130 +_bilo 130 +bilo 130 +oj 129 +ecy 128 +_od 128 +gl 128 +op 127 +ju 127 +rav 126 +_u 125 +s_ 125 +_V 125 +ila 125 +ce 124 +_mo 124 +ali_ 124 +ah 122 +str 122 +_sp 121 +vr 121 +aj_ 121 +_do 121 +bilo_ 121 +N 119 +iv 117 +ru 116 +vs 116 +jal 116 +pi 115 +O 115 +_z_ 113 +icy 112 +k_ 112 +be 112 +elo 111 +dr 110 +pra 110 +sye 110 +ved 109 +rs 108 +_tr 108 +tv 108 +oz 108 +tn 107 +_nj 107 +le_ 107 +_N 107 +_ni_ 106 +pa_ 106 +l,_ 105 +l, 105 +ins 105 +ako 104 +ac 104 +ist 104 +ir 104 +sl 104 +ila_ 103 +nik 103 +bi_ 103 +i. 102 +i._ 102 +_vs 102 +iti 102 +_sy 101 +P 101 +val 100 +ku 100 +_P 99 +pe 99 +ala 99 +bil_ 98 +eli 98 +jen 98 +ede 98 +_zy 98 +T 96 +ja_ 96 +ran 95 +_bo 95 +S 95 +ln 95 +zn 94 +nst 93 +_pa_ 93 +_ra 93 +_bil_ 93 +nil 93 +ati 92 +ej 92 +ocyi 92 +e. 91 +_le 91 +ud 91 +nov 91 +nja 91 +sn 91 +ar_ 91 +e._ 91 +kl 91 +isy 90 +zye 90 +en_ 90 +sti 90 +_ga 90 +prav 90 +_bi_ 90 +za_ 89 +lik 89 +ton 89 +kra 88 +rt 88 +W 88 +_de 88 +_ga_ 88 +M 88 +ep 87 +cyn 87 +Wi 87 +_S 87 +ut 87 +_W 87 +inst 87 +insto 86 +ste 86 +Wins 86 +gov 86 +nu 86 +Win 86 +_Wi 86 +Winst 86 +nsto 86 +eti 86 +ston 86 +nston 86 +_Win 85 +_Wins 85 +ili 84 +bra 83 +rat 83 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/slovenian-iso8859_2.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/slovenian-iso8859_2.lm new file mode 100644 index 0000000..b4a1bea --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/slovenian-iso8859_2.lm @@ -0,0 +1,400 @@ +_ 10406 +a 2828 +e 2676 +i 2458 +o 2418 +n 1814 +r 1484 +v 1253 +l 1248 +s 1228 +t 1172 +j 1107 +d 1085 +k 911 +p 880 +a_ 823 +m 763 +i_ 681 +e_ 678 +_p 603 +o_ 566 +u 521 +z 516 +b 456 +_s 435 +je 434 +, 416 +,_ 411 +ni 399 +è 383 +_v 372 +_d 356 +pr 355 +g 345 +ra 336 +_n 332 +st 323 +an 313 +po 303 +re 301 +na 295 +h 287 +ov 276 +_pr 276 +li 275 +al 274 +_z 270 +je_ 259 +la 255 +¹ 253 +ne 248 +en 246 +ko 244 +in 237 +c 234 +ti 234 +v_ 234 +_po 232 +no 230 +ve 230 +_k 227 +_i 224 +da 224 +. 221 +_j 221 +ri 220 +ja 216 +_t 214 +se 213 +ed 212 +._ 211 +em 206 +te 205 +za 201 +od 201 +av 200 +lo 196 +nj 194 +_o 194 +_je 193 +il 190 +or 183 +ka 181 +sk 179 +_b 178 +_je_ 178 +ih 178 +n_ 177 +_za 173 +h_ 171 +er 171 +os 171 +_na 168 +va 168 +ta 164 +le 163 +m_ 161 +ev 157 +ij 157 +ar 157 +do 155 +to 155 +¾ 154 +A 153 +el 150 +_m 148 +ro 147 +ol 146 +_v_ 145 +aj 145 +di 143 +N 142 +S 142 +at 140 +ih_ 139 +ki 138 +de 137 +_in 135 +vo 135 +ga 134 +me 131 +in_ 129 +vi 129 +om 127 +_in_ 125 +et 124 +pre 124 +O 123 +bi 120 +I 119 +da_ 117 +ik 117 +ma 115 +E 114 +so 113 +bo 112 +it 112 +anj 112 +eg 110 +ni_ 109 +mi 108 +ke 108 +na_ 108 +u_ 108 +lj 106 +iz 105 +ob 105 +_da 103 +li_ 103 +is 103 +im 102 +red 102 +_pre 102 +dr 100 +mo 99 +P 99 +_se 99 +ji 98 +r_ 97 +ad 97 +pri 97 +K 97 +_l 97 +tr 95 +pa 94 +no_ 94 +j_ 92 +ki_ 91 +ti_ 91 +_pri 91 +dn 89 +_P 88 +ej 88 +_da_ 87 +ne_ 86 +ega 86 +_r 86 +_bi 86 +l_ 86 +em_ 86 +go 86 +" 85 +sl 85 +ek 84 +ali 84 +ove 84 +aè 84 +ak 84 +ci 83 +ga_ 83 +ko_ 83 +se_ 82 +_S 82 +jo 81 +ot 81 +ja_ 81 +_so 80 +lov 80 +L 80 +D 79 +V 79 +as 78 +_do 78 +am 78 +nje 77 +es 77 +za_ 77 +_pa 76 +T 75 +tu 75 +_za_ 74 +sti 74 +_dr 74 +la_ 74 +_N 74 +_de 74 +ega_ 73 +_ko 73 +og 73 +ns 72 +èe 72 +ds 72 +_bo 71 +ora 71 +vn 71 +ost 71 +_ne 71 +iè 70 +ven 69 +z_ 69 +èi 69 +_te 68 +ce 68 +_se_ 67 +èa 67 +oè 67 +M 66 +_u 66 +un 65 +ln 65 +pos 64 +ju 64 +sta 64 +op 64 +di_ 63 +ud 63 +vs 63 +t_ 62 +nsk 62 +tv 62 +on 62 +ski 62 +R 62 +pa_ 62 +_ka 62 +i, 61 +so_ 61 +_iz 60 +_pa_ 60 +s_ 60 +i,_ 60 +pro 59 +del 59 +rav 59 +eni 59 +oli 58 +rj 58 +e, 57 +¹e 57 +ili 57 +vr 57 +d_ 57 +_le 57 +pred 57 +jo_ 56 +e,_ 56 +nik 56 +love 56 +_pred 56 +ske 56 +er_ 55 +str 55 +èn 54 +pra 54 +J 54 +_¹ 54 +oven 53 +_ra 53 +tn 53 +_na_ 53 +_so_ 53 +nih 53 +loven 53 +si 52 +ke_ 52 +_g 52 +ic 52 +udi 51 +bi_ 51 +eds 51 +oj 51 +ru 51 +a, 51 +_pro 50 +_pos 50 +nc 50 +nih_ 50 +èu 50 +a,_ 50 +_a 50 +az 50 +ok 50 +B 50 +let 49 +udi_ 49 +_od 49 +_K 49 +aj_ 48 +_bi_ 48 +_ve 48 +raè 48 +o, 47 +_tu 47 +ija 47 +ter 47 +ist 47 +Z 47 +reds 46 +nd 46 +ali_ 46 +A_ 46 +iti 46 +bil 46 +_ob 46 +o,_ 46 +ati 46 +tud 45 +tudi 45 +_ki 45 +k_ 45 +be 45 +a¹ 45 +ir 45 +¾a 45 +do_ 45 +sp 45 +_ki_ 45 +_st 45 +ep 44 +_del 44 +tudi_ 44 +r¾ 44 +aèu 44 +_ni 44 +ah 43 +raèu 43 +raèun 43 +i¹ 43 +_mo 43 +avn 43 +_tud 43 +èun 43 +aèun 43 +_tudi 43 +_to 42 +raz 42 +kr 42 +ova 42 +_e 42 +ogo 42 +ani 42 +_" 42 +ev_ 42 +br 42 +eb 42 +sa 42 +mi_ 42 +tem 42 +ta_ 41 +prav 41 +i. 41 +slov 41 +ens 41 +bo_ 41 +¾e 41 +_T 41 +_let 41 +odo 41 +slo 41 +ensk 40 +ka_ 40 +neg 40 +ez 40 +nos 40 +eè 40 +_sl 40 +_V 40 +r¾a 40 +nega 40 +ili_ 39 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/spanish.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/spanish.lm new file mode 100644 index 0000000..3e8bbba --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/spanish.lm @@ -0,0 +1,400 @@ +_ 25044 +e 7830 +a 7437 +o 5102 +s 4394 +n 4358 +i 4065 +r 3998 +l 3634 +d 3118 +c 2931 +t 2834 +u 2316 +a_ 2269 +e_ 2211 +s_ 1862 +de 1679 +p 1673 +_d 1644 +m 1447 +_de 1443 +n_ 1332 +o_ 1301 +en 1295 +_e 1216 +es 1177 +_l 1132 +de_ 1080 +la 1060 +os 1028 +_de_ 1027 +_p 963 +l_ 910 +ci 890 +_c 866 +_a 866 +os_ 801 +ar 777 +er 775 +as 768 +ra 746 +nt 736 +_la 727 +re 726 +,_ 724 +, 724 +el 722 +ta 708 +ue 701 +g 678 +on 674 +al 670 +_s 666 +co 653 +b 637 +an 622 +v 616 +la_ 616 +or 612 +te 599 +st 596 +el_ 580 +_la_ 573 +y 545 +to 543 +r_ 517 +ad 512 +ó 511 +do 504 +ro 504 +se 488 +as_ 488 +q 487 +qu 487 +. 479 +._ 478 +en_ 475 +ca 460 +in 459 +un 456 +_co 450 +es_ 449 +ic 449 +_en 440 +ac 440 +que 439 +na 439 +lo 430 +_m 430 +f 429 +ent 428 +da 412 +ue_ 411 +po 405 +le 399 +_q 399 +_qu 399 +que_ 393 +_que 388 +ie 386 +h 385 +pa 382 +y_ 371 +ti 367 +_que_ 365 +_en_ 365 +_y 361 +tr 358 +_el 353 +ri 349 +ia 342 +_el_ 333 +_se 330 +ió 330 +_y_ 330 +io 329 +pr 320 +ón 317 +ec 317 +no 314 +id 301 +í 300 +mi 299 +_t 299 +ión 292 +nte 292 +me 286 +aci 283 +do_ 279 +li 276 +con 276 +nd 273 +est 272 +ni 272 +á 271 +di 270 +_es 268 +_lo 267 +ció 265 +ma 265 +ón_ 264 +_pr 263 +_r 261 +ción 255 +z 254 +ra_ 251 +si 247 +ión_ 246 +oc 245 +nc 244 +_u 244 +_po 243 +los 243 +or_ 242 +_con 241 +is 239 +del 238 +_del 237 +ado 236 +se_ 233 +_i 233 +los_ 231 +_re 231 +por 229 +_del_ 228 +sta 228 +del_ 228 +al_ 228 +ne 226 +_h 226 +cu 225 +_n 225 +_a_ 224 +_v 224 +_un 223 +ce 222 +so 220 +ción_ 218 +res 218 +vi 217 +om 216 +te_ 212 +_pa 211 +ien 210 +j 209 +E 208 +_los 207 +_los_ 207 +to_ 206 +ol 204 +it 203 +am 202 +ació 201 +rt 201 +ación 201 +pe 197 +ha 190 +_se_ 189 +nto 188 +_o 184 +_E 184 +on_ 184 +sa 183 +na_ 182 +ta_ 181 +su 180 +cia 180 +mo 180 +ct 178 +par 178 +_f 177 +_por 176 +eg 172 +_in 172 +ur 170 +L 168 +ve 166 +im 164 +ga 163 +_est 161 +ar_ 161 +ab 160 +_L 159 +tu 158 +at 158 +no_ 157 +s, 157 +s,_ 157 +_por_ 156 +por_ 156 +las 156 +ba 154 +o,_ 154 +o, 154 +ento 151 +et 150 +C 150 +_ha 149 +A 149 +tra 148 +ient 148 +_al 147 +a,_ 146 +ica 146 +a, 146 +pro 146 +ado_ 145 +ici 144 +_ca 144 +an_ 144 +las_ 143 +ara 143 +nci 143 +ente 142 +ú 142 +rr 142 +ir 142 +da_ 141 +em 141 +ll 140 +il 139 +ía 138 +iv 138 +_su 138 +_par 136 +ul 136 +ant 136 +_A 135 +mp 135 +_las_ 134 +_las 134 +_C 134 +_pro 133 +men 132 +P 132 +des 131 +com 130 +ion 130 +era 130 +ed 129 +ida 129 +sp 128 +gu 127 +nte_ 127 +ns 127 +za 126 +dos 125 +M 125 +cio 125 +les 125 +_P 124 +bl 124 +_com 122 +s._ 122 +s. 122 +_M 121 +ua 120 +nta 120 +mu 119 +_no 118 +dad 118 +ñ 117 +é 116 +un_ 116 +va 116 +ist 116 +nes 116 +iento 115 +one 114 +ara_ 113 +S 113 +ada 113 +_un_ 113 +fi 111 +pre 110 +tos 110 +ter 109 +ot 109 +esta 108 +_me 107 +ido 107 +ob 107 +_g 105 +br 105 +go 105 +ea 104 +nto_ 104 +ona 103 +pu 103 +dos_ 103 +tro 103 +ier 103 +para 102 +ment 101 +ag 101 +ero 101 +gr 101 +rec 101 +bi 101 +ia_ 100 +una 100 +nic 99 +ncia 99 +ía_ 98 +a._ 98 +tos_ 98 +a. 98 +ran 98 +lo_ 97 +ones 97 +rm 96 +lu 96 +ron 95 +con_ 95 +ó_ 95 +nes_ 95 +_ci 95 +ante 94 +ch 94 +_con_ 94 +_para 94 +ntr 93 +una_ 93 +para_ 93 +mie 92 +ico 92 +fe 92 +les_ 92 +uc 92 +ip 91 +sto 91 +_ma 91 +ui 91 +sta_ 91 +_ve 90 +cion 90 +" 90 +op 90 +cal 89 +_mu 89 +_S 89 +ro_ 89 +_pe 88 +ste 88 +ras 88 +pl 88 +_una 88 +_di 87 +ento_ 86 +ita 86 +ione 85 +ect 85 +_una_ 85 +mien 85 +tan 85 +du 84 +den 84 +ndo 84 +per 84 +eri 84 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/swedish.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/swedish.lm new file mode 100644 index 0000000..8cb1aec --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/swedish.lm @@ -0,0 +1,400 @@ +_ 33494 +e 8992 +n 7900 +t 7859 +a 7781 +r 7251 +s 6435 +i 5649 +l 4541 +d 4079 +o 3724 +m 3203 +k 3058 +g 2478 +en 2403 +n_ 2389 +t_ 2073 +de 1939 +r_ 1910 +v 1890 +h 1789 +u 1782 +_s 1768 +ä 1724 +er 1709 +f 1597 +en_ 1537 +a_ 1526 +an 1357 +p 1320 +et 1317 +ö 1278 +å 1261 +st 1236 +ar 1226 +c 1191 +_d 1158 +e_ 1116 +in 1045 +_f 1027 +te 1000 +b 997 +_a 978 +s_ 974 +ra 958 +. 956 +tt 935 +_i 898 +_m 890 +._ 886 +ll 870 +ta 844 +_o 842 +_e 839 +nd 820 +ti 804 +sk 798 +re 779 +at 769 +_de 754 +om 743 +m_ 739 +ör 720 +, 697 +,_ 695 +ng 686 +li 673 +ka 666 +oc 662 +_h 654 +on 652 +et_ 647 +ch 645 +ns 643 +is 642 +er_ 630 +är 625 +_v 614 +_t 614 +ni 611 +i_ 609 +_oc 592 +tt_ 587 +na 586 +y 586 +la 579 +_b 579 +h_ 577 +kt 575 +ch_ 568 +ig 564 +fö 563 +och 555 +or 555 +_och 554 +och_ 554 +_och_ 553 +me 548 +den 548 +om_ 535 +_i_ 531 +d_ 530 +j 529 +ik 520 +de_ 520 +för 518 +ge 498 +ad 497 +_k 491 +_fö 487 +ri 484 +el 482 +il 481 +so 480 +al 474 +g_ 469 +le 464 +an_ 461 +_för 447 +si 437 +ar_ 437 +att 435 +_p 434 +es 420 +ing 413 +se 407 +to 404 +_u 403 +_en 403 +and 398 +den_ 395 +nde 393 +nn 393 +_l 391 +å_ 391 +D 385 +än 383 +nt 382 +l_ 381 +tr 378 +_D 372 +va 370 +am 369 +sa 367 +_so 365 +ga 364 +_en_ 361 +är_ 358 +ck 357 +av 354 +v_ 351 +ed 347 +ma 346 +da 346 +som 346 +rs 344 +som_ 344 +ve 342 +ter 341 +att_ 341 +ha 338 +ne 337 +ut 335 +as 332 +ska 329 +_at 327 +_att 326 +_som 324 +_att_ 324 +_som_ 323 +vi 322 +ikt 317 +_av 316 +det 316 +_den 315 +he 315 +ss 314 +un 307 +ke 304 +_g 303 +us 302 +di 302 +_st 300 +rn 297 +_me 296 +_ä 295 +ade 294 +" 290 +_ha 290 +av_ 289 +ill 288 +_n 286 +_in 279 +io 275 +_r 275 +der 275 +it 274 +_av_ 274 +sta 274 +gen 272 +isk 270 +_ti 269 +id 265 +na_ 265 +ns_ 264 +ko 262 +_den_ 261 +ag 258 +det_ 257 +lig 257 +era 256 +ll_ 255 +_det 252 +_är 251 +be 249 +_är_ 248 +ra_ 247 +ion 244 +- 241 +pr 240 +oni 233 +til 231 +ten 228 +_si 225 +k_ 222 +på 222 +fr 221 +ro 219 +till 219 +iv 216 +ls 216 +ande 215 +ör_ 214 +_det_ 213 +äl 212 +_på 211 +ts 210 +ens 209 +med 209 +mm 208 +rt 208 +_till 208 +_til 208 +_va 207 +_fr 205 +_sk 205 +var 205 +nin 204 +ning 203 +ol 201 +ka_ 200 +lle 198 +ett 198 +rd 197 +em 196 +på_ 195 +x 195 +rk 194 +_ut 194 +ste 194 +ds 193 +_vi 192 +år 192 +S 192 +nde_ 191 +are 191 +ver 190 +_på_ 190 +nis 189 +kr 189 +_med 188 +all 188 +ån 187 +nge 185 +mo 184 +os 183 +ld 182 +ade_ 181 +_S 181 +ed_ 180 +rä 176 +De 175 +_- 175 +kan 174 +ta_ 173 +ng_ 172 +vä 171 +för_ 170 +ill_ 170 +han 170 +_De 170 +pp 169 +lt 169 +sam 168 +nte 167 +ans 167 +ton 166 +ur 165 +mi 165 +ess 165 +kl 164 +ig_ 164 +ks 164 +as_ 163 +und 163 +men 162 +med_ 161 +_med_ 161 +ak 161 +Di 160 +ot 159 +rna 159 +ul 159 +_var 159 +te_ 158 +gen_ 158 +het 157 +kto 157 +str 156 +_Di 155 +tad 155 +lan 154 +ga_ 154 +iska 154 +fa 154 +fi 154 +så 154 +Dikt 153 +Dik 153 +pe 153 +ska_ 152 +ja 152 +H 151 +res 151 +ku 151 +iu 150 +ande_ 150 +till_ 150 +t. 150 +ern 150 +rm 149 +_Dikt 149 +_Dik 149 +ie 149 +bl 148 +-_ 147 +od 147 +_H 147 +n. 147 +ist 147 +_di 146 +ius 146 +_" 145 +la_ 145 +sl 145 +man 145 +ren 145 +_för_ 145 +toni 144 +kton 144 +n._ 144 +ktoni 144 +ikton 144 +I 144 +ikto 144 +nius 143 +ten_ 143 +onius 143 +oniu 143 +toniu 143 +ing_ 143 +Dikto 143 +niu 143 +_ko 143 +ic 142 +_sa 142 +_han 142 +ett_ 142 +sm 141 +ba 141 +M 141 +gr 140 +lä 140 +ex 138 +t._ 138 +sp 137 +lla 137 +_et 137 +_M 137 +dr 137 +rö 136 +rad 136 +ek 136 +_be 135 +tar 135 +_-_ 135 +_om 134 +rl 134 +E 134 +mä 133 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/LM/turkish.lm b/interactive-mining-3rdparty-madis/madis/src/lib/LM/turkish.lm new file mode 100644 index 0000000..47bdbfd --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/LM/turkish.lm @@ -0,0 +1,400 @@ +_ 23226 +i 8957 +a 7675 +e 6219 +n 5169 +& 4950 +; 4950 +l 4674 +r 4464 +&i 3206 +&i; 3206 +i; 3206 +s 3206 +k 3009 +d 2977 +t 2442 +m 2010 +y 2001 +u 1885 +n_ 1725 +g 1584 +o 1567 +b 1470 +e_ 1426 +ü 1353 +ar 1273 +la 1236 +a_ 1209 +i_ 1169 +in 1124 +_b 1101 +an 1097 +er 1073 +le 1058 +s; 1036 +&s; 1036 +&s 1036 +;_ 1018 +de 936 +;n 918 +&i;n 917 +i;n 917 +,_ 872 +_, 872 +_,_ 872 +, 872 +i;_ 863 +&i;_ 863 +_k 816 +en 769 +r_ 762 +_y 759 +da 759 +il 759 +k_ 750 +z 739 +nd 725 +&g; 708 +g; 708 +&g 708 +ra 697 +_a 692 +_d 692 +_s 676 +' 673 +_i 644 +._ 641 +. 641 +_. 637 +_._ 637 +c 637 +ka 635 +v 632 +;& 624 +h 615 +_g 597 +ri 596 +ç 596 +lar 583 +li 580 +ma 559 +ya 555 +ler 553 +p 547 +re 529 +al 529 +ö 527 +_t 520 +ir 508 +ak 502 +bi 500 +;l 480 +in_ 478 +di 477 +r& 468 +el 453 +et 449 +ek 445 +n& 439 +_o 439 +ol 437 +da_ 434 +n&i 433 +n&i; 433 +ni 429 +ti 428 +de_ 425 +an_ 422 +eri 421 +r&i 417 +r&i; 417 +s& 413 +s&i 413 +s&i; 413 +ar& 412 +me 407 +te 405 +a& 404 +i& 390 +ay 387 +ne 380 +_bi 373 +_ka 368 +ar&i; 367 +ar&i 367 +u_ 363 +as 363 +_e 362 +ta 359 +&i;l 352 +i;l 352 +nda 350 +ki 347 +na 346 +si 343 +_v 337 +;&i; 334 +;&i 334 +ve 334 +ara 333 +en_ 332 +;i 331 +on 328 +un 326 +l&i; 322 +l& 322 +l&i 322 +leri 322 +ba 318 +_m 318 +ik 315 +mi 315 +f 306 +lar& 302 +lar&i 302 +sa 298 +_h 297 +ld 296 +&i;& 290 +i;& 290 +_ve 288 +l_ 287 +ge 286 +is 285 +ed 285 +i&s; 284 +i&s 284 +;r 282 +_ya 279 +_ol 279 +d&i; 278 +d& 278 +d&i 278 +nl 277 +kl 275 +;k 274 +&i;n_ 271 +;n_ 271 +i;n_ 271 +ile 270 +or 269 +iy 267 +a&s 264 +a&s; 264 +y&i; 262 +ad 262 +y& 262 +y&i 262 +ye 259 +ha 258 +es 258 +t& 257 +t&i 257 +t&i; 257 +ini 253 +;nd 253 +i;nd 253 +ür 253 +&i;nd 253 +se 248 +_ge 248 +i;nda 248 +;nda 248 +;n&i; 247 +i;n& 247 +;n& 247 +&i;n& 247 +i;n&i 247 +;n&i 247 +bu 245 +_' 245 +_ba 244 +as&i 242 +as&i; 242 +_de 242 +as& 242 +at 240 +am 240 +nda_ 239 +ar_ 231 +ve_ 230 +rin 230 +_ve_ 228 +_bu 227 +im 227 +&i;r 226 +i;r 226 +ur 221 +g;&i 220 +g;& 220 +&g;& 220 +yo 220 +&g;&i 220 +g;&i; 220 +ul 215 +ak_ 215 +ke 213 +nu 213 +erin 211 +g;i 208 +&g;i 208 +lan 207 +bir 205 +r&i;n 205 +nde 202 +rl 202 +n&i;_ 201 +ko 201 +ca 200 +m_ 197 +rd 196 +t_ 194 +er_ 194 +st 193 +em 193 +_sa 190 +lm 189 +rt 188 +_ü 187 +i;k 187 +ün 187 +ola 187 +&i;k 187 +lerin 185 +ce 185 +'_ 185 +;m 183 +az 183 +rk 182 +yü 182 +;la 181 +_bir 181 +ir_ 180 +n&i;n 180 +ru 180 +lu 180 +;nda_ 178 +e& 177 +_ç 176 +_ha 175 +_ko 173 +esi 171 +_ö 170 +ap 170 +ni_ 168 +tü 167 +den 164 +ind 161 +di_ 161 +be 161 +s&i;n 160 +nin 159 +üz 158 +ri_ 155 +y&i;l 155 +_p 154 +nin_ 153 +&s;_ 152 +_y& 152 +edi 152 +s;_ 152 +_y&i; 152 +_y&i 152 +yl 151 +le_ 151 +inde 150 +eti 150 +ala 150 +&i;&s 149 +ele 149 +i;&s; 149 +;&s; 149 +;&s 149 +i;&s 149 +ek_ 148 +ere 148 +çi 147 +du 145 +ön 145 +z_ 144 +na_ 144 +eri_ 143 +ec 142 +gö 142 +i;&g; 141 +s&i;_ 141 +bir_ 141 +&i;&g 141 +i;&g 141 +ah 141 +;&g; 141 +;&g 141 +_gö 140 +lar_ 140 +eli 140 +a&g; 140 +a&g 140 +dan 140 +ac 140 +iç 140 +an& 140 +u& 139 +;&g;& 138 +_yü 138 +an&i 138 +an&i; 138 +pa 138 +it 137 +_ola 137 +_bir_ 136 +;t 135 +ör 135 +ne_ 135 +ini_ 134 +lma 134 +kan 133 +ab 132 +to 131 +ba& 131 +kar 130 +r&i;_ 130 +_ar 129 +ili 129 +li_ 129 +ki_ 128 +bu_ 127 +anl 127 +dü 127 +ler_ 126 +_ba& 126 +kon 126 +ll 125 +tl 125 +ine 125 +e&g; 124 +e&g 124 +_il 124 +_bu_ 124 +re_ 124 +bil 123 +&s;i 123 +;&i;n 123 +s;i 123 +ede 123 +zd 123 +'' 122 +_da 122 +_'' 122 +_tü 122 +ret 122 +_-_ 121 +_''_ 121 +mas 121 +''_ 121 +- 121 +dan_ 121 +leri_ 121 +;u 121 +_- 121 +ev 121 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/TableHTMLParser.py b/interactive-mining-3rdparty-madis/madis/src/lib/TableHTMLParser.py new file mode 100644 index 0000000..6b1b668 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/TableHTMLParser.py @@ -0,0 +1,177 @@ +from HTMLParser import * +import re +import Queue + + +piencodingRegExp = '.*encoding=\"([^\"]+)\"' + +metaencodingRegExp = '.*charset=([^\" ;]+)' + +class TableHTMLParser(HTMLParser): + "HTMLParser derived parser." + + bInspecting = True + idle = 0 + intable = 1 + inheader = 2 + inraw = 3 + incolumn = 4 + state = idle + tablesFound = 0 + + def __init__(self, tableNum): + "Initialise an object, passing 'verbose' to the superclass." + HTMLParser.__init__(self) + self.line = [] + self.lines = [] + self.header=[] + self.value='' + self.tableNum = tableNum + self.encoding = 'utf-8' + self.rowIndex = 0 + self.columnIndex = 0 + self.columnsNumber=0 + self.rowRepeats=dict() + + def close(self): + self.f.close() + + + def parse(self, s): + "Parse the given string 's'." + self.lines = [] + self.feed(unicode(s,self.encoding)) + if self.columnsNumber==0 and self.lines!=[]: + self.columnsNumber=len(self.lines[0]) + for el in self.lines: + lineSize=len(el) + if lineSize +# +# 128 --> 0.42261 +# 256 --> 0.57851 +# 512 --> 0.74851 +# 1024 --> 0.89384 +# 2048 --> 0.97583 +# +# Ideal Distribution Ratio = 0.74851/(1-0.74851) =2.98 +# Random Distribution Ration = 512/(5401-512)=0.105 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR + +BIG5_TYPICAL_DISTRIBUTION_RATIO = 0.75 + +#Char to FreqOrder table +BIG5_TABLE_SIZE = 5376 + +Big5CharToFreqOrder = ( \ + 1,1801,1506, 255,1431, 198, 9, 82, 6,5008, 177, 202,3681,1256,2821, 110, # 16 +3814, 33,3274, 261, 76, 44,2114, 16,2946,2187,1176, 659,3971, 26,3451,2653, # 32 +1198,3972,3350,4202, 410,2215, 302, 590, 361,1964, 8, 204, 58,4510,5009,1932, # 48 + 63,5010,5011, 317,1614, 75, 222, 159,4203,2417,1480,5012,3555,3091, 224,2822, # 64 +3682, 3, 10,3973,1471, 29,2787,1135,2866,1940, 873, 130,3275,1123, 312,5013, # 80 +4511,2052, 507, 252, 682,5014, 142,1915, 124, 206,2947, 34,3556,3204, 64, 604, # 96 +5015,2501,1977,1978, 155,1991, 645, 641,1606,5016,3452, 337, 72, 406,5017, 80, # 112 + 630, 238,3205,1509, 263, 939,1092,2654, 756,1440,1094,3453, 449, 69,2987, 591, # 128 + 179,2096, 471, 115,2035,1844, 60, 50,2988, 134, 806,1869, 734,2036,3454, 180, # 144 + 995,1607, 156, 537,2907, 688,5018, 319,1305, 779,2145, 514,2379, 298,4512, 359, # 160 +2502, 90,2716,1338, 663, 11, 906,1099,2553, 20,2441, 182, 532,1716,5019, 732, # 176 +1376,4204,1311,1420,3206, 25,2317,1056, 113, 399, 382,1950, 242,3455,2474, 529, # 192 +3276, 475,1447,3683,5020, 117, 21, 656, 810,1297,2300,2334,3557,5021, 126,4205, # 208 + 706, 456, 150, 613,4513, 71,1118,2037,4206, 145,3092, 85, 835, 486,2115,1246, # 224 +1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,5022,2128,2359, 347,3815, 221, # 240 +3558,3135,5023,1956,1153,4207, 83, 296,1199,3093, 192, 624, 93,5024, 822,1898, # 256 +2823,3136, 795,2065, 991,1554,1542,1592, 27, 43,2867, 859, 139,1456, 860,4514, # 272 + 437, 712,3974, 164,2397,3137, 695, 211,3037,2097, 195,3975,1608,3559,3560,3684, # 288 +3976, 234, 811,2989,2098,3977,2233,1441,3561,1615,2380, 668,2077,1638, 305, 228, # 304 +1664,4515, 467, 415,5025, 262,2099,1593, 239, 108, 300, 200,1033, 512,1247,2078, # 320 +5026,5027,2176,3207,3685,2682, 593, 845,1062,3277, 88,1723,2038,3978,1951, 212, # 336 + 266, 152, 149, 468,1899,4208,4516, 77, 187,5028,3038, 37, 5,2990,5029,3979, # 352 +5030,5031, 39,2524,4517,2908,3208,2079, 55, 148, 74,4518, 545, 483,1474,1029, # 368 +1665, 217,1870,1531,3138,1104,2655,4209, 24, 172,3562, 900,3980,3563,3564,4519, # 384 + 32,1408,2824,1312, 329, 487,2360,2251,2717, 784,2683, 4,3039,3351,1427,1789, # 400 + 188, 109, 499,5032,3686,1717,1790, 888,1217,3040,4520,5033,3565,5034,3352,1520, # 416 +3687,3981, 196,1034, 775,5035,5036, 929,1816, 249, 439, 38,5037,1063,5038, 794, # 432 +3982,1435,2301, 46, 178,3278,2066,5039,2381,5040, 214,1709,4521, 804, 35, 707, # 448 + 324,3688,1601,2554, 140, 459,4210,5041,5042,1365, 839, 272, 978,2262,2580,3456, # 464 +2129,1363,3689,1423, 697, 100,3094, 48, 70,1231, 495,3139,2196,5043,1294,5044, # 480 +2080, 462, 586,1042,3279, 853, 256, 988, 185,2382,3457,1698, 434,1084,5045,3458, # 496 + 314,2625,2788,4522,2335,2336, 569,2285, 637,1817,2525, 757,1162,1879,1616,3459, # 512 + 287,1577,2116, 768,4523,1671,2868,3566,2526,1321,3816, 909,2418,5046,4211, 933, # 528 +3817,4212,2053,2361,1222,4524, 765,2419,1322, 786,4525,5047,1920,1462,1677,2909, # 544 +1699,5048,4526,1424,2442,3140,3690,2600,3353,1775,1941,3460,3983,4213, 309,1369, # 560 +1130,2825, 364,2234,1653,1299,3984,3567,3985,3986,2656, 525,1085,3041, 902,2001, # 576 +1475, 964,4527, 421,1845,1415,1057,2286, 940,1364,3141, 376,4528,4529,1381, 7, # 592 +2527, 983,2383, 336,1710,2684,1846, 321,3461, 559,1131,3042,2752,1809,1132,1313, # 608 + 265,1481,1858,5049, 352,1203,2826,3280, 167,1089, 420,2827, 776, 792,1724,3568, # 624 +4214,2443,3281,5050,4215,5051, 446, 229, 333,2753, 901,3818,1200,1557,4530,2657, # 640 +1921, 395,2754,2685,3819,4216,1836, 125, 916,3209,2626,4531,5052,5053,3820,5054, # 656 +5055,5056,4532,3142,3691,1133,2555,1757,3462,1510,2318,1409,3569,5057,2146, 438, # 672 +2601,2910,2384,3354,1068, 958,3043, 461, 311,2869,2686,4217,1916,3210,4218,1979, # 688 + 383, 750,2755,2627,4219, 274, 539, 385,1278,1442,5058,1154,1965, 384, 561, 210, # 704 + 98,1295,2556,3570,5059,1711,2420,1482,3463,3987,2911,1257, 129,5060,3821, 642, # 720 + 523,2789,2790,2658,5061, 141,2235,1333, 68, 176, 441, 876, 907,4220, 603,2602, # 736 + 710, 171,3464, 404, 549, 18,3143,2398,1410,3692,1666,5062,3571,4533,2912,4534, # 752 +5063,2991, 368,5064, 146, 366, 99, 871,3693,1543, 748, 807,1586,1185, 22,2263, # 768 + 379,3822,3211,5065,3212, 505,1942,2628,1992,1382,2319,5066, 380,2362, 218, 702, # 784 +1818,1248,3465,3044,3572,3355,3282,5067,2992,3694, 930,3283,3823,5068, 59,5069, # 800 + 585, 601,4221, 497,3466,1112,1314,4535,1802,5070,1223,1472,2177,5071, 749,1837, # 816 + 690,1900,3824,1773,3988,1476, 429,1043,1791,2236,2117, 917,4222, 447,1086,1629, # 832 +5072, 556,5073,5074,2021,1654, 844,1090, 105, 550, 966,1758,2828,1008,1783, 686, # 848 +1095,5075,2287, 793,1602,5076,3573,2603,4536,4223,2948,2302,4537,3825, 980,2503, # 864 + 544, 353, 527,4538, 908,2687,2913,5077, 381,2629,1943,1348,5078,1341,1252, 560, # 880 +3095,5079,3467,2870,5080,2054, 973, 886,2081, 143,4539,5081,5082, 157,3989, 496, # 896 +4224, 57, 840, 540,2039,4540,4541,3468,2118,1445, 970,2264,1748,1966,2082,4225, # 912 +3144,1234,1776,3284,2829,3695, 773,1206,2130,1066,2040,1326,3990,1738,1725,4226, # 928 + 279,3145, 51,1544,2604, 423,1578,2131,2067, 173,4542,1880,5083,5084,1583, 264, # 944 + 610,3696,4543,2444, 280, 154,5085,5086,5087,1739, 338,1282,3096, 693,2871,1411, # 960 +1074,3826,2445,5088,4544,5089,5090,1240, 952,2399,5091,2914,1538,2688, 685,1483, # 976 +4227,2475,1436, 953,4228,2055,4545, 671,2400, 79,4229,2446,3285, 608, 567,2689, # 992 +3469,4230,4231,1691, 393,1261,1792,2401,5092,4546,5093,5094,5095,5096,1383,1672, # 1008 +3827,3213,1464, 522,1119, 661,1150, 216, 675,4547,3991,1432,3574, 609,4548,2690, # 1024 +2402,5097,5098,5099,4232,3045, 0,5100,2476, 315, 231,2447, 301,3356,4549,2385, # 1040 +5101, 233,4233,3697,1819,4550,4551,5102, 96,1777,1315,2083,5103, 257,5104,1810, # 1056 +3698,2718,1139,1820,4234,2022,1124,2164,2791,1778,2659,5105,3097, 363,1655,3214, # 1072 +5106,2993,5107,5108,5109,3992,1567,3993, 718, 103,3215, 849,1443, 341,3357,2949, # 1088 +1484,5110,1712, 127, 67, 339,4235,2403, 679,1412, 821,5111,5112, 834, 738, 351, # 1104 +2994,2147, 846, 235,1497,1881, 418,1993,3828,2719, 186,1100,2148,2756,3575,1545, # 1120 +1355,2950,2872,1377, 583,3994,4236,2581,2995,5113,1298,3699,1078,2557,3700,2363, # 1136 + 78,3829,3830, 267,1289,2100,2002,1594,4237, 348, 369,1274,2197,2178,1838,4552, # 1152 +1821,2830,3701,2757,2288,2003,4553,2951,2758, 144,3358, 882,4554,3995,2759,3470, # 1168 +4555,2915,5114,4238,1726, 320,5115,3996,3046, 788,2996,5116,2831,1774,1327,2873, # 1184 +3997,2832,5117,1306,4556,2004,1700,3831,3576,2364,2660, 787,2023, 506, 824,3702, # 1200 + 534, 323,4557,1044,3359,2024,1901, 946,3471,5118,1779,1500,1678,5119,1882,4558, # 1216 + 165, 243,4559,3703,2528, 123, 683,4239, 764,4560, 36,3998,1793, 589,2916, 816, # 1232 + 626,1667,3047,2237,1639,1555,1622,3832,3999,5120,4000,2874,1370,1228,1933, 891, # 1248 +2084,2917, 304,4240,5121, 292,2997,2720,3577, 691,2101,4241,1115,4561, 118, 662, # 1264 +5122, 611,1156, 854,2386,1316,2875, 2, 386, 515,2918,5123,5124,3286, 868,2238, # 1280 +1486, 855,2661, 785,2216,3048,5125,1040,3216,3578,5126,3146, 448,5127,1525,5128, # 1296 +2165,4562,5129,3833,5130,4242,2833,3579,3147, 503, 818,4001,3148,1568, 814, 676, # 1312 +1444, 306,1749,5131,3834,1416,1030, 197,1428, 805,2834,1501,4563,5132,5133,5134, # 1328 +1994,5135,4564,5136,5137,2198, 13,2792,3704,2998,3149,1229,1917,5138,3835,2132, # 1344 +5139,4243,4565,2404,3580,5140,2217,1511,1727,1120,5141,5142, 646,3836,2448, 307, # 1360 +5143,5144,1595,3217,5145,5146,5147,3705,1113,1356,4002,1465,2529,2530,5148, 519, # 1376 +5149, 128,2133, 92,2289,1980,5150,4003,1512, 342,3150,2199,5151,2793,2218,1981, # 1392 +3360,4244, 290,1656,1317, 789, 827,2365,5152,3837,4566, 562, 581,4004,5153, 401, # 1408 +4567,2252, 94,4568,5154,1399,2794,5155,1463,2025,4569,3218,1944,5156, 828,1105, # 1424 +4245,1262,1394,5157,4246, 605,4570,5158,1784,2876,5159,2835, 819,2102, 578,2200, # 1440 +2952,5160,1502, 436,3287,4247,3288,2836,4005,2919,3472,3473,5161,2721,2320,5162, # 1456 +5163,2337,2068, 23,4571, 193, 826,3838,2103, 699,1630,4248,3098, 390,1794,1064, # 1472 +3581,5164,1579,3099,3100,1400,5165,4249,1839,1640,2877,5166,4572,4573, 137,4250, # 1488 + 598,3101,1967, 780, 104, 974,2953,5167, 278, 899, 253, 402, 572, 504, 493,1339, # 1504 +5168,4006,1275,4574,2582,2558,5169,3706,3049,3102,2253, 565,1334,2722, 863, 41, # 1520 +5170,5171,4575,5172,1657,2338, 19, 463,2760,4251, 606,5173,2999,3289,1087,2085, # 1536 +1323,2662,3000,5174,1631,1623,1750,4252,2691,5175,2878, 791,2723,2663,2339, 232, # 1552 +2421,5176,3001,1498,5177,2664,2630, 755,1366,3707,3290,3151,2026,1609, 119,1918, # 1568 +3474, 862,1026,4253,5178,4007,3839,4576,4008,4577,2265,1952,2477,5179,1125, 817, # 1584 +4254,4255,4009,1513,1766,2041,1487,4256,3050,3291,2837,3840,3152,5180,5181,1507, # 1600 +5182,2692, 733, 40,1632,1106,2879, 345,4257, 841,2531, 230,4578,3002,1847,3292, # 1616 +3475,5183,1263, 986,3476,5184, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562, # 1632 +4010,4011,2954, 967,2761,2665,1349, 592,2134,1692,3361,3003,1995,4258,1679,4012, # 1648 +1902,2188,5185, 739,3708,2724,1296,1290,5186,4259,2201,2202,1922,1563,2605,2559, # 1664 +1871,2762,3004,5187, 435,5188, 343,1108, 596, 17,1751,4579,2239,3477,3709,5189, # 1680 +4580, 294,3582,2955,1693, 477, 979, 281,2042,3583, 643,2043,3710,2631,2795,2266, # 1696 +1031,2340,2135,2303,3584,4581, 367,1249,2560,5190,3585,5191,4582,1283,3362,2005, # 1712 + 240,1762,3363,4583,4584, 836,1069,3153, 474,5192,2149,2532, 268,3586,5193,3219, # 1728 +1521,1284,5194,1658,1546,4260,5195,3587,3588,5196,4261,3364,2693,1685,4262, 961, # 1744 +1673,2632, 190,2006,2203,3841,4585,4586,5197, 570,2504,3711,1490,5198,4587,2633, # 1760 +3293,1957,4588, 584,1514, 396,1045,1945,5199,4589,1968,2449,5200,5201,4590,4013, # 1776 + 619,5202,3154,3294, 215,2007,2796,2561,3220,4591,3221,4592, 763,4263,3842,4593, # 1792 +5203,5204,1958,1767,2956,3365,3712,1174, 452,1477,4594,3366,3155,5205,2838,1253, # 1808 +2387,2189,1091,2290,4264, 492,5206, 638,1169,1825,2136,1752,4014, 648, 926,1021, # 1824 +1324,4595, 520,4596, 997, 847,1007, 892,4597,3843,2267,1872,3713,2405,1785,4598, # 1840 +1953,2957,3103,3222,1728,4265,2044,3714,4599,2008,1701,3156,1551, 30,2268,4266, # 1856 +5207,2027,4600,3589,5208, 501,5209,4267, 594,3478,2166,1822,3590,3479,3591,3223, # 1872 + 829,2839,4268,5210,1680,3157,1225,4269,5211,3295,4601,4270,3158,2341,5212,4602, # 1888 +4271,5213,4015,4016,5214,1848,2388,2606,3367,5215,4603, 374,4017, 652,4272,4273, # 1904 + 375,1140, 798,5216,5217,5218,2366,4604,2269, 546,1659, 138,3051,2450,4605,5219, # 1920 +2254, 612,1849, 910, 796,3844,1740,1371, 825,3845,3846,5220,2920,2562,5221, 692, # 1936 + 444,3052,2634, 801,4606,4274,5222,1491, 244,1053,3053,4275,4276, 340,5223,4018, # 1952 +1041,3005, 293,1168, 87,1357,5224,1539, 959,5225,2240, 721, 694,4277,3847, 219, # 1968 +1478, 644,1417,3368,2666,1413,1401,1335,1389,4019,5226,5227,3006,2367,3159,1826, # 1984 + 730,1515, 184,2840, 66,4607,5228,1660,2958, 246,3369, 378,1457, 226,3480, 975, # 2000 +4020,2959,1264,3592, 674, 696,5229, 163,5230,1141,2422,2167, 713,3593,3370,4608, # 2016 +4021,5231,5232,1186, 15,5233,1079,1070,5234,1522,3224,3594, 276,1050,2725, 758, # 2032 +1126, 653,2960,3296,5235,2342, 889,3595,4022,3104,3007, 903,1250,4609,4023,3481, # 2048 +3596,1342,1681,1718, 766,3297, 286, 89,2961,3715,5236,1713,5237,2607,3371,3008, # 2064 +5238,2962,2219,3225,2880,5239,4610,2505,2533, 181, 387,1075,4024, 731,2190,3372, # 2080 +5240,3298, 310, 313,3482,2304, 770,4278, 54,3054, 189,4611,3105,3848,4025,5241, # 2096 +1230,1617,1850, 355,3597,4279,4612,3373, 111,4280,3716,1350,3160,3483,3055,4281, # 2112 +2150,3299,3598,5242,2797,4026,4027,3009, 722,2009,5243,1071, 247,1207,2343,2478, # 2128 +1378,4613,2010, 864,1437,1214,4614, 373,3849,1142,2220, 667,4615, 442,2763,2563, # 2144 +3850,4028,1969,4282,3300,1840, 837, 170,1107, 934,1336,1883,5244,5245,2119,4283, # 2160 +2841, 743,1569,5246,4616,4284, 582,2389,1418,3484,5247,1803,5248, 357,1395,1729, # 2176 +3717,3301,2423,1564,2241,5249,3106,3851,1633,4617,1114,2086,4285,1532,5250, 482, # 2192 +2451,4618,5251,5252,1492, 833,1466,5253,2726,3599,1641,2842,5254,1526,1272,3718, # 2208 +4286,1686,1795, 416,2564,1903,1954,1804,5255,3852,2798,3853,1159,2321,5256,2881, # 2224 +4619,1610,1584,3056,2424,2764, 443,3302,1163,3161,5257,5258,4029,5259,4287,2506, # 2240 +3057,4620,4030,3162,2104,1647,3600,2011,1873,4288,5260,4289, 431,3485,5261, 250, # 2256 + 97, 81,4290,5262,1648,1851,1558, 160, 848,5263, 866, 740,1694,5264,2204,2843, # 2272 +3226,4291,4621,3719,1687, 950,2479, 426, 469,3227,3720,3721,4031,5265,5266,1188, # 2288 + 424,1996, 861,3601,4292,3854,2205,2694, 168,1235,3602,4293,5267,2087,1674,4622, # 2304 +3374,3303, 220,2565,1009,5268,3855, 670,3010, 332,1208, 717,5269,5270,3603,2452, # 2320 +4032,3375,5271, 513,5272,1209,2882,3376,3163,4623,1080,5273,5274,5275,5276,2534, # 2336 +3722,3604, 815,1587,4033,4034,5277,3605,3486,3856,1254,4624,1328,3058,1390,4035, # 2352 +1741,4036,3857,4037,5278, 236,3858,2453,3304,5279,5280,3723,3859,1273,3860,4625, # 2368 +5281, 308,5282,4626, 245,4627,1852,2480,1307,2583, 430, 715,2137,2454,5283, 270, # 2384 + 199,2883,4038,5284,3606,2727,1753, 761,1754, 725,1661,1841,4628,3487,3724,5285, # 2400 +5286, 587, 14,3305, 227,2608, 326, 480,2270, 943,2765,3607, 291, 650,1884,5287, # 2416 +1702,1226, 102,1547, 62,3488, 904,4629,3489,1164,4294,5288,5289,1224,1548,2766, # 2432 + 391, 498,1493,5290,1386,1419,5291,2056,1177,4630, 813, 880,1081,2368, 566,1145, # 2448 +4631,2291,1001,1035,2566,2609,2242, 394,1286,5292,5293,2069,5294, 86,1494,1730, # 2464 +4039, 491,1588, 745, 897,2963, 843,3377,4040,2767,2884,3306,1768, 998,2221,2070, # 2480 + 397,1827,1195,1970,3725,3011,3378, 284,5295,3861,2507,2138,2120,1904,5296,4041, # 2496 +2151,4042,4295,1036,3490,1905, 114,2567,4296, 209,1527,5297,5298,2964,2844,2635, # 2512 +2390,2728,3164, 812,2568,5299,3307,5300,1559, 737,1885,3726,1210, 885, 28,2695, # 2528 +3608,3862,5301,4297,1004,1780,4632,5302, 346,1982,2222,2696,4633,3863,1742, 797, # 2544 +1642,4043,1934,1072,1384,2152, 896,4044,3308,3727,3228,2885,3609,5303,2569,1959, # 2560 +4634,2455,1786,5304,5305,5306,4045,4298,1005,1308,3728,4299,2729,4635,4636,1528, # 2576 +2610, 161,1178,4300,1983, 987,4637,1101,4301, 631,4046,1157,3229,2425,1343,1241, # 2592 +1016,2243,2570, 372, 877,2344,2508,1160, 555,1935, 911,4047,5307, 466,1170, 169, # 2608 +1051,2921,2697,3729,2481,3012,1182,2012,2571,1251,2636,5308, 992,2345,3491,1540, # 2624 +2730,1201,2071,2406,1997,2482,5309,4638, 528,1923,2191,1503,1874,1570,2369,3379, # 2640 +3309,5310, 557,1073,5311,1828,3492,2088,2271,3165,3059,3107, 767,3108,2799,4639, # 2656 +1006,4302,4640,2346,1267,2179,3730,3230, 778,4048,3231,2731,1597,2667,5312,4641, # 2672 +5313,3493,5314,5315,5316,3310,2698,1433,3311, 131, 95,1504,4049, 723,4303,3166, # 2688 +1842,3610,2768,2192,4050,2028,2105,3731,5317,3013,4051,1218,5318,3380,3232,4052, # 2704 +4304,2584, 248,1634,3864, 912,5319,2845,3732,3060,3865, 654, 53,5320,3014,5321, # 2720 +1688,4642, 777,3494,1032,4053,1425,5322, 191, 820,2121,2846, 971,4643, 931,3233, # 2736 + 135, 664, 783,3866,1998, 772,2922,1936,4054,3867,4644,2923,3234, 282,2732, 640, # 2752 +1372,3495,1127, 922, 325,3381,5323,5324, 711,2045,5325,5326,4055,2223,2800,1937, # 2768 +4056,3382,2224,2255,3868,2305,5327,4645,3869,1258,3312,4057,3235,2139,2965,4058, # 2784 +4059,5328,2225, 258,3236,4646, 101,1227,5329,3313,1755,5330,1391,3314,5331,2924, # 2800 +2057, 893,5332,5333,5334,1402,4305,2347,5335,5336,3237,3611,5337,5338, 878,1325, # 2816 +1781,2801,4647, 259,1385,2585, 744,1183,2272,4648,5339,4060,2509,5340, 684,1024, # 2832 +4306,5341, 472,3612,3496,1165,3315,4061,4062, 322,2153, 881, 455,1695,1152,1340, # 2848 + 660, 554,2154,4649,1058,4650,4307, 830,1065,3383,4063,4651,1924,5342,1703,1919, # 2864 +5343, 932,2273, 122,5344,4652, 947, 677,5345,3870,2637, 297,1906,1925,2274,4653, # 2880 +2322,3316,5346,5347,4308,5348,4309, 84,4310, 112, 989,5349, 547,1059,4064, 701, # 2896 +3613,1019,5350,4311,5351,3497, 942, 639, 457,2306,2456, 993,2966, 407, 851, 494, # 2912 +4654,3384, 927,5352,1237,5353,2426,3385, 573,4312, 680, 921,2925,1279,1875, 285, # 2928 + 790,1448,1984, 719,2168,5354,5355,4655,4065,4066,1649,5356,1541, 563,5357,1077, # 2944 +5358,3386,3061,3498, 511,3015,4067,4068,3733,4069,1268,2572,3387,3238,4656,4657, # 2960 +5359, 535,1048,1276,1189,2926,2029,3167,1438,1373,2847,2967,1134,2013,5360,4313, # 2976 +1238,2586,3109,1259,5361, 700,5362,2968,3168,3734,4314,5363,4315,1146,1876,1907, # 2992 +4658,2611,4070, 781,2427, 132,1589, 203, 147, 273,2802,2407, 898,1787,2155,4071, # 3008 +4072,5364,3871,2803,5365,5366,4659,4660,5367,3239,5368,1635,3872, 965,5369,1805, # 3024 +2699,1516,3614,1121,1082,1329,3317,4073,1449,3873, 65,1128,2848,2927,2769,1590, # 3040 +3874,5370,5371, 12,2668, 45, 976,2587,3169,4661, 517,2535,1013,1037,3240,5372, # 3056 +3875,2849,5373,3876,5374,3499,5375,2612, 614,1999,2323,3877,3110,2733,2638,5376, # 3072 +2588,4316, 599,1269,5377,1811,3735,5378,2700,3111, 759,1060, 489,1806,3388,3318, # 3088 +1358,5379,5380,2391,1387,1215,2639,2256, 490,5381,5382,4317,1759,2392,2348,5383, # 3104 +4662,3878,1908,4074,2640,1807,3241,4663,3500,3319,2770,2349, 874,5384,5385,3501, # 3120 +3736,1859, 91,2928,3737,3062,3879,4664,5386,3170,4075,2669,5387,3502,1202,1403, # 3136 +3880,2969,2536,1517,2510,4665,3503,2511,5388,4666,5389,2701,1886,1495,1731,4076, # 3152 +2370,4667,5390,2030,5391,5392,4077,2702,1216, 237,2589,4318,2324,4078,3881,4668, # 3168 +4669,2703,3615,3504, 445,4670,5393,5394,5395,5396,2771, 61,4079,3738,1823,4080, # 3184 +5397, 687,2046, 935, 925, 405,2670, 703,1096,1860,2734,4671,4081,1877,1367,2704, # 3200 +3389, 918,2106,1782,2483, 334,3320,1611,1093,4672, 564,3171,3505,3739,3390, 945, # 3216 +2641,2058,4673,5398,1926, 872,4319,5399,3506,2705,3112, 349,4320,3740,4082,4674, # 3232 +3882,4321,3741,2156,4083,4675,4676,4322,4677,2408,2047, 782,4084, 400, 251,4323, # 3248 +1624,5400,5401, 277,3742, 299,1265, 476,1191,3883,2122,4324,4325,1109, 205,5402, # 3264 +2590,1000,2157,3616,1861,5403,5404,5405,4678,5406,4679,2573, 107,2484,2158,4085, # 3280 +3507,3172,5407,1533, 541,1301, 158, 753,4326,2886,3617,5408,1696, 370,1088,4327, # 3296 +4680,3618, 579, 327, 440, 162,2244, 269,1938,1374,3508, 968,3063, 56,1396,3113, # 3312 +2107,3321,3391,5409,1927,2159,4681,3016,5410,3619,5411,5412,3743,4682,2485,5413, # 3328 +2804,5414,1650,4683,5415,2613,5416,5417,4086,2671,3392,1149,3393,4087,3884,4088, # 3344 +5418,1076, 49,5419, 951,3242,3322,3323, 450,2850, 920,5420,1812,2805,2371,4328, # 3360 +1909,1138,2372,3885,3509,5421,3243,4684,1910,1147,1518,2428,4685,3886,5422,4686, # 3376 +2393,2614, 260,1796,3244,5423,5424,3887,3324, 708,5425,3620,1704,5426,3621,1351, # 3392 +1618,3394,3017,1887, 944,4329,3395,4330,3064,3396,4331,5427,3744, 422, 413,1714, # 3408 +3325, 500,2059,2350,4332,2486,5428,1344,1911, 954,5429,1668,5430,5431,4089,2409, # 3424 +4333,3622,3888,4334,5432,2307,1318,2512,3114, 133,3115,2887,4687, 629, 31,2851, # 3440 +2706,3889,4688, 850, 949,4689,4090,2970,1732,2089,4335,1496,1853,5433,4091, 620, # 3456 +3245, 981,1242,3745,3397,1619,3746,1643,3326,2140,2457,1971,1719,3510,2169,5434, # 3472 +3246,5435,5436,3398,1829,5437,1277,4690,1565,2048,5438,1636,3623,3116,5439, 869, # 3488 +2852, 655,3890,3891,3117,4092,3018,3892,1310,3624,4691,5440,5441,5442,1733, 558, # 3504 +4692,3747, 335,1549,3065,1756,4336,3748,1946,3511,1830,1291,1192, 470,2735,2108, # 3520 +2806, 913,1054,4093,5443,1027,5444,3066,4094,4693, 982,2672,3399,3173,3512,3247, # 3536 +3248,1947,2807,5445, 571,4694,5446,1831,5447,3625,2591,1523,2429,5448,2090, 984, # 3552 +4695,3749,1960,5449,3750, 852, 923,2808,3513,3751, 969,1519, 999,2049,2325,1705, # 3568 +5450,3118, 615,1662, 151, 597,4095,2410,2326,1049, 275,4696,3752,4337, 568,3753, # 3584 +3626,2487,4338,3754,5451,2430,2275, 409,3249,5452,1566,2888,3514,1002, 769,2853, # 3600 + 194,2091,3174,3755,2226,3327,4339, 628,1505,5453,5454,1763,2180,3019,4096, 521, # 3616 +1161,2592,1788,2206,2411,4697,4097,1625,4340,4341, 412, 42,3119, 464,5455,2642, # 3632 +4698,3400,1760,1571,2889,3515,2537,1219,2207,3893,2643,2141,2373,4699,4700,3328, # 3648 +1651,3401,3627,5456,5457,3628,2488,3516,5458,3756,5459,5460,2276,2092, 460,5461, # 3664 +4701,5462,3020, 962, 588,3629, 289,3250,2644,1116, 52,5463,3067,1797,5464,5465, # 3680 +5466,1467,5467,1598,1143,3757,4342,1985,1734,1067,4702,1280,3402, 465,4703,1572, # 3696 + 510,5468,1928,2245,1813,1644,3630,5469,4704,3758,5470,5471,2673,1573,1534,5472, # 3712 +5473, 536,1808,1761,3517,3894,3175,2645,5474,5475,5476,4705,3518,2929,1912,2809, # 3728 +5477,3329,1122, 377,3251,5478, 360,5479,5480,4343,1529, 551,5481,2060,3759,1769, # 3744 +2431,5482,2930,4344,3330,3120,2327,2109,2031,4706,1404, 136,1468,1479, 672,1171, # 3760 +3252,2308, 271,3176,5483,2772,5484,2050, 678,2736, 865,1948,4707,5485,2014,4098, # 3776 +2971,5486,2737,2227,1397,3068,3760,4708,4709,1735,2931,3403,3631,5487,3895, 509, # 3792 +2854,2458,2890,3896,5488,5489,3177,3178,4710,4345,2538,4711,2309,1166,1010, 552, # 3808 + 681,1888,5490,5491,2972,2973,4099,1287,1596,1862,3179, 358, 453, 736, 175, 478, # 3824 +1117, 905,1167,1097,5492,1854,1530,5493,1706,5494,2181,3519,2292,3761,3520,3632, # 3840 +4346,2093,4347,5495,3404,1193,2489,4348,1458,2193,2208,1863,1889,1421,3331,2932, # 3856 +3069,2182,3521, 595,2123,5496,4100,5497,5498,4349,1707,2646, 223,3762,1359, 751, # 3872 +3121, 183,3522,5499,2810,3021, 419,2374, 633, 704,3897,2394, 241,5500,5501,5502, # 3888 + 838,3022,3763,2277,2773,2459,3898,1939,2051,4101,1309,3122,2246,1181,5503,1136, # 3904 +2209,3899,2375,1446,4350,2310,4712,5504,5505,4351,1055,2615, 484,3764,5506,4102, # 3920 + 625,4352,2278,3405,1499,4353,4103,5507,4104,4354,3253,2279,2280,3523,5508,5509, # 3936 +2774, 808,2616,3765,3406,4105,4355,3123,2539, 526,3407,3900,4356, 955,5510,1620, # 3952 +4357,2647,2432,5511,1429,3766,1669,1832, 994, 928,5512,3633,1260,5513,5514,5515, # 3968 +1949,2293, 741,2933,1626,4358,2738,2460, 867,1184, 362,3408,1392,5516,5517,4106, # 3984 +4359,1770,1736,3254,2934,4713,4714,1929,2707,1459,1158,5518,3070,3409,2891,1292, # 4000 +1930,2513,2855,3767,1986,1187,2072,2015,2617,4360,5519,2574,2514,2170,3768,2490, # 4016 +3332,5520,3769,4715,5521,5522, 666,1003,3023,1022,3634,4361,5523,4716,1814,2257, # 4032 + 574,3901,1603, 295,1535, 705,3902,4362, 283, 858, 417,5524,5525,3255,4717,4718, # 4048 +3071,1220,1890,1046,2281,2461,4107,1393,1599, 689,2575, 388,4363,5526,2491, 802, # 4064 +5527,2811,3903,2061,1405,2258,5528,4719,3904,2110,1052,1345,3256,1585,5529, 809, # 4080 +5530,5531,5532, 575,2739,3524, 956,1552,1469,1144,2328,5533,2329,1560,2462,3635, # 4096 +3257,4108, 616,2210,4364,3180,2183,2294,5534,1833,5535,3525,4720,5536,1319,3770, # 4112 +3771,1211,3636,1023,3258,1293,2812,5537,5538,5539,3905, 607,2311,3906, 762,2892, # 4128 +1439,4365,1360,4721,1485,3072,5540,4722,1038,4366,1450,2062,2648,4367,1379,4723, # 4144 +2593,5541,5542,4368,1352,1414,2330,2935,1172,5543,5544,3907,3908,4724,1798,1451, # 4160 +5545,5546,5547,5548,2936,4109,4110,2492,2351, 411,4111,4112,3637,3333,3124,4725, # 4176 +1561,2674,1452,4113,1375,5549,5550, 47,2974, 316,5551,1406,1591,2937,3181,5552, # 4192 +1025,2142,3125,3182, 354,2740, 884,2228,4369,2412, 508,3772, 726,3638, 996,2433, # 4208 +3639, 729,5553, 392,2194,1453,4114,4726,3773,5554,5555,2463,3640,2618,1675,2813, # 4224 + 919,2352,2975,2353,1270,4727,4115, 73,5556,5557, 647,5558,3259,2856,2259,1550, # 4240 +1346,3024,5559,1332, 883,3526,5560,5561,5562,5563,3334,2775,5564,1212, 831,1347, # 4256 +4370,4728,2331,3909,1864,3073, 720,3910,4729,4730,3911,5565,4371,5566,5567,4731, # 4272 +5568,5569,1799,4732,3774,2619,4733,3641,1645,2376,4734,5570,2938, 669,2211,2675, # 4288 +2434,5571,2893,5572,5573,1028,3260,5574,4372,2413,5575,2260,1353,5576,5577,4735, # 4304 +3183, 518,5578,4116,5579,4373,1961,5580,2143,4374,5581,5582,3025,2354,2355,3912, # 4320 + 516,1834,1454,4117,2708,4375,4736,2229,2620,1972,1129,3642,5583,2776,5584,2976, # 4336 +1422, 577,1470,3026,1524,3410,5585,5586, 432,4376,3074,3527,5587,2594,1455,2515, # 4352 +2230,1973,1175,5588,1020,2741,4118,3528,4737,5589,2742,5590,1743,1361,3075,3529, # 4368 +2649,4119,4377,4738,2295, 895, 924,4378,2171, 331,2247,3076, 166,1627,3077,1098, # 4384 +5591,1232,2894,2231,3411,4739, 657, 403,1196,2377, 542,3775,3412,1600,4379,3530, # 4400 +5592,4740,2777,3261, 576, 530,1362,4741,4742,2540,2676,3776,4120,5593, 842,3913, # 4416 +5594,2814,2032,1014,4121, 213,2709,3413, 665, 621,4380,5595,3777,2939,2435,5596, # 4432 +2436,3335,3643,3414,4743,4381,2541,4382,4744,3644,1682,4383,3531,1380,5597, 724, # 4448 +2282, 600,1670,5598,1337,1233,4745,3126,2248,5599,1621,4746,5600, 651,4384,5601, # 4464 +1612,4385,2621,5602,2857,5603,2743,2312,3078,5604, 716,2464,3079, 174,1255,2710, # 4480 +4122,3645, 548,1320,1398, 728,4123,1574,5605,1891,1197,3080,4124,5606,3081,3082, # 4496 +3778,3646,3779, 747,5607, 635,4386,4747,5608,5609,5610,4387,5611,5612,4748,5613, # 4512 +3415,4749,2437, 451,5614,3780,2542,2073,4388,2744,4389,4125,5615,1764,4750,5616, # 4528 +4390, 350,4751,2283,2395,2493,5617,4391,4126,2249,1434,4127, 488,4752, 458,4392, # 4544 +4128,3781, 771,1330,2396,3914,2576,3184,2160,2414,1553,2677,3185,4393,5618,2494, # 4560 +2895,2622,1720,2711,4394,3416,4753,5619,2543,4395,5620,3262,4396,2778,5621,2016, # 4576 +2745,5622,1155,1017,3782,3915,5623,3336,2313, 201,1865,4397,1430,5624,4129,5625, # 4592 +5626,5627,5628,5629,4398,1604,5630, 414,1866, 371,2595,4754,4755,3532,2017,3127, # 4608 +4756,1708, 960,4399, 887, 389,2172,1536,1663,1721,5631,2232,4130,2356,2940,1580, # 4624 +5632,5633,1744,4757,2544,4758,4759,5634,4760,5635,2074,5636,4761,3647,3417,2896, # 4640 +4400,5637,4401,2650,3418,2815, 673,2712,2465, 709,3533,4131,3648,4402,5638,1148, # 4656 + 502, 634,5639,5640,1204,4762,3649,1575,4763,2623,3783,5641,3784,3128, 948,3263, # 4672 + 121,1745,3916,1110,5642,4403,3083,2516,3027,4132,3785,1151,1771,3917,1488,4133, # 4688 +1987,5643,2438,3534,5644,5645,2094,5646,4404,3918,1213,1407,2816, 531,2746,2545, # 4704 +3264,1011,1537,4764,2779,4405,3129,1061,5647,3786,3787,1867,2897,5648,2018, 120, # 4720 +4406,4407,2063,3650,3265,2314,3919,2678,3419,1955,4765,4134,5649,3535,1047,2713, # 4736 +1266,5650,1368,4766,2858, 649,3420,3920,2546,2747,1102,2859,2679,5651,5652,2000, # 4752 +5653,1111,3651,2977,5654,2495,3921,3652,2817,1855,3421,3788,5655,5656,3422,2415, # 4768 +2898,3337,3266,3653,5657,2577,5658,3654,2818,4135,1460, 856,5659,3655,5660,2899, # 4784 +2978,5661,2900,3922,5662,4408, 632,2517, 875,3923,1697,3924,2296,5663,5664,4767, # 4800 +3028,1239, 580,4768,4409,5665, 914, 936,2075,1190,4136,1039,2124,5666,5667,5668, # 4816 +5669,3423,1473,5670,1354,4410,3925,4769,2173,3084,4137, 915,3338,4411,4412,3339, # 4832 +1605,1835,5671,2748, 398,3656,4413,3926,4138, 328,1913,2860,4139,3927,1331,4414, # 4848 +3029, 937,4415,5672,3657,4140,4141,3424,2161,4770,3425, 524, 742, 538,3085,1012, # 4864 +5673,5674,3928,2466,5675, 658,1103, 225,3929,5676,5677,4771,5678,4772,5679,3267, # 4880 +1243,5680,4142, 963,2250,4773,5681,2714,3658,3186,5682,5683,2596,2332,5684,4774, # 4896 +5685,5686,5687,3536, 957,3426,2547,2033,1931,2941,2467, 870,2019,3659,1746,2780, # 4912 +2781,2439,2468,5688,3930,5689,3789,3130,3790,3537,3427,3791,5690,1179,3086,5691, # 4928 +3187,2378,4416,3792,2548,3188,3131,2749,4143,5692,3428,1556,2549,2297, 977,2901, # 4944 +2034,4144,1205,3429,5693,1765,3430,3189,2125,1271, 714,1689,4775,3538,5694,2333, # 4960 +3931, 533,4417,3660,2184, 617,5695,2469,3340,3539,2315,5696,5697,3190,5698,5699, # 4976 +3932,1988, 618, 427,2651,3540,3431,5700,5701,1244,1690,5702,2819,4418,4776,5703, # 4992 +3541,4777,5704,2284,1576, 473,3661,4419,3432, 972,5705,3662,5706,3087,5707,5708, # 5008 +4778,4779,5709,3793,4145,4146,5710, 153,4780, 356,5711,1892,2902,4420,2144, 408, # 5024 + 803,2357,5712,3933,5713,4421,1646,2578,2518,4781,4782,3934,5714,3935,4422,5715, # 5040 +2416,3433, 752,5716,5717,1962,3341,2979,5718, 746,3030,2470,4783,4423,3794, 698, # 5056 +4784,1893,4424,3663,2550,4785,3664,3936,5719,3191,3434,5720,1824,1302,4147,2715, # 5072 +3937,1974,4425,5721,4426,3192, 823,1303,1288,1236,2861,3542,4148,3435, 774,3938, # 5088 +5722,1581,4786,1304,2862,3939,4787,5723,2440,2162,1083,3268,4427,4149,4428, 344, # 5104 +1173, 288,2316, 454,1683,5724,5725,1461,4788,4150,2597,5726,5727,4789, 985, 894, # 5120 +5728,3436,3193,5729,1914,2942,3795,1989,5730,2111,1975,5731,4151,5732,2579,1194, # 5136 + 425,5733,4790,3194,1245,3796,4429,5734,5735,2863,5736, 636,4791,1856,3940, 760, # 5152 +1800,5737,4430,2212,1508,4792,4152,1894,1684,2298,5738,5739,4793,4431,4432,2213, # 5168 + 479,5740,5741, 832,5742,4153,2496,5743,2980,2497,3797, 990,3132, 627,1815,2652, # 5184 +4433,1582,4434,2126,2112,3543,4794,5744, 799,4435,3195,5745,4795,2113,1737,3031, # 5200 +1018, 543, 754,4436,3342,1676,4796,4797,4154,4798,1489,5746,3544,5747,2624,2903, # 5216 +4155,5748,5749,2981,5750,5751,5752,5753,3196,4799,4800,2185,1722,5754,3269,3270, # 5232 +1843,3665,1715, 481, 365,1976,1857,5755,5756,1963,2498,4801,5757,2127,3666,3271, # 5248 + 433,1895,2064,2076,5758, 602,2750,5759,5760,5761,5762,5763,3032,1628,3437,5764, # 5264 +3197,4802,4156,2904,4803,2519,5765,2551,2782,5766,5767,5768,3343,4804,2905,5769, # 5280 +4805,5770,2864,4806,4807,1221,2982,4157,2520,5771,5772,5773,1868,1990,5774,5775, # 5296 +5776,1896,5777,5778,4808,1897,4158, 318,5779,2095,4159,4437,5780,5781, 485,5782, # 5312 + 938,3941, 553,2680, 116,5783,3942,3667,5784,3545,2681,2783,3438,3344,2820,5785, # 5328 +3668,2943,4160,1747,2944,2983,5786,5787, 207,5788,4809,5789,4810,2521,5790,3033, # 5344 + 890,3669,3943,5791,1878,3798,3439,5792,2186,2358,3440,1652,5793,5794,5795, 941, # 5360 +2299, 208,3546,4161,2020, 330,4438,3944,2906,2499,3799,4439,4811,5796,5797,5798, # 5376 #last 512 +#Everything below is of no interest for detection purpose +2522,1613,4812,5799,3345,3945,2523,5800,4162,5801,1637,4163,2471,4813,3946,5802, # 5392 +2500,3034,3800,5803,5804,2195,4814,5805,2163,5806,5807,5808,5809,5810,5811,5812, # 5408 +5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828, # 5424 +5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844, # 5440 +5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,5860, # 5456 +5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,5874,5875,5876, # 5472 +5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,5889,5890,5891,5892, # 5488 +5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,5905,5906,5907,5908, # 5504 +5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920,5921,5922,5923,5924, # 5520 +5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936,5937,5938,5939,5940, # 5536 +5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952,5953,5954,5955,5956, # 5552 +5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968,5969,5970,5971,5972, # 5568 +5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,5984,5985,5986,5987,5988, # 5584 +5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,5999,6000,6001,6002,6003,6004, # 5600 +6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020, # 5616 +6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036, # 5632 +6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052, # 5648 +6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068, # 5664 +6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084, # 5680 +6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6100, # 5696 +6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,6115,6116, # 5712 +6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,6130,6131,6132, # 5728 +6133,6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,6144,6145,6146,6147,6148, # 5744 +6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,6160,6161,6162,6163,6164, # 5760 +6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,6175,6176,6177,6178,6179,6180, # 5776 +6181,6182,6183,6184,6185,6186,6187,6188,6189,6190,6191,6192,6193,6194,6195,6196, # 5792 +6197,6198,6199,6200,6201,6202,6203,6204,6205,6206,6207,6208,6209,6210,6211,6212, # 5808 +6213,6214,6215,6216,6217,6218,6219,6220,6221,6222,6223,3670,6224,6225,6226,6227, # 5824 +6228,6229,6230,6231,6232,6233,6234,6235,6236,6237,6238,6239,6240,6241,6242,6243, # 5840 +6244,6245,6246,6247,6248,6249,6250,6251,6252,6253,6254,6255,6256,6257,6258,6259, # 5856 +6260,6261,6262,6263,6264,6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275, # 5872 +6276,6277,6278,6279,6280,6281,6282,6283,6284,6285,4815,6286,6287,6288,6289,6290, # 5888 +6291,6292,4816,6293,6294,6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305, # 5904 +6306,6307,6308,6309,6310,6311,4817,4818,6312,6313,6314,6315,6316,6317,6318,4819, # 5920 +6319,6320,6321,6322,6323,6324,6325,6326,6327,6328,6329,6330,6331,6332,6333,6334, # 5936 +6335,6336,6337,4820,6338,6339,6340,6341,6342,6343,6344,6345,6346,6347,6348,6349, # 5952 +6350,6351,6352,6353,6354,6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365, # 5968 +6366,6367,6368,6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381, # 5984 +6382,6383,6384,6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397, # 6000 +6398,6399,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,3441,6411,6412, # 6016 +6413,6414,6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,4440,6426,6427, # 6032 +6428,6429,6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443, # 6048 +6444,6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,4821,6455,6456,6457,6458, # 6064 +6459,6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,6474, # 6080 +6475,6476,6477,3947,3948,6478,6479,6480,6481,3272,4441,6482,6483,6484,6485,4442, # 6096 +6486,6487,6488,6489,6490,6491,6492,6493,6494,6495,6496,4822,6497,6498,6499,6500, # 6112 +6501,6502,6503,6504,6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516, # 6128 +6517,6518,6519,6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532, # 6144 +6533,6534,6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548, # 6160 +6549,6550,6551,6552,6553,6554,6555,6556,2784,6557,4823,6558,6559,6560,6561,6562, # 6176 +6563,6564,6565,6566,6567,6568,6569,3949,6570,6571,6572,4824,6573,6574,6575,6576, # 6192 +6577,6578,6579,6580,6581,6582,6583,4825,6584,6585,6586,3950,2785,6587,6588,6589, # 6208 +6590,6591,6592,6593,6594,6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605, # 6224 +6606,6607,6608,6609,6610,6611,6612,4826,6613,6614,6615,4827,6616,6617,6618,6619, # 6240 +6620,6621,6622,6623,6624,6625,4164,6626,6627,6628,6629,6630,6631,6632,6633,6634, # 6256 +3547,6635,4828,6636,6637,6638,6639,6640,6641,6642,3951,2984,6643,6644,6645,6646, # 6272 +6647,6648,6649,4165,6650,4829,6651,6652,4830,6653,6654,6655,6656,6657,6658,6659, # 6288 +6660,6661,6662,4831,6663,6664,6665,6666,6667,6668,6669,6670,6671,4166,6672,4832, # 6304 +3952,6673,6674,6675,6676,4833,6677,6678,6679,4167,6680,6681,6682,3198,6683,6684, # 6320 +6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,4834,6698,6699, # 6336 +6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,6715, # 6352 +6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,6730,6731, # 6368 +6732,6733,6734,4443,6735,6736,6737,6738,6739,6740,6741,6742,6743,6744,6745,4444, # 6384 +6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,6759,6760,6761, # 6400 +6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777, # 6416 +6778,6779,6780,6781,4168,6782,6783,3442,6784,6785,6786,6787,6788,6789,6790,6791, # 6432 +4169,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,6805,6806, # 6448 +6807,6808,6809,6810,6811,4835,6812,6813,6814,4445,6815,6816,4446,6817,6818,6819, # 6464 +6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,6834,6835, # 6480 +3548,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,4836,6847,6848,6849, # 6496 +6850,6851,6852,6853,6854,3953,6855,6856,6857,6858,6859,6860,6861,6862,6863,6864, # 6512 +6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,3199,6878,6879, # 6528 +6880,6881,6882,4447,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,6894, # 6544 +6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,4170,6905,6906,6907,6908,6909, # 6560 +6910,6911,6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,6924,6925, # 6576 +6926,6927,4837,6928,6929,6930,6931,6932,6933,6934,6935,6936,3346,6937,6938,4838, # 6592 +6939,6940,6941,4448,6942,6943,6944,6945,6946,4449,6947,6948,6949,6950,6951,6952, # 6608 +6953,6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968, # 6624 +6969,6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,6984, # 6640 +6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,3671,6995,6996,6997,6998,4839, # 6656 +6999,7000,7001,7002,3549,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013, # 6672 +7014,7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,7029, # 6688 +7030,4840,7031,7032,7033,7034,7035,7036,7037,7038,4841,7039,7040,7041,7042,7043, # 6704 +7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059, # 6720 +7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,2985,7071,7072,7073,7074, # 6736 +7075,7076,7077,7078,7079,7080,4842,7081,7082,7083,7084,7085,7086,7087,7088,7089, # 6752 +7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,7104,7105, # 6768 +7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,4450,7119,7120, # 6784 +7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,7135,7136, # 6800 +7137,7138,7139,7140,7141,7142,7143,4843,7144,7145,7146,7147,7148,7149,7150,7151, # 6816 +7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,7165,7166,7167, # 6832 +7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,7180,7181,7182,7183, # 6848 +7184,7185,7186,7187,7188,4171,4172,7189,7190,7191,7192,7193,7194,7195,7196,7197, # 6864 +7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,7209,7210,7211,7212,7213, # 6880 +7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7224,7225,7226,7227,7228,7229, # 6896 +7230,7231,7232,7233,7234,7235,7236,7237,7238,7239,7240,7241,7242,7243,7244,7245, # 6912 +7246,7247,7248,7249,7250,7251,7252,7253,7254,7255,7256,7257,7258,7259,7260,7261, # 6928 +7262,7263,7264,7265,7266,7267,7268,7269,7270,7271,7272,7273,7274,7275,7276,7277, # 6944 +7278,7279,7280,7281,7282,7283,7284,7285,7286,7287,7288,7289,7290,7291,7292,7293, # 6960 +7294,7295,7296,4844,7297,7298,7299,7300,7301,7302,7303,7304,7305,7306,7307,7308, # 6976 +7309,7310,7311,7312,7313,7314,7315,7316,4451,7317,7318,7319,7320,7321,7322,7323, # 6992 +7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339, # 7008 +7340,7341,7342,7343,7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,4173,7354, # 7024 +7355,4845,7356,7357,7358,7359,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369, # 7040 +7370,7371,7372,7373,7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385, # 7056 +7386,7387,7388,4846,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400, # 7072 +7401,7402,7403,7404,7405,3672,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415, # 7088 +7416,7417,7418,7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431, # 7104 +7432,7433,7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447, # 7120 +7448,7449,7450,7451,7452,7453,4452,7454,3200,7455,7456,7457,7458,7459,7460,7461, # 7136 +7462,7463,7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,4847,7475,7476, # 7152 +7477,3133,7478,7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491, # 7168 +7492,7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,3347,7503,7504,7505,7506, # 7184 +7507,7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,4848, # 7200 +7522,7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537, # 7216 +7538,7539,7540,7541,7542,7543,7544,7545,7546,7547,7548,7549,3801,4849,7550,7551, # 7232 +7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567, # 7248 +7568,7569,3035,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582, # 7264 +7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,7598, # 7280 +7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,7613,7614, # 7296 +7615,7616,4850,7617,7618,3802,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628, # 7312 +7629,7630,7631,7632,4851,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643, # 7328 +7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659, # 7344 +7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,7670,4453,7671,7672,7673,7674, # 7360 +7675,7676,7677,7678,7679,7680,7681,7682,7683,7684,7685,7686,7687,7688,7689,7690, # 7376 +7691,7692,7693,7694,7695,7696,7697,3443,7698,7699,7700,7701,7702,4454,7703,7704, # 7392 +7705,7706,7707,7708,7709,7710,7711,7712,7713,2472,7714,7715,7716,7717,7718,7719, # 7408 +7720,7721,7722,7723,7724,7725,7726,7727,7728,7729,7730,7731,3954,7732,7733,7734, # 7424 +7735,7736,7737,7738,7739,7740,7741,7742,7743,7744,7745,7746,7747,7748,7749,7750, # 7440 +3134,7751,7752,4852,7753,7754,7755,4853,7756,7757,7758,7759,7760,4174,7761,7762, # 7456 +7763,7764,7765,7766,7767,7768,7769,7770,7771,7772,7773,7774,7775,7776,7777,7778, # 7472 +7779,7780,7781,7782,7783,7784,7785,7786,7787,7788,7789,7790,7791,7792,7793,7794, # 7488 +7795,7796,7797,7798,7799,7800,7801,7802,7803,7804,7805,4854,7806,7807,7808,7809, # 7504 +7810,7811,7812,7813,7814,7815,7816,7817,7818,7819,7820,7821,7822,7823,7824,7825, # 7520 +4855,7826,7827,7828,7829,7830,7831,7832,7833,7834,7835,7836,7837,7838,7839,7840, # 7536 +7841,7842,7843,7844,7845,7846,7847,3955,7848,7849,7850,7851,7852,7853,7854,7855, # 7552 +7856,7857,7858,7859,7860,3444,7861,7862,7863,7864,7865,7866,7867,7868,7869,7870, # 7568 +7871,7872,7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886, # 7584 +7887,7888,7889,7890,7891,4175,7892,7893,7894,7895,7896,4856,4857,7897,7898,7899, # 7600 +7900,2598,7901,7902,7903,7904,7905,7906,7907,7908,4455,7909,7910,7911,7912,7913, # 7616 +7914,3201,7915,7916,7917,7918,7919,7920,7921,4858,7922,7923,7924,7925,7926,7927, # 7632 +7928,7929,7930,7931,7932,7933,7934,7935,7936,7937,7938,7939,7940,7941,7942,7943, # 7648 +7944,7945,7946,7947,7948,7949,7950,7951,7952,7953,7954,7955,7956,7957,7958,7959, # 7664 +7960,7961,7962,7963,7964,7965,7966,7967,7968,7969,7970,7971,7972,7973,7974,7975, # 7680 +7976,7977,7978,7979,7980,7981,4859,7982,7983,7984,7985,7986,7987,7988,7989,7990, # 7696 +7991,7992,7993,7994,7995,7996,4860,7997,7998,7999,8000,8001,8002,8003,8004,8005, # 7712 +8006,8007,8008,8009,8010,8011,8012,8013,8014,8015,8016,4176,8017,8018,8019,8020, # 7728 +8021,8022,8023,4861,8024,8025,8026,8027,8028,8029,8030,8031,8032,8033,8034,8035, # 7744 +8036,4862,4456,8037,8038,8039,8040,4863,8041,8042,8043,8044,8045,8046,8047,8048, # 7760 +8049,8050,8051,8052,8053,8054,8055,8056,8057,8058,8059,8060,8061,8062,8063,8064, # 7776 +8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079,8080, # 7792 +8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095,8096, # 7808 +8097,8098,8099,4864,4177,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110, # 7824 +8111,8112,8113,8114,8115,8116,8117,8118,8119,8120,4178,8121,8122,8123,8124,8125, # 7840 +8126,8127,8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,8138,8139,8140,8141, # 7856 +8142,8143,8144,8145,4865,4866,8146,8147,8148,8149,8150,8151,8152,8153,8154,8155, # 7872 +8156,8157,8158,8159,8160,8161,8162,8163,8164,8165,4179,8166,8167,8168,8169,8170, # 7888 +8171,8172,8173,8174,8175,8176,8177,8178,8179,8180,8181,4457,8182,8183,8184,8185, # 7904 +8186,8187,8188,8189,8190,8191,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201, # 7920 +8202,8203,8204,8205,8206,8207,8208,8209,8210,8211,8212,8213,8214,8215,8216,8217, # 7936 +8218,8219,8220,8221,8222,8223,8224,8225,8226,8227,8228,8229,8230,8231,8232,8233, # 7952 +8234,8235,8236,8237,8238,8239,8240,8241,8242,8243,8244,8245,8246,8247,8248,8249, # 7968 +8250,8251,8252,8253,8254,8255,8256,3445,8257,8258,8259,8260,8261,8262,4458,8263, # 7984 +8264,8265,8266,8267,8268,8269,8270,8271,8272,4459,8273,8274,8275,8276,3550,8277, # 8000 +8278,8279,8280,8281,8282,8283,8284,8285,8286,8287,8288,8289,4460,8290,8291,8292, # 8016 +8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,8303,8304,8305,8306,8307,4867, # 8032 +8308,8309,8310,8311,8312,3551,8313,8314,8315,8316,8317,8318,8319,8320,8321,8322, # 8048 +8323,8324,8325,8326,4868,8327,8328,8329,8330,8331,8332,8333,8334,8335,8336,8337, # 8064 +8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,8348,8349,8350,8351,8352,8353, # 8080 +8354,8355,8356,8357,8358,8359,8360,8361,8362,8363,4869,4461,8364,8365,8366,8367, # 8096 +8368,8369,8370,4870,8371,8372,8373,8374,8375,8376,8377,8378,8379,8380,8381,8382, # 8112 +8383,8384,8385,8386,8387,8388,8389,8390,8391,8392,8393,8394,8395,8396,8397,8398, # 8128 +8399,8400,8401,8402,8403,8404,8405,8406,8407,8408,8409,8410,4871,8411,8412,8413, # 8144 +8414,8415,8416,8417,8418,8419,8420,8421,8422,4462,8423,8424,8425,8426,8427,8428, # 8160 +8429,8430,8431,8432,8433,2986,8434,8435,8436,8437,8438,8439,8440,8441,8442,8443, # 8176 +8444,8445,8446,8447,8448,8449,8450,8451,8452,8453,8454,8455,8456,8457,8458,8459, # 8192 +8460,8461,8462,8463,8464,8465,8466,8467,8468,8469,8470,8471,8472,8473,8474,8475, # 8208 +8476,8477,8478,4180,8479,8480,8481,8482,8483,8484,8485,8486,8487,8488,8489,8490, # 8224 +8491,8492,8493,8494,8495,8496,8497,8498,8499,8500,8501,8502,8503,8504,8505,8506, # 8240 +8507,8508,8509,8510,8511,8512,8513,8514,8515,8516,8517,8518,8519,8520,8521,8522, # 8256 +8523,8524,8525,8526,8527,8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538, # 8272 +8539,8540,8541,8542,8543,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554, # 8288 +8555,8556,8557,8558,8559,8560,8561,8562,8563,8564,4872,8565,8566,8567,8568,8569, # 8304 +8570,8571,8572,8573,4873,8574,8575,8576,8577,8578,8579,8580,8581,8582,8583,8584, # 8320 +8585,8586,8587,8588,8589,8590,8591,8592,8593,8594,8595,8596,8597,8598,8599,8600, # 8336 +8601,8602,8603,8604,8605,3803,8606,8607,8608,8609,8610,8611,8612,8613,4874,3804, # 8352 +8614,8615,8616,8617,8618,8619,8620,8621,3956,8622,8623,8624,8625,8626,8627,8628, # 8368 +8629,8630,8631,8632,8633,8634,8635,8636,8637,8638,2865,8639,8640,8641,8642,8643, # 8384 +8644,8645,8646,8647,8648,8649,8650,8651,8652,8653,8654,8655,8656,4463,8657,8658, # 8400 +8659,4875,4876,8660,8661,8662,8663,8664,8665,8666,8667,8668,8669,8670,8671,8672, # 8416 +8673,8674,8675,8676,8677,8678,8679,8680,8681,4464,8682,8683,8684,8685,8686,8687, # 8432 +8688,8689,8690,8691,8692,8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703, # 8448 +8704,8705,8706,8707,8708,8709,2261,8710,8711,8712,8713,8714,8715,8716,8717,8718, # 8464 +8719,8720,8721,8722,8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,4181, # 8480 +8734,8735,8736,8737,8738,8739,8740,8741,8742,8743,8744,8745,8746,8747,8748,8749, # 8496 +8750,8751,8752,8753,8754,8755,8756,8757,8758,8759,8760,8761,8762,8763,4877,8764, # 8512 +8765,8766,8767,8768,8769,8770,8771,8772,8773,8774,8775,8776,8777,8778,8779,8780, # 8528 +8781,8782,8783,8784,8785,8786,8787,8788,4878,8789,4879,8790,8791,8792,4880,8793, # 8544 +8794,8795,8796,8797,8798,8799,8800,8801,4881,8802,8803,8804,8805,8806,8807,8808, # 8560 +8809,8810,8811,8812,8813,8814,8815,3957,8816,8817,8818,8819,8820,8821,8822,8823, # 8576 +8824,8825,8826,8827,8828,8829,8830,8831,8832,8833,8834,8835,8836,8837,8838,8839, # 8592 +8840,8841,8842,8843,8844,8845,8846,8847,4882,8848,8849,8850,8851,8852,8853,8854, # 8608 +8855,8856,8857,8858,8859,8860,8861,8862,8863,8864,8865,8866,8867,8868,8869,8870, # 8624 +8871,8872,8873,8874,8875,8876,8877,8878,8879,8880,8881,8882,8883,8884,3202,8885, # 8640 +8886,8887,8888,8889,8890,8891,8892,8893,8894,8895,8896,8897,8898,8899,8900,8901, # 8656 +8902,8903,8904,8905,8906,8907,8908,8909,8910,8911,8912,8913,8914,8915,8916,8917, # 8672 +8918,8919,8920,8921,8922,8923,8924,4465,8925,8926,8927,8928,8929,8930,8931,8932, # 8688 +4883,8933,8934,8935,8936,8937,8938,8939,8940,8941,8942,8943,2214,8944,8945,8946, # 8704 +8947,8948,8949,8950,8951,8952,8953,8954,8955,8956,8957,8958,8959,8960,8961,8962, # 8720 +8963,8964,8965,4884,8966,8967,8968,8969,8970,8971,8972,8973,8974,8975,8976,8977, # 8736 +8978,8979,8980,8981,8982,8983,8984,8985,8986,8987,8988,8989,8990,8991,8992,4885, # 8752 +8993,8994,8995,8996,8997,8998,8999,9000,9001,9002,9003,9004,9005,9006,9007,9008, # 8768 +9009,9010,9011,9012,9013,9014,9015,9016,9017,9018,9019,9020,9021,4182,9022,9023, # 8784 +9024,9025,9026,9027,9028,9029,9030,9031,9032,9033,9034,9035,9036,9037,9038,9039, # 8800 +9040,9041,9042,9043,9044,9045,9046,9047,9048,9049,9050,9051,9052,9053,9054,9055, # 8816 +9056,9057,9058,9059,9060,9061,9062,9063,4886,9064,9065,9066,9067,9068,9069,4887, # 8832 +9070,9071,9072,9073,9074,9075,9076,9077,9078,9079,9080,9081,9082,9083,9084,9085, # 8848 +9086,9087,9088,9089,9090,9091,9092,9093,9094,9095,9096,9097,9098,9099,9100,9101, # 8864 +9102,9103,9104,9105,9106,9107,9108,9109,9110,9111,9112,9113,9114,9115,9116,9117, # 8880 +9118,9119,9120,9121,9122,9123,9124,9125,9126,9127,9128,9129,9130,9131,9132,9133, # 8896 +9134,9135,9136,9137,9138,9139,9140,9141,3958,9142,9143,9144,9145,9146,9147,9148, # 8912 +9149,9150,9151,4888,9152,9153,9154,9155,9156,9157,9158,9159,9160,9161,9162,9163, # 8928 +9164,9165,9166,9167,9168,9169,9170,9171,9172,9173,9174,9175,4889,9176,9177,9178, # 8944 +9179,9180,9181,9182,9183,9184,9185,9186,9187,9188,9189,9190,9191,9192,9193,9194, # 8960 +9195,9196,9197,9198,9199,9200,9201,9202,9203,4890,9204,9205,9206,9207,9208,9209, # 8976 +9210,9211,9212,9213,9214,9215,9216,9217,9218,9219,9220,9221,9222,4466,9223,9224, # 8992 +9225,9226,9227,9228,9229,9230,9231,9232,9233,9234,9235,9236,9237,9238,9239,9240, # 9008 +9241,9242,9243,9244,9245,4891,9246,9247,9248,9249,9250,9251,9252,9253,9254,9255, # 9024 +9256,9257,4892,9258,9259,9260,9261,4893,4894,9262,9263,9264,9265,9266,9267,9268, # 9040 +9269,9270,9271,9272,9273,4467,9274,9275,9276,9277,9278,9279,9280,9281,9282,9283, # 9056 +9284,9285,3673,9286,9287,9288,9289,9290,9291,9292,9293,9294,9295,9296,9297,9298, # 9072 +9299,9300,9301,9302,9303,9304,9305,9306,9307,9308,9309,9310,9311,9312,9313,9314, # 9088 +9315,9316,9317,9318,9319,9320,9321,9322,4895,9323,9324,9325,9326,9327,9328,9329, # 9104 +9330,9331,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345, # 9120 +9346,9347,4468,9348,9349,9350,9351,9352,9353,9354,9355,9356,9357,9358,9359,9360, # 9136 +9361,9362,9363,9364,9365,9366,9367,9368,9369,9370,9371,9372,9373,4896,9374,4469, # 9152 +9375,9376,9377,9378,9379,4897,9380,9381,9382,9383,9384,9385,9386,9387,9388,9389, # 9168 +9390,9391,9392,9393,9394,9395,9396,9397,9398,9399,9400,9401,9402,9403,9404,9405, # 9184 +9406,4470,9407,2751,9408,9409,3674,3552,9410,9411,9412,9413,9414,9415,9416,9417, # 9200 +9418,9419,9420,9421,4898,9422,9423,9424,9425,9426,9427,9428,9429,3959,9430,9431, # 9216 +9432,9433,9434,9435,9436,4471,9437,9438,9439,9440,9441,9442,9443,9444,9445,9446, # 9232 +9447,9448,9449,9450,3348,9451,9452,9453,9454,9455,9456,9457,9458,9459,9460,9461, # 9248 +9462,9463,9464,9465,9466,9467,9468,9469,9470,9471,9472,4899,9473,9474,9475,9476, # 9264 +9477,4900,9478,9479,9480,9481,9482,9483,9484,9485,9486,9487,9488,3349,9489,9490, # 9280 +9491,9492,9493,9494,9495,9496,9497,9498,9499,9500,9501,9502,9503,9504,9505,9506, # 9296 +9507,9508,9509,9510,9511,9512,9513,9514,9515,9516,9517,9518,9519,9520,4901,9521, # 9312 +9522,9523,9524,9525,9526,4902,9527,9528,9529,9530,9531,9532,9533,9534,9535,9536, # 9328 +9537,9538,9539,9540,9541,9542,9543,9544,9545,9546,9547,9548,9549,9550,9551,9552, # 9344 +9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568, # 9360 +9569,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,9581,9582,9583,9584, # 9376 +3805,9585,9586,9587,9588,9589,9590,9591,9592,9593,9594,9595,9596,9597,9598,9599, # 9392 +9600,9601,9602,4903,9603,9604,9605,9606,9607,4904,9608,9609,9610,9611,9612,9613, # 9408 +9614,4905,9615,9616,9617,9618,9619,9620,9621,9622,9623,9624,9625,9626,9627,9628, # 9424 +9629,9630,9631,9632,4906,9633,9634,9635,9636,9637,9638,9639,9640,9641,9642,9643, # 9440 +4907,9644,9645,9646,9647,9648,9649,9650,9651,9652,9653,9654,9655,9656,9657,9658, # 9456 +9659,9660,9661,9662,9663,9664,9665,9666,9667,9668,9669,9670,9671,9672,4183,9673, # 9472 +9674,9675,9676,9677,4908,9678,9679,9680,9681,4909,9682,9683,9684,9685,9686,9687, # 9488 +9688,9689,9690,4910,9691,9692,9693,3675,9694,9695,9696,2945,9697,9698,9699,9700, # 9504 +9701,9702,9703,9704,9705,4911,9706,9707,9708,9709,9710,9711,9712,9713,9714,9715, # 9520 +9716,9717,9718,9719,9720,9721,9722,9723,9724,9725,9726,9727,9728,9729,9730,9731, # 9536 +9732,9733,9734,9735,4912,9736,9737,9738,9739,9740,4913,9741,9742,9743,9744,9745, # 9552 +9746,9747,9748,9749,9750,9751,9752,9753,9754,9755,9756,9757,9758,4914,9759,9760, # 9568 +9761,9762,9763,9764,9765,9766,9767,9768,9769,9770,9771,9772,9773,9774,9775,9776, # 9584 +9777,9778,9779,9780,9781,9782,4915,9783,9784,9785,9786,9787,9788,9789,9790,9791, # 9600 +9792,9793,4916,9794,9795,9796,9797,9798,9799,9800,9801,9802,9803,9804,9805,9806, # 9616 +9807,9808,9809,9810,9811,9812,9813,9814,9815,9816,9817,9818,9819,9820,9821,9822, # 9632 +9823,9824,9825,9826,9827,9828,9829,9830,9831,9832,9833,9834,9835,9836,9837,9838, # 9648 +9839,9840,9841,9842,9843,9844,9845,9846,9847,9848,9849,9850,9851,9852,9853,9854, # 9664 +9855,9856,9857,9858,9859,9860,9861,9862,9863,9864,9865,9866,9867,9868,4917,9869, # 9680 +9870,9871,9872,9873,9874,9875,9876,9877,9878,9879,9880,9881,9882,9883,9884,9885, # 9696 +9886,9887,9888,9889,9890,9891,9892,4472,9893,9894,9895,9896,9897,3806,9898,9899, # 9712 +9900,9901,9902,9903,9904,9905,9906,9907,9908,9909,9910,9911,9912,9913,9914,4918, # 9728 +9915,9916,9917,4919,9918,9919,9920,9921,4184,9922,9923,9924,9925,9926,9927,9928, # 9744 +9929,9930,9931,9932,9933,9934,9935,9936,9937,9938,9939,9940,9941,9942,9943,9944, # 9760 +9945,9946,4920,9947,9948,9949,9950,9951,9952,9953,9954,9955,4185,9956,9957,9958, # 9776 +9959,9960,9961,9962,9963,9964,9965,4921,9966,9967,9968,4473,9969,9970,9971,9972, # 9792 +9973,9974,9975,9976,9977,4474,9978,9979,9980,9981,9982,9983,9984,9985,9986,9987, # 9808 +9988,9989,9990,9991,9992,9993,9994,9995,9996,9997,9998,9999,10000,10001,10002,10003, # 9824 +10004,10005,10006,10007,10008,10009,10010,10011,10012,10013,10014,10015,10016,10017,10018,10019, # 9840 +10020,10021,4922,10022,4923,10023,10024,10025,10026,10027,10028,10029,10030,10031,10032,10033, # 9856 +10034,10035,10036,10037,10038,10039,10040,10041,10042,10043,10044,10045,10046,10047,10048,4924, # 9872 +10049,10050,10051,10052,10053,10054,10055,10056,10057,10058,10059,10060,10061,10062,10063,10064, # 9888 +10065,10066,10067,10068,10069,10070,10071,10072,10073,10074,10075,10076,10077,10078,10079,10080, # 9904 +10081,10082,10083,10084,10085,10086,10087,4475,10088,10089,10090,10091,10092,10093,10094,10095, # 9920 +10096,10097,4476,10098,10099,10100,10101,10102,10103,10104,10105,10106,10107,10108,10109,10110, # 9936 +10111,2174,10112,10113,10114,10115,10116,10117,10118,10119,10120,10121,10122,10123,10124,10125, # 9952 +10126,10127,10128,10129,10130,10131,10132,10133,10134,10135,10136,10137,10138,10139,10140,3807, # 9968 +4186,4925,10141,10142,10143,10144,10145,10146,10147,4477,4187,10148,10149,10150,10151,10152, # 9984 +10153,4188,10154,10155,10156,10157,10158,10159,10160,10161,4926,10162,10163,10164,10165,10166, #10000 +10167,10168,10169,10170,10171,10172,10173,10174,10175,10176,10177,10178,10179,10180,10181,10182, #10016 +10183,10184,10185,10186,10187,10188,10189,10190,10191,10192,3203,10193,10194,10195,10196,10197, #10032 +10198,10199,10200,4478,10201,10202,10203,10204,4479,10205,10206,10207,10208,10209,10210,10211, #10048 +10212,10213,10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,10224,10225,10226,10227, #10064 +10228,10229,10230,10231,10232,10233,10234,4927,10235,10236,10237,10238,10239,10240,10241,10242, #10080 +10243,10244,10245,10246,10247,10248,10249,10250,10251,10252,10253,10254,10255,10256,10257,10258, #10096 +10259,10260,10261,10262,10263,10264,10265,10266,10267,10268,10269,10270,10271,10272,10273,4480, #10112 +4928,4929,10274,10275,10276,10277,10278,10279,10280,10281,10282,10283,10284,10285,10286,10287, #10128 +10288,10289,10290,10291,10292,10293,10294,10295,10296,10297,10298,10299,10300,10301,10302,10303, #10144 +10304,10305,10306,10307,10308,10309,10310,10311,10312,10313,10314,10315,10316,10317,10318,10319, #10160 +10320,10321,10322,10323,10324,10325,10326,10327,10328,10329,10330,10331,10332,10333,10334,4930, #10176 +10335,10336,10337,10338,10339,10340,10341,10342,4931,10343,10344,10345,10346,10347,10348,10349, #10192 +10350,10351,10352,10353,10354,10355,3088,10356,2786,10357,10358,10359,10360,4189,10361,10362, #10208 +10363,10364,10365,10366,10367,10368,10369,10370,10371,10372,10373,10374,10375,4932,10376,10377, #10224 +10378,10379,10380,10381,10382,10383,10384,10385,10386,10387,10388,10389,10390,10391,10392,4933, #10240 +10393,10394,10395,4934,10396,10397,10398,10399,10400,10401,10402,10403,10404,10405,10406,10407, #10256 +10408,10409,10410,10411,10412,3446,10413,10414,10415,10416,10417,10418,10419,10420,10421,10422, #10272 +10423,4935,10424,10425,10426,10427,10428,10429,10430,4936,10431,10432,10433,10434,10435,10436, #10288 +10437,10438,10439,10440,10441,10442,10443,4937,10444,10445,10446,10447,4481,10448,10449,10450, #10304 +10451,10452,10453,10454,10455,10456,10457,10458,10459,10460,10461,10462,10463,10464,10465,10466, #10320 +10467,10468,10469,10470,10471,10472,10473,10474,10475,10476,10477,10478,10479,10480,10481,10482, #10336 +10483,10484,10485,10486,10487,10488,10489,10490,10491,10492,10493,10494,10495,10496,10497,10498, #10352 +10499,10500,10501,10502,10503,10504,10505,4938,10506,10507,10508,10509,10510,2552,10511,10512, #10368 +10513,10514,10515,10516,3447,10517,10518,10519,10520,10521,10522,10523,10524,10525,10526,10527, #10384 +10528,10529,10530,10531,10532,10533,10534,10535,10536,10537,10538,10539,10540,10541,10542,10543, #10400 +4482,10544,4939,10545,10546,10547,10548,10549,10550,10551,10552,10553,10554,10555,10556,10557, #10416 +10558,10559,10560,10561,10562,10563,10564,10565,10566,10567,3676,4483,10568,10569,10570,10571, #10432 +10572,3448,10573,10574,10575,10576,10577,10578,10579,10580,10581,10582,10583,10584,10585,10586, #10448 +10587,10588,10589,10590,10591,10592,10593,10594,10595,10596,10597,10598,10599,10600,10601,10602, #10464 +10603,10604,10605,10606,10607,10608,10609,10610,10611,10612,10613,10614,10615,10616,10617,10618, #10480 +10619,10620,10621,10622,10623,10624,10625,10626,10627,4484,10628,10629,10630,10631,10632,4940, #10496 +10633,10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,10644,10645,10646,10647,10648, #10512 +10649,10650,10651,10652,10653,10654,10655,10656,4941,10657,10658,10659,2599,10660,10661,10662, #10528 +10663,10664,10665,10666,3089,10667,10668,10669,10670,10671,10672,10673,10674,10675,10676,10677, #10544 +10678,10679,10680,4942,10681,10682,10683,10684,10685,10686,10687,10688,10689,10690,10691,10692, #10560 +10693,10694,10695,10696,10697,4485,10698,10699,10700,10701,10702,10703,10704,4943,10705,3677, #10576 +10706,10707,10708,10709,10710,10711,10712,4944,10713,10714,10715,10716,10717,10718,10719,10720, #10592 +10721,10722,10723,10724,10725,10726,10727,10728,4945,10729,10730,10731,10732,10733,10734,10735, #10608 +10736,10737,10738,10739,10740,10741,10742,10743,10744,10745,10746,10747,10748,10749,10750,10751, #10624 +10752,10753,10754,10755,10756,10757,10758,10759,10760,10761,4946,10762,10763,10764,10765,10766, #10640 +10767,4947,4948,10768,10769,10770,10771,10772,10773,10774,10775,10776,10777,10778,10779,10780, #10656 +10781,10782,10783,10784,10785,10786,10787,10788,10789,10790,10791,10792,10793,10794,10795,10796, #10672 +10797,10798,10799,10800,10801,10802,10803,10804,10805,10806,10807,10808,10809,10810,10811,10812, #10688 +10813,10814,10815,10816,10817,10818,10819,10820,10821,10822,10823,10824,10825,10826,10827,10828, #10704 +10829,10830,10831,10832,10833,10834,10835,10836,10837,10838,10839,10840,10841,10842,10843,10844, #10720 +10845,10846,10847,10848,10849,10850,10851,10852,10853,10854,10855,10856,10857,10858,10859,10860, #10736 +10861,10862,10863,10864,10865,10866,10867,10868,10869,10870,10871,10872,10873,10874,10875,10876, #10752 +10877,10878,4486,10879,10880,10881,10882,10883,10884,10885,4949,10886,10887,10888,10889,10890, #10768 +10891,10892,10893,10894,10895,10896,10897,10898,10899,10900,10901,10902,10903,10904,10905,10906, #10784 +10907,10908,10909,10910,10911,10912,10913,10914,10915,10916,10917,10918,10919,4487,10920,10921, #10800 +10922,10923,10924,10925,10926,10927,10928,10929,10930,10931,10932,4950,10933,10934,10935,10936, #10816 +10937,10938,10939,10940,10941,10942,10943,10944,10945,10946,10947,10948,10949,4488,10950,10951, #10832 +10952,10953,10954,10955,10956,10957,10958,10959,4190,10960,10961,10962,10963,10964,10965,10966, #10848 +10967,10968,10969,10970,10971,10972,10973,10974,10975,10976,10977,10978,10979,10980,10981,10982, #10864 +10983,10984,10985,10986,10987,10988,10989,10990,10991,10992,10993,10994,10995,10996,10997,10998, #10880 +10999,11000,11001,11002,11003,11004,11005,11006,3960,11007,11008,11009,11010,11011,11012,11013, #10896 +11014,11015,11016,11017,11018,11019,11020,11021,11022,11023,11024,11025,11026,11027,11028,11029, #10912 +11030,11031,11032,4951,11033,11034,11035,11036,11037,11038,11039,11040,11041,11042,11043,11044, #10928 +11045,11046,11047,4489,11048,11049,11050,11051,4952,11052,11053,11054,11055,11056,11057,11058, #10944 +4953,11059,11060,11061,11062,11063,11064,11065,11066,11067,11068,11069,11070,11071,4954,11072, #10960 +11073,11074,11075,11076,11077,11078,11079,11080,11081,11082,11083,11084,11085,11086,11087,11088, #10976 +11089,11090,11091,11092,11093,11094,11095,11096,11097,11098,11099,11100,11101,11102,11103,11104, #10992 +11105,11106,11107,11108,11109,11110,11111,11112,11113,11114,11115,3808,11116,11117,11118,11119, #11008 +11120,11121,11122,11123,11124,11125,11126,11127,11128,11129,11130,11131,11132,11133,11134,4955, #11024 +11135,11136,11137,11138,11139,11140,11141,11142,11143,11144,11145,11146,11147,11148,11149,11150, #11040 +11151,11152,11153,11154,11155,11156,11157,11158,11159,11160,11161,4956,11162,11163,11164,11165, #11056 +11166,11167,11168,11169,11170,11171,11172,11173,11174,11175,11176,11177,11178,11179,11180,4957, #11072 +11181,11182,11183,11184,11185,11186,4958,11187,11188,11189,11190,11191,11192,11193,11194,11195, #11088 +11196,11197,11198,11199,11200,3678,11201,11202,11203,11204,11205,11206,4191,11207,11208,11209, #11104 +11210,11211,11212,11213,11214,11215,11216,11217,11218,11219,11220,11221,11222,11223,11224,11225, #11120 +11226,11227,11228,11229,11230,11231,11232,11233,11234,11235,11236,11237,11238,11239,11240,11241, #11136 +11242,11243,11244,11245,11246,11247,11248,11249,11250,11251,4959,11252,11253,11254,11255,11256, #11152 +11257,11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,11268,11269,11270,11271,11272, #11168 +11273,11274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,11286,11287,11288, #11184 +11289,11290,11291,11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304, #11200 +11305,11306,11307,11308,11309,11310,11311,11312,11313,11314,3679,11315,11316,11317,11318,4490, #11216 +11319,11320,11321,11322,11323,11324,11325,11326,11327,11328,11329,11330,11331,11332,11333,11334, #11232 +11335,11336,11337,11338,11339,11340,11341,11342,11343,11344,11345,11346,11347,4960,11348,11349, #11248 +11350,11351,11352,11353,11354,11355,11356,11357,11358,11359,11360,11361,11362,11363,11364,11365, #11264 +11366,11367,11368,11369,11370,11371,11372,11373,11374,11375,11376,11377,3961,4961,11378,11379, #11280 +11380,11381,11382,11383,11384,11385,11386,11387,11388,11389,11390,11391,11392,11393,11394,11395, #11296 +11396,11397,4192,11398,11399,11400,11401,11402,11403,11404,11405,11406,11407,11408,11409,11410, #11312 +11411,4962,11412,11413,11414,11415,11416,11417,11418,11419,11420,11421,11422,11423,11424,11425, #11328 +11426,11427,11428,11429,11430,11431,11432,11433,11434,11435,11436,11437,11438,11439,11440,11441, #11344 +11442,11443,11444,11445,11446,11447,11448,11449,11450,11451,11452,11453,11454,11455,11456,11457, #11360 +11458,11459,11460,11461,11462,11463,11464,11465,11466,11467,11468,11469,4963,11470,11471,4491, #11376 +11472,11473,11474,11475,4964,11476,11477,11478,11479,11480,11481,11482,11483,11484,11485,11486, #11392 +11487,11488,11489,11490,11491,11492,4965,11493,11494,11495,11496,11497,11498,11499,11500,11501, #11408 +11502,11503,11504,11505,11506,11507,11508,11509,11510,11511,11512,11513,11514,11515,11516,11517, #11424 +11518,11519,11520,11521,11522,11523,11524,11525,11526,11527,11528,11529,3962,11530,11531,11532, #11440 +11533,11534,11535,11536,11537,11538,11539,11540,11541,11542,11543,11544,11545,11546,11547,11548, #11456 +11549,11550,11551,11552,11553,11554,11555,11556,11557,11558,11559,11560,11561,11562,11563,11564, #11472 +4193,4194,11565,11566,11567,11568,11569,11570,11571,11572,11573,11574,11575,11576,11577,11578, #11488 +11579,11580,11581,11582,11583,11584,11585,11586,11587,11588,11589,11590,11591,4966,4195,11592, #11504 +11593,11594,11595,11596,11597,11598,11599,11600,11601,11602,11603,11604,3090,11605,11606,11607, #11520 +11608,11609,11610,4967,11611,11612,11613,11614,11615,11616,11617,11618,11619,11620,11621,11622, #11536 +11623,11624,11625,11626,11627,11628,11629,11630,11631,11632,11633,11634,11635,11636,11637,11638, #11552 +11639,11640,11641,11642,11643,11644,11645,11646,11647,11648,11649,11650,11651,11652,11653,11654, #11568 +11655,11656,11657,11658,11659,11660,11661,11662,11663,11664,11665,11666,11667,11668,11669,11670, #11584 +11671,11672,11673,11674,4968,11675,11676,11677,11678,11679,11680,11681,11682,11683,11684,11685, #11600 +11686,11687,11688,11689,11690,11691,11692,11693,3809,11694,11695,11696,11697,11698,11699,11700, #11616 +11701,11702,11703,11704,11705,11706,11707,11708,11709,11710,11711,11712,11713,11714,11715,11716, #11632 +11717,11718,3553,11719,11720,11721,11722,11723,11724,11725,11726,11727,11728,11729,11730,4969, #11648 +11731,11732,11733,11734,11735,11736,11737,11738,11739,11740,4492,11741,11742,11743,11744,11745, #11664 +11746,11747,11748,11749,11750,11751,11752,4970,11753,11754,11755,11756,11757,11758,11759,11760, #11680 +11761,11762,11763,11764,11765,11766,11767,11768,11769,11770,11771,11772,11773,11774,11775,11776, #11696 +11777,11778,11779,11780,11781,11782,11783,11784,11785,11786,11787,11788,11789,11790,4971,11791, #11712 +11792,11793,11794,11795,11796,11797,4972,11798,11799,11800,11801,11802,11803,11804,11805,11806, #11728 +11807,11808,11809,11810,4973,11811,11812,11813,11814,11815,11816,11817,11818,11819,11820,11821, #11744 +11822,11823,11824,11825,11826,11827,11828,11829,11830,11831,11832,11833,11834,3680,3810,11835, #11760 +11836,4974,11837,11838,11839,11840,11841,11842,11843,11844,11845,11846,11847,11848,11849,11850, #11776 +11851,11852,11853,11854,11855,11856,11857,11858,11859,11860,11861,11862,11863,11864,11865,11866, #11792 +11867,11868,11869,11870,11871,11872,11873,11874,11875,11876,11877,11878,11879,11880,11881,11882, #11808 +11883,11884,4493,11885,11886,11887,11888,11889,11890,11891,11892,11893,11894,11895,11896,11897, #11824 +11898,11899,11900,11901,11902,11903,11904,11905,11906,11907,11908,11909,11910,11911,11912,11913, #11840 +11914,11915,4975,11916,11917,11918,11919,11920,11921,11922,11923,11924,11925,11926,11927,11928, #11856 +11929,11930,11931,11932,11933,11934,11935,11936,11937,11938,11939,11940,11941,11942,11943,11944, #11872 +11945,11946,11947,11948,11949,4976,11950,11951,11952,11953,11954,11955,11956,11957,11958,11959, #11888 +11960,11961,11962,11963,11964,11965,11966,11967,11968,11969,11970,11971,11972,11973,11974,11975, #11904 +11976,11977,11978,11979,11980,11981,11982,11983,11984,11985,11986,11987,4196,11988,11989,11990, #11920 +11991,11992,4977,11993,11994,11995,11996,11997,11998,11999,12000,12001,12002,12003,12004,12005, #11936 +12006,12007,12008,12009,12010,12011,12012,12013,12014,12015,12016,12017,12018,12019,12020,12021, #11952 +12022,12023,12024,12025,12026,12027,12028,12029,12030,12031,12032,12033,12034,12035,12036,12037, #11968 +12038,12039,12040,12041,12042,12043,12044,12045,12046,12047,12048,12049,12050,12051,12052,12053, #11984 +12054,12055,12056,12057,12058,12059,12060,12061,4978,12062,12063,12064,12065,12066,12067,12068, #12000 +12069,12070,12071,12072,12073,12074,12075,12076,12077,12078,12079,12080,12081,12082,12083,12084, #12016 +12085,12086,12087,12088,12089,12090,12091,12092,12093,12094,12095,12096,12097,12098,12099,12100, #12032 +12101,12102,12103,12104,12105,12106,12107,12108,12109,12110,12111,12112,12113,12114,12115,12116, #12048 +12117,12118,12119,12120,12121,12122,12123,4979,12124,12125,12126,12127,12128,4197,12129,12130, #12064 +12131,12132,12133,12134,12135,12136,12137,12138,12139,12140,12141,12142,12143,12144,12145,12146, #12080 +12147,12148,12149,12150,12151,12152,12153,12154,4980,12155,12156,12157,12158,12159,12160,4494, #12096 +12161,12162,12163,12164,3811,12165,12166,12167,12168,12169,4495,12170,12171,4496,12172,12173, #12112 +12174,12175,12176,3812,12177,12178,12179,12180,12181,12182,12183,12184,12185,12186,12187,12188, #12128 +12189,12190,12191,12192,12193,12194,12195,12196,12197,12198,12199,12200,12201,12202,12203,12204, #12144 +12205,12206,12207,12208,12209,12210,12211,12212,12213,12214,12215,12216,12217,12218,12219,12220, #12160 +12221,4981,12222,12223,12224,12225,12226,12227,12228,12229,12230,12231,12232,12233,12234,12235, #12176 +4982,12236,12237,12238,12239,12240,12241,12242,12243,12244,12245,4983,12246,12247,12248,12249, #12192 +4984,12250,12251,12252,12253,12254,12255,12256,12257,12258,12259,12260,12261,12262,12263,12264, #12208 +4985,12265,4497,12266,12267,12268,12269,12270,12271,12272,12273,12274,12275,12276,12277,12278, #12224 +12279,12280,12281,12282,12283,12284,12285,12286,12287,4986,12288,12289,12290,12291,12292,12293, #12240 +12294,12295,12296,2473,12297,12298,12299,12300,12301,12302,12303,12304,12305,12306,12307,12308, #12256 +12309,12310,12311,12312,12313,12314,12315,12316,12317,12318,12319,3963,12320,12321,12322,12323, #12272 +12324,12325,12326,12327,12328,12329,12330,12331,12332,4987,12333,12334,12335,12336,12337,12338, #12288 +12339,12340,12341,12342,12343,12344,12345,12346,12347,12348,12349,12350,12351,12352,12353,12354, #12304 +12355,12356,12357,12358,12359,3964,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369, #12320 +12370,3965,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384, #12336 +12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400, #12352 +12401,12402,12403,12404,12405,12406,12407,12408,4988,12409,12410,12411,12412,12413,12414,12415, #12368 +12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431, #12384 +12432,12433,12434,12435,12436,12437,12438,3554,12439,12440,12441,12442,12443,12444,12445,12446, #12400 +12447,12448,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462, #12416 +12463,12464,4989,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477, #12432 +12478,12479,12480,4990,12481,12482,12483,12484,12485,12486,12487,12488,12489,4498,12490,12491, #12448 +12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507, #12464 +12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523, #12480 +12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,12535,12536,12537,12538,12539, #12496 +12540,12541,12542,12543,12544,12545,12546,12547,12548,12549,12550,12551,4991,12552,12553,12554, #12512 +12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570, #12528 +12571,12572,12573,12574,12575,12576,12577,12578,3036,12579,12580,12581,12582,12583,3966,12584, #12544 +12585,12586,12587,12588,12589,12590,12591,12592,12593,12594,12595,12596,12597,12598,12599,12600, #12560 +12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,12611,12612,12613,12614,12615,12616, #12576 +12617,12618,12619,12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,12632, #12592 +12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,4499,12647, #12608 +12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,12662,12663, #12624 +12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679, #12640 +12680,12681,12682,12683,12684,12685,12686,12687,12688,12689,12690,12691,12692,12693,12694,12695, #12656 +12696,12697,12698,4992,12699,12700,12701,12702,12703,12704,12705,12706,12707,12708,12709,12710, #12672 +12711,12712,12713,12714,12715,12716,12717,12718,12719,12720,12721,12722,12723,12724,12725,12726, #12688 +12727,12728,12729,12730,12731,12732,12733,12734,12735,12736,12737,12738,12739,12740,12741,12742, #12704 +12743,12744,12745,12746,12747,12748,12749,12750,12751,12752,12753,12754,12755,12756,12757,12758, #12720 +12759,12760,12761,12762,12763,12764,12765,12766,12767,12768,12769,12770,12771,12772,12773,12774, #12736 +12775,12776,12777,12778,4993,2175,12779,12780,12781,12782,12783,12784,12785,12786,4500,12787, #12752 +12788,12789,12790,12791,12792,12793,12794,12795,12796,12797,12798,12799,12800,12801,12802,12803, #12768 +12804,12805,12806,12807,12808,12809,12810,12811,12812,12813,12814,12815,12816,12817,12818,12819, #12784 +12820,12821,12822,12823,12824,12825,12826,4198,3967,12827,12828,12829,12830,12831,12832,12833, #12800 +12834,12835,12836,12837,12838,12839,12840,12841,12842,12843,12844,12845,12846,12847,12848,12849, #12816 +12850,12851,12852,12853,12854,12855,12856,12857,12858,12859,12860,12861,4199,12862,12863,12864, #12832 +12865,12866,12867,12868,12869,12870,12871,12872,12873,12874,12875,12876,12877,12878,12879,12880, #12848 +12881,12882,12883,12884,12885,12886,12887,4501,12888,12889,12890,12891,12892,12893,12894,12895, #12864 +12896,12897,12898,12899,12900,12901,12902,12903,12904,12905,12906,12907,12908,12909,12910,12911, #12880 +12912,4994,12913,12914,12915,12916,12917,12918,12919,12920,12921,12922,12923,12924,12925,12926, #12896 +12927,12928,12929,12930,12931,12932,12933,12934,12935,12936,12937,12938,12939,12940,12941,12942, #12912 +12943,12944,12945,12946,12947,12948,12949,12950,12951,12952,12953,12954,12955,12956,1772,12957, #12928 +12958,12959,12960,12961,12962,12963,12964,12965,12966,12967,12968,12969,12970,12971,12972,12973, #12944 +12974,12975,12976,12977,12978,12979,12980,12981,12982,12983,12984,12985,12986,12987,12988,12989, #12960 +12990,12991,12992,12993,12994,12995,12996,12997,4502,12998,4503,12999,13000,13001,13002,13003, #12976 +4504,13004,13005,13006,13007,13008,13009,13010,13011,13012,13013,13014,13015,13016,13017,13018, #12992 +13019,13020,13021,13022,13023,13024,13025,13026,13027,13028,13029,3449,13030,13031,13032,13033, #13008 +13034,13035,13036,13037,13038,13039,13040,13041,13042,13043,13044,13045,13046,13047,13048,13049, #13024 +13050,13051,13052,13053,13054,13055,13056,13057,13058,13059,13060,13061,13062,13063,13064,13065, #13040 +13066,13067,13068,13069,13070,13071,13072,13073,13074,13075,13076,13077,13078,13079,13080,13081, #13056 +13082,13083,13084,13085,13086,13087,13088,13089,13090,13091,13092,13093,13094,13095,13096,13097, #13072 +13098,13099,13100,13101,13102,13103,13104,13105,13106,13107,13108,13109,13110,13111,13112,13113, #13088 +13114,13115,13116,13117,13118,3968,13119,4995,13120,13121,13122,13123,13124,13125,13126,13127, #13104 +4505,13128,13129,13130,13131,13132,13133,13134,4996,4506,13135,13136,13137,13138,13139,4997, #13120 +13140,13141,13142,13143,13144,13145,13146,13147,13148,13149,13150,13151,13152,13153,13154,13155, #13136 +13156,13157,13158,13159,4998,13160,13161,13162,13163,13164,13165,13166,13167,13168,13169,13170, #13152 +13171,13172,13173,13174,13175,13176,4999,13177,13178,13179,13180,13181,13182,13183,13184,13185, #13168 +13186,13187,13188,13189,13190,13191,13192,13193,13194,13195,13196,13197,13198,13199,13200,13201, #13184 +13202,13203,13204,13205,13206,5000,13207,13208,13209,13210,13211,13212,13213,13214,13215,13216, #13200 +13217,13218,13219,13220,13221,13222,13223,13224,13225,13226,13227,4200,5001,13228,13229,13230, #13216 +13231,13232,13233,13234,13235,13236,13237,13238,13239,13240,3969,13241,13242,13243,13244,3970, #13232 +13245,13246,13247,13248,13249,13250,13251,13252,13253,13254,13255,13256,13257,13258,13259,13260, #13248 +13261,13262,13263,13264,13265,13266,13267,13268,3450,13269,13270,13271,13272,13273,13274,13275, #13264 +13276,5002,13277,13278,13279,13280,13281,13282,13283,13284,13285,13286,13287,13288,13289,13290, #13280 +13291,13292,13293,13294,13295,13296,13297,13298,13299,13300,13301,13302,3813,13303,13304,13305, #13296 +13306,13307,13308,13309,13310,13311,13312,13313,13314,13315,13316,13317,13318,13319,13320,13321, #13312 +13322,13323,13324,13325,13326,13327,13328,4507,13329,13330,13331,13332,13333,13334,13335,13336, #13328 +13337,13338,13339,13340,13341,5003,13342,13343,13344,13345,13346,13347,13348,13349,13350,13351, #13344 +13352,13353,13354,13355,13356,13357,13358,13359,13360,13361,13362,13363,13364,13365,13366,13367, #13360 +5004,13368,13369,13370,13371,13372,13373,13374,13375,13376,13377,13378,13379,13380,13381,13382, #13376 +13383,13384,13385,13386,13387,13388,13389,13390,13391,13392,13393,13394,13395,13396,13397,13398, #13392 +13399,13400,13401,13402,13403,13404,13405,13406,13407,13408,13409,13410,13411,13412,13413,13414, #13408 +13415,13416,13417,13418,13419,13420,13421,13422,13423,13424,13425,13426,13427,13428,13429,13430, #13424 +13431,13432,4508,13433,13434,13435,4201,13436,13437,13438,13439,13440,13441,13442,13443,13444, #13440 +13445,13446,13447,13448,13449,13450,13451,13452,13453,13454,13455,13456,13457,5005,13458,13459, #13456 +13460,13461,13462,13463,13464,13465,13466,13467,13468,13469,13470,4509,13471,13472,13473,13474, #13472 +13475,13476,13477,13478,13479,13480,13481,13482,13483,13484,13485,13486,13487,13488,13489,13490, #13488 +13491,13492,13493,13494,13495,13496,13497,13498,13499,13500,13501,13502,13503,13504,13505,13506, #13504 +13507,13508,13509,13510,13511,13512,13513,13514,13515,13516,13517,13518,13519,13520,13521,13522, #13520 +13523,13524,13525,13526,13527,13528,13529,13530,13531,13532,13533,13534,13535,13536,13537,13538, #13536 +13539,13540,13541,13542,13543,13544,13545,13546,13547,13548,13549,13550,13551,13552,13553,13554, #13552 +13555,13556,13557,13558,13559,13560,13561,13562,13563,13564,13565,13566,13567,13568,13569,13570, #13568 +13571,13572,13573,13574,13575,13576,13577,13578,13579,13580,13581,13582,13583,13584,13585,13586, #13584 +13587,13588,13589,13590,13591,13592,13593,13594,13595,13596,13597,13598,13599,13600,13601,13602, #13600 +13603,13604,13605,13606,13607,13608,13609,13610,13611,13612,13613,13614,13615,13616,13617,13618, #13616 +13619,13620,13621,13622,13623,13624,13625,13626,13627,13628,13629,13630,13631,13632,13633,13634, #13632 +13635,13636,13637,13638,13639,13640,13641,13642,5006,13643,13644,13645,13646,13647,13648,13649, #13648 +13650,13651,5007,13652,13653,13654,13655,13656,13657,13658,13659,13660,13661,13662,13663,13664, #13664 +13665,13666,13667,13668,13669,13670,13671,13672,13673,13674,13675,13676,13677,13678,13679,13680, #13680 +13681,13682,13683,13684,13685,13686,13687,13688,13689,13690,13691,13692,13693,13694,13695,13696, #13696 +13697,13698,13699,13700,13701,13702,13703,13704,13705,13706,13707,13708,13709,13710,13711,13712, #13712 +13713,13714,13715,13716,13717,13718,13719,13720,13721,13722,13723,13724,13725,13726,13727,13728, #13728 +13729,13730,13731,13732,13733,13734,13735,13736,13737,13738,13739,13740,13741,13742,13743,13744, #13744 +13745,13746,13747,13748,13749,13750,13751,13752,13753,13754,13755,13756,13757,13758,13759,13760, #13760 +13761,13762,13763,13764,13765,13766,13767,13768,13769,13770,13771,13772,13773,13774,3273,13775, #13776 +13776,13777,13778,13779,13780,13781,13782,13783,13784,13785,13786,13787,13788,13789,13790,13791, #13792 +13792,13793,13794,13795,13796,13797,13798,13799,13800,13801,13802,13803,13804,13805,13806,13807, #13808 +13808,13809,13810,13811,13812,13813,13814,13815,13816,13817,13818,13819,13820,13821,13822,13823, #13824 +13824,13825,13826,13827,13828,13829,13830,13831,13832,13833,13834,13835,13836,13837,13838,13839, #13840 +13840,13841,13842,13843,13844,13845,13846,13847,13848,13849,13850,13851,13852,13853,13854,13855, #13856 +13856,13857,13858,13859,13860,13861,13862,13863,13864,13865,13866,13867,13868,13869,13870,13871, #13872 +13872,13873,13874,13875,13876,13877,13878,13879,13880,13881,13882,13883,13884,13885,13886,13887, #13888 +13888,13889,13890,13891,13892,13893,13894,13895,13896,13897,13898,13899,13900,13901,13902,13903, #13904 +13904,13905,13906,13907,13908,13909,13910,13911,13912,13913,13914,13915,13916,13917,13918,13919, #13920 +13920,13921,13922,13923,13924,13925,13926,13927,13928,13929,13930,13931,13932,13933,13934,13935, #13936 +13936,13937,13938,13939,13940,13941,13942,13943,13944,13945,13946,13947,13948,13949,13950,13951, #13952 +13952,13953,13954,13955,13956,13957,13958,13959,13960,13961,13962,13963,13964,13965,13966,13967, #13968 +13968,13969,13970,13971,13972) #13973 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/big5prober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/big5prober.py new file mode 100755 index 0000000..e6b52aa --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/big5prober.py @@ -0,0 +1,41 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from mbcharsetprober import MultiByteCharSetProber +from codingstatemachine import CodingStateMachine +from chardistribution import Big5DistributionAnalysis +from mbcssm import Big5SMModel + +class Big5Prober(MultiByteCharSetProber): + def __init__(self): + MultiByteCharSetProber.__init__(self) + self._mCodingSM = CodingStateMachine(Big5SMModel) + self._mDistributionAnalyzer = Big5DistributionAnalysis() + self.reset() + + def get_charset_name(self): + return "Big5" diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/chardistribution.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/chardistribution.py new file mode 100755 index 0000000..b893341 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/chardistribution.py @@ -0,0 +1,200 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants +from euctwfreq import EUCTWCharToFreqOrder, EUCTW_TABLE_SIZE, EUCTW_TYPICAL_DISTRIBUTION_RATIO +from euckrfreq import EUCKRCharToFreqOrder, EUCKR_TABLE_SIZE, EUCKR_TYPICAL_DISTRIBUTION_RATIO +from gb2312freq import GB2312CharToFreqOrder, GB2312_TABLE_SIZE, GB2312_TYPICAL_DISTRIBUTION_RATIO +from big5freq import Big5CharToFreqOrder, BIG5_TABLE_SIZE, BIG5_TYPICAL_DISTRIBUTION_RATIO +from jisfreq import JISCharToFreqOrder, JIS_TABLE_SIZE, JIS_TYPICAL_DISTRIBUTION_RATIO + +ENOUGH_DATA_THRESHOLD = 1024 +SURE_YES = 0.99 +SURE_NO = 0.01 + +class CharDistributionAnalysis: + def __init__(self): + self._mCharToFreqOrder = None # Mapping table to get frequency order from char order (get from GetOrder()) + self._mTableSize = None # Size of above table + self._mTypicalDistributionRatio = None # This is a constant value which varies from language to language, used in calculating confidence. See http://www.mozilla.org/projects/intl/UniversalCharsetDetection.html for further detail. + self.reset() + + def reset(self): + """reset analyser, clear any state""" + self._mDone = constants.False # If this flag is set to constants.True, detection is done and conclusion has been made + self._mTotalChars = 0 # Total characters encountered + self._mFreqChars = 0 # The number of characters whose frequency order is less than 512 + + def feed(self, aStr, aCharLen): + """feed a character with known length""" + if aCharLen == 2: + # we only care about 2-bytes character in our distribution analysis + order = self.get_order(aStr) + else: + order = -1 + if order >= 0: + self._mTotalChars += 1 + # order is valid + if order < self._mTableSize: + if 512 > self._mCharToFreqOrder[order]: + self._mFreqChars += 1 + + def get_confidence(self): + """return confidence based on existing data""" + # if we didn't receive any character in our consideration range, return negative answer + if self._mTotalChars <= 0: + return SURE_NO + + if self._mTotalChars != self._mFreqChars: + r = self._mFreqChars / ((self._mTotalChars - self._mFreqChars) * self._mTypicalDistributionRatio) + if r < SURE_YES: + return r + + # normalize confidence (we don't want to be 100% sure) + return SURE_YES + + def got_enough_data(self): + # It is not necessary to receive all data to draw conclusion. For charset detection, + # certain amount of data is enough + return self._mTotalChars > ENOUGH_DATA_THRESHOLD + + def get_order(self, aStr): + # We do not handle characters based on the original encoding string, but + # convert this encoding string to a number, here called order. + # This allows multiple encodings of a language to share one frequency table. + return -1 + +class EUCTWDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + CharDistributionAnalysis.__init__(self) + self._mCharToFreqOrder = EUCTWCharToFreqOrder + self._mTableSize = EUCTW_TABLE_SIZE + self._mTypicalDistributionRatio = EUCTW_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, aStr): + # for euc-TW encoding, we are interested + # first byte range: 0xc4 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + if aStr[0] >= '\xC4': + return 94 * (ord(aStr[0]) - 0xC4) + ord(aStr[1]) - 0xA1 + else: + return -1 + +class EUCKRDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + CharDistributionAnalysis.__init__(self) + self._mCharToFreqOrder = EUCKRCharToFreqOrder + self._mTableSize = EUCKR_TABLE_SIZE + self._mTypicalDistributionRatio = EUCKR_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, aStr): + # for euc-KR encoding, we are interested + # first byte range: 0xb0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + if aStr[0] >= '\xB0': + return 94 * (ord(aStr[0]) - 0xB0) + ord(aStr[1]) - 0xA1 + else: + return -1; + +class GB2312DistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + CharDistributionAnalysis.__init__(self) + self._mCharToFreqOrder = GB2312CharToFreqOrder + self._mTableSize = GB2312_TABLE_SIZE + self._mTypicalDistributionRatio = GB2312_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, aStr): + # for GB2312 encoding, we are interested + # first byte range: 0xb0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + if (aStr[0] >= '\xB0') and (aStr[1] >= '\xA1'): + return 94 * (ord(aStr[0]) - 0xB0) + ord(aStr[1]) - 0xA1 + else: + return -1; + +class Big5DistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + CharDistributionAnalysis.__init__(self) + self._mCharToFreqOrder = Big5CharToFreqOrder + self._mTableSize = BIG5_TABLE_SIZE + self._mTypicalDistributionRatio = BIG5_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, aStr): + # for big5 encoding, we are interested + # first byte range: 0xa4 -- 0xfe + # second byte range: 0x40 -- 0x7e , 0xa1 -- 0xfe + # no validation needed here. State machine has done that + if aStr[0] >= '\xA4': + if aStr[1] >= '\xA1': + return 157 * (ord(aStr[0]) - 0xA4) + ord(aStr[1]) - 0xA1 + 63 + else: + return 157 * (ord(aStr[0]) - 0xA4) + ord(aStr[1]) - 0x40 + else: + return -1 + +class SJISDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + CharDistributionAnalysis.__init__(self) + self._mCharToFreqOrder = JISCharToFreqOrder + self._mTableSize = JIS_TABLE_SIZE + self._mTypicalDistributionRatio = JIS_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, aStr): + # for sjis encoding, we are interested + # first byte range: 0x81 -- 0x9f , 0xe0 -- 0xfe + # second byte range: 0x40 -- 0x7e, 0x81 -- oxfe + # no validation needed here. State machine has done that + if (aStr[0] >= '\x81') and (aStr[0] <= '\x9F'): + order = 188 * (ord(aStr[0]) - 0x81) + elif (aStr[0] >= '\xE0') and (aStr[0] <= '\xEF'): + order = 188 * (ord(aStr[0]) - 0xE0 + 31) + else: + return -1; + order = order + ord(aStr[1]) - 0x40 + if aStr[1] > '\x7F': + order =- 1 + return order + +class EUCJPDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + CharDistributionAnalysis.__init__(self) + self._mCharToFreqOrder = JISCharToFreqOrder + self._mTableSize = JIS_TABLE_SIZE + self._mTypicalDistributionRatio = JIS_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, aStr): + # for euc-JP encoding, we are interested + # first byte range: 0xa0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + if aStr[0] >= '\xA0': + return 94 * (ord(aStr[0]) - 0xA1) + ord(aStr[1]) - 0xa1 + else: + return -1 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/charsetgroupprober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/charsetgroupprober.py new file mode 100755 index 0000000..5188069 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/charsetgroupprober.py @@ -0,0 +1,96 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants, sys +from charsetprober import CharSetProber + +class CharSetGroupProber(CharSetProber): + def __init__(self): + CharSetProber.__init__(self) + self._mActiveNum = 0 + self._mProbers = [] + self._mBestGuessProber = None + + def reset(self): + CharSetProber.reset(self) + self._mActiveNum = 0 + for prober in self._mProbers: + if prober: + prober.reset() + prober.active = constants.True + self._mActiveNum += 1 + self._mBestGuessProber = None + + def get_charset_name(self): + if not self._mBestGuessProber: + self.get_confidence() + if not self._mBestGuessProber: return None +# self._mBestGuessProber = self._mProbers[0] + return self._mBestGuessProber.get_charset_name() + + def feed(self, aBuf): + for prober in self._mProbers: + if not prober: continue + if not prober.active: continue + st = prober.feed(aBuf) + if not st: continue + if st == constants.eFoundIt: + self._mBestGuessProber = prober + return self.get_state() + elif st == constants.eNotMe: + prober.active = constants.False + self._mActiveNum -= 1 + if self._mActiveNum <= 0: + self._mState = constants.eNotMe + return self.get_state() + return self.get_state() + + def get_confidence(self): + st = self.get_state() + if st == constants.eFoundIt: + return 0.99 + elif st == constants.eNotMe: + return 0.01 + bestConf = 0.0 + self._mBestGuessProber = None + for prober in self._mProbers: + if not prober: continue + if not prober.active: + if constants._debug: + sys.stderr.write(prober.get_charset_name() + ' not active\n') + continue + cf = prober.get_confidence() + if constants._debug: + sys.stderr.write('%s confidence = %s\n' % (prober.get_charset_name(), cf)) + if bestConf < cf: + bestConf = cf + self._mBestGuessProber = prober + if not self._mBestGuessProber: return 0.0 + return bestConf +# else: +# self._mBestGuessProber = self._mProbers[0] +# return self._mBestGuessProber.get_confidence() diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/charsetprober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/charsetprober.py new file mode 100755 index 0000000..3ac1683 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/charsetprober.py @@ -0,0 +1,60 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants, re + +class CharSetProber: + def __init__(self): + pass + + def reset(self): + self._mState = constants.eDetecting + + def get_charset_name(self): + return None + + def feed(self, aBuf): + pass + + def get_state(self): + return self._mState + + def get_confidence(self): + return 0.0 + + def filter_high_bit_only(self, aBuf): + aBuf = re.sub(r'([\x00-\x7F])+', ' ', aBuf) + return aBuf + + def filter_without_english_letters(self, aBuf): + aBuf = re.sub(r'([A-Za-z])+', ' ', aBuf) + return aBuf + + def filter_with_english_letters(self, aBuf): + # TODO + return aBuf diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/codingstatemachine.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/codingstatemachine.py new file mode 100755 index 0000000..452d3b0 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/codingstatemachine.py @@ -0,0 +1,56 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from constants import eStart, eError, eItsMe + +class CodingStateMachine: + def __init__(self, sm): + self._mModel = sm + self._mCurrentBytePos = 0 + self._mCurrentCharLen = 0 + self.reset() + + def reset(self): + self._mCurrentState = eStart + + def next_state(self, c): + # for each byte we get its class + # if it is first byte, we also get byte length + byteCls = self._mModel['classTable'][ord(c)] + if self._mCurrentState == eStart: + self._mCurrentBytePos = 0 + self._mCurrentCharLen = self._mModel['charLenTable'][byteCls] + # from byte's class and stateTable, we get its next state + self._mCurrentState = self._mModel['stateTable'][self._mCurrentState * self._mModel['classFactor'] + byteCls] + self._mCurrentBytePos += 1 + return self._mCurrentState + + def get_current_charlen(self): + return self._mCurrentCharLen + + def get_coding_state_machine(self): + return self._mModel['name'] diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/constants.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/constants.py new file mode 100755 index 0000000..e94e226 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/constants.py @@ -0,0 +1,47 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +_debug = 0 + +eDetecting = 0 +eFoundIt = 1 +eNotMe = 2 + +eStart = 0 +eError = 1 +eItsMe = 2 + +SHORTCUT_THRESHOLD = 0.95 + +import __builtin__ +if not hasattr(__builtin__, 'False'): + False = 0 + True = 1 +else: + False = __builtin__.False + True = __builtin__.True diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/css/chardet.css b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/css/chardet.css new file mode 100644 index 0000000..91baaf3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/css/chardet.css @@ -0,0 +1,299 @@ +html { + margin: 0; + padding: 0; +} + +body { + background-color: #fff; + color: #333; + font-family: 'Lucida Grande', Verdana, Geneva, Lucida, Helvetica, sans-serif; + font-size: 100%; + margin: 10px; + padding: 0; +} + +a:link, a:visited { + background-color: transparent; + color: #333; + text-decoration: none !important; + border-bottom: 1px dotted #333 !important; + text-decoration: underline; + border-bottom: 0; +} + +a:hover { + background-color: transparent; + color: #993344; + text-decoration: none !important; + text-decoration: underline; + border-bottom: 1px dotted #993344 !important; + border-bottom: 0; +} + +h1 { + margin: 8px 0 0 0; + padding: 0; + font-variant: small-caps; + letter-spacing: 0.1em; + font-family: "Book Antiqua", Georgia, Palatino, Times, "Times New Roman", serif; +} + +h1 a:link, h1 a:visited, h1 a:hover { + background-color: transparent ! important; + color: #333 ! important; + text-decoration: none ! important; + border-bottom: 0px ! important; +} + +#intro { + width: 730px; + } + +#intro ul { + margin-left: 0; + padding-left: 0; + display: inline; +} + +#intro ul li { + display: inline; + font-size: small; +} + +#intro ul li.li1 { +} + +#intro p { + font-size: small; + font-weight: normal; + margin: 1.2em 0 0 0; + padding: 0; +} + +.z { + float:left; + background: url(/img/shadowAlpha.png) no-repeat bottom right !important; + background: url(/img/shadow.gif) no-repeat bottom right; + margin: 15px 0 0 10px !important; + margin: 15px 0 0 5px; +} + +.z .sectionInner { + background: none !important; + background: url(/img/shadow2.gif) no-repeat left top; + padding: 0 !important; + padding: 0 6px 6px 0; + } + +.z .sectionInner .sectionInner2 { + background-color: #fff; + border: 1px solid #a9a9a9; + padding: 4px; + margin: -6px 6px 6px -6px !important; + margin: 0; +} + +.s { + margin-left: 1em; + margin-right: 1em; + margin-bottom: 1em; +} + +#main { + clear: left; + margin-left: 11px; + margin-bottom: 2em; + font-size: small; +} + +#mainInner { + margin-left: 1em; + margin-bottom: 2em; + padding-top: 1em; +} + +.footernavigation { + clear: both; + font-size: small; + padding-bottom: 1em; + margin-bottom: 0; +} + +.example, .section, .appendix { + line-height: 150%; +} + +#breadcrumb { + width: 100%; + margin: 0 0 1em 0; + padding: 0; + line-height: 140%; + font-size: small; +} + +#breadcrumb #thispage { + font-weight: bold; +} + +/* ----- Python code syntax coloring ----- */ +.computeroutput, .traceback, .pykeyword, .pystring, .pycomment, .pyfunction, .pyclass { + background-color: white; +} + +.pykeyword, .pyfunction, .pyclass { + font-weight: bold; +} + +.computeroutput { + color: teal; +} + +.traceback { + color: red; +} + +.pykeyword { + color: navy; +} + +.pystring { + color: olive; +} + +.pycomment { + color: green; + font-style: italic; +} + +.pyfunction { + color: teal; +} + +.pyclass { + color: blue; +} + +/* ----- standard stuff ----- */ +.skip { + display: none; +} + +samp, code, tt, pre { + font-weight: normal; + font-family: monospace; + font-size: small; +} + +img { + border: 0; +} + +acronym, abbr { +/* border-bottom: 1px dotted #333;*/ + border-bottom: 0; + font-style: normal; + cursor: help; +} + +hr { + clear: both; + margin-top: 2em !important; + margin-top: 1em; + height: 1px; + background-color: #cecbc6; + color: #cecbc6; +} + +#footer { + text-align: center; + font-size: x-small; +} + +body.docs .example { + border-left: 4px double #ddd !important; + border-left: 1px solid #ccc; + margin-left: 2em; + padding-left: 2em; +} + +body.docs .example h3 { + font-size: 100%; +} + +body.docs .example a.skip:link, +body.docs .example a.skip:visited, +body.docs .example a.skip:hover, +body.docs .section h3.title a.skip:link, +body.docs .section h3.title a.skip:visited, +body.docs .section h3.title a.skip:hover, +body.docs .appendix h3.title a.skip:link, +body.docs .appendix h3.title a.skip:visited, +body.docs .appendix h3.title a.skip:hover { + display: block; + float: left; + vertical-align: bottom; + text-decoration: none; + border-bottom: 0 ! important; + margin-right: 6px; +} + +.reference-from h3, +.seealso h3, +.furtherreading h3 { + margin-top: -1.2em; + margin-left: -15px; + font-size: small; + width: 8em; + border: 1px solid #a9a9a9; + padding: 3px 3px 3px 13px; + background: white; + position: relative; +} + +.reference-from, .seealso, .furtherreading { + width: 680px; + margin-top: 3em; + margin-bottom: 3em; + border: 1px solid #a9a9a9; +} + +table.tip, table.note, table.warning, table.caution, table.important { + margin-bottom: 1em; +} + +.table h3 { + display: none; +} + +.table table td { + padding: 5px 1em 5px 1em; +} + +div.download { + width: 708px; + margin-top: 3em; + margin-bottom: 3em; + border: 1px solid #a9a9a9; +} + +div.download h3 { + margin-top: -1.2em; + margin-left: -15px; + font-size: small; + width: 10em; + border: 1px solid #a9a9a9; + padding: 3px 3px 3px 13px; + background-color: #fff; + color: #222; + position: relative; +} + +div.download p { + margin-left: 1em; +} + +div.download ul { + list-style: none; + padding-left: 1em; + margin-left: 0; +} diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/faq.html b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/faq.html new file mode 100644 index 0000000..d225dc9 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/faq.html @@ -0,0 +1,107 @@ + + + + +Frequently asked questions [Universal Encoding Detector] + + + + + + + + + + +
+ +
+
+
+ +
+
+

+ Frequently asked questions

+
+
+
+
+

+ What is character encoding?

+
+
+

When you think of “textâ€, you probably think of “characters and symbols I see on my computer screenâ€. But computers don’t deal in characters and symbols; they deal in bits and bytes. Every piece of text you’ve ever seen on a computer screen is actually stored in a particular character encoding. There are many different character encodings, some optimized for particular languages like Russian or Chinese or English, and others that can be used for multiple languages. Very roughly speaking, the character encoding provides a mapping between the stuff you see on your screen and the stuff your computer actually stores in memory and on disk.

+

In reality, it’s more complicated than that. Many characters are common to multiple encodings, but each encoding may use a different sequence of bytes to actually store those characters in memory or on disk. So you can think of the character encoding as a kind of decryption key for the text. Whenever someone gives you a sequence of bytes and claims it’s “textâ€, you need to know what character encoding they used so you can decode the bytes into characters and display them (or process them, or whatever).

+
+
+
+

+ What is character encoding auto-detection?

+
+
+

It means taking a sequence of bytes in an unknown character encoding, and attempting to determine the encoding so you can read the text. It’s like cracking a code when you don’t have the decryption key.

+
+
+
+

+ Isn’t that impossible?

+
+
+

In general, yes. However, some encodings are optimized for specific languages, and languages are not random. Some character sequences pop up all the time, while other sequences make no sense. A person fluent in English who opens a newspaper and finds “txzqJv 2!dasd0a QqdKjvz†will instantly recognize that that isn’t English (even though it is composed entirely of English letters). By studying lots of “typical†text, a computer algorithm can simulate this kind of fluency and make an educated guess about a text’s language.

+

In other words, encoding detection is really language detection, combined with knowledge of which languages tend to use which character encodings.

+
+
+
+

+ Who wrote this detection algorithm?

+
+
+

This library is a port of the auto-detection code in Mozilla. I have attempted to maintain as much of the original structure as possible (mostly for selfish reasons, to make it easier to maintain the port as the original code evolves). I have also retained the original authors’ comments, which are quite extensive and informative.

+

You may also be interested in the research paper which led to the Mozilla implementation, A composite approach to language/encoding detection.

+
+
+
+

+ Yippie! Screw the standards, I’ll just auto-detect everything!

+
+
+

Don’t do that. Virtually every format and protocol contains a method for specifying character encoding.

+
    +
  • HTTP can define a charset parameter in the Content-type header.
  • +
  • HTML documents can define a <meta http-equiv="content-type"> element in the <head> of a web page.
  • +
  • XML documents can define an encoding attribute in the XML prolog.
  • +
+

If text comes with explicit character encoding information, you should use it. If the text has no explicit information, but the relevant standard defines a default encoding, you should use that. (This is harder than it sounds, because standards can overlap. If you fetch an XML document over HTTP, you need to support both standards and figure out which one wins if they give you conflicting information.)

+

Despite the complexity, it’s worthwhile to follow standards and respect explicit character encoding information. It will almost certainly be faster and more accurate than trying to auto-detect the encoding. It will also make the world a better place, since your program will interoperate with other programs that follow the same standards.

+
+
+
+

+ Why bother with auto-detection if it’s slow, inaccurate, and non-standard?

+
+
+

Sometimes you receive text with verifiably inaccurate encoding information. Or text without any encoding information, and the specified default encoding doesn’t work. There are also some poorly designed standards that have no way to specify encoding at all.

+

If following the relevant standards gets you nowhere, and you decide that processing the text is more important than maintaining interoperability, then you can try to auto-detect the character encoding as a last resort. An example is my Universal Feed Parser, which calls this auto-detection library only after exhausting all other options.

+
+
+
+
â†Â Documentation +
+
+Supported encodings →
+
+
+ +
+ + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/history.html b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/history.html new file mode 100644 index 0000000..d45f647 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/history.html @@ -0,0 +1,67 @@ + + + + +Revision history [Universal Encoding Detector] + + + + + + + + + + +
+ +
+
+
+ +
+
+
+

+ Revision history

+
+

+

Universal Encoding Detector 1.0.1 is the latest version.

+
+
+
+
+
+
1.0.1-py3 (2009-06-26)
+
  • Released Python 3 version
+
1.0.1 (2008-03-05)
+
    +
  • fixed typo in detecting little endian UTF-16; closes issue 81 +
  • +
  • fixed length of ISO2022JPCharLenTable; closes issue 98 +
  • +
+
1.0 (2006-01-10)
+
  • Initial release
+
+
+
+
â†Â How it works +
+
+Terms of use →
+
+
+ +
+ + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/how-it-works.html b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/how-it-works.html new file mode 100644 index 0000000..f722984 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/how-it-works.html @@ -0,0 +1,114 @@ + + + + +How it works [Universal Encoding Detector] + + + + + + + + + + +
+ +
+
+
+ +
+
+
+

+ How it works

+
+

+

This is a brief guide to navigating the code itself.

+
+
+
+
+

First, you should read A composite approach to language/encoding detection, which explains the detection algorithm and how it was derived. This will help you later when you stumble across the huge character frequency distribution tables like big5freq.py and language models like langcyrillicmodel.py.

+

The main entry point for the detection algorithm is universaldetector.py, which has one class, UniversalDetector. (You might think the main entry point is the detect function in chardet/__init__.py, but that’s really just a convenience function that creates a UniversalDetector object, calls it, and returns its result.)

+

There are 5 categories of encodings that UniversalDetector handles:

+
    +
  1. +UTF-n with a BOM. This includes UTF-8, both BE and LE variants of UTF-16, and all 4 byte-order variants of UTF-32.
  2. +
  3. Escaped encodings, which are entirely 7-bit ASCII compatible, where non-ASCII characters start with an escape sequence. Examples: ISO-2022-JP (Japanese) and HZ-GB-2312 (Chinese).
  4. +
  5. Multi-byte encodings, where each character is represented by a variable number of bytes. Examples: Big5 (Chinese), SHIFT_JIS (Japanese), EUC-KR (Korean), and UTF-8 without a BOM.
  6. +
  7. Single-byte encodings, where each character is represented by one byte. Examples: KOI8-R (Russian), windows-1255 (Hebrew), and TIS-620 (Thai).
  8. +
  9. +windows-1252, which is used primarily on Microsoft Windows by middle managers who don’t know a character encoding from a hole in the ground.
  10. +
+
+
+

+ UTF-n with a BOM +

+
+
+

If the text starts with a BOM, we can reasonably assume that the text is encoded in UTF-8, UTF-16, or UTF-32. (The BOM will tell us exactly which one; that’s what it’s for.) This is handled inline in UniversalDetector, which returns the result immediately without any further processing.

+
+
+
+

+ Escaped encodings

+
+
+

If the text contains a recognizable escape sequence that might indicate an escaped encoding, UniversalDetector creates an EscCharSetProber (defined in escprober.py) and feeds it the text.

+

EscCharSetProber creates a series of state machines, based on models of HZ-GB-2312, ISO-2022-CN, ISO-2022-JP, and ISO-2022-KR (defined in escsm.py). EscCharSetProber feeds the text to each of these state machines, one byte at a time. If any state machine ends up uniquely identifying the encoding, EscCharSetProber immediately returns the positive result to UniversalDetector, which returns it to the caller. If any state machine hits an illegal sequence, it is dropped and processing continues with the other state machines.

+
+
+
+

+ Multi-byte encodings

+
+
+

Assuming no BOM, UniversalDetector checks whether the text contains any high-bit characters. If so, it creates a series of “probers†for detecting multi-byte encodings, single-byte encodings, and as a last resort, windows-1252.

+

The multi-byte encoding prober, MBCSGroupProber (defined in mbcsgroupprober.py), is really just a shell that manages a group of other probers, one for each multi-byte encoding: Big5, GB2312, EUC-TW, EUC-KR, EUC-JP, SHIFT_JIS, and UTF-8. MBCSGroupProber feeds the text to each of these encoding-specific probers and checks the results. If a prober reports that it has found an illegal byte sequence, it is dropped from further processing (so that, for instance, any subsequent calls to UniversalDetector.feed will skip that prober). If a prober reports that it is reasonably confident that it has detected the encoding, MBCSGroupProber reports this positive result to UniversalDetector, which reports the result to the caller.

+

Most of the multi-byte encoding probers are inherited from MultiByteCharSetProber (defined in mbcharsetprober.py), and simply hook up the appropriate state machine and distribution analyzer and let MultiByteCharSetProber do the rest of the work. MultiByteCharSetProber runs the text through the encoding-specific state machine, one byte at a time, to look for byte sequences that would indicate a conclusive positive or negative result. At the same time, MultiByteCharSetProber feeds the text to an encoding-specific distribution analyzer.

+

The distribution analyzers (each defined in chardistribution.py) use language-specific models of which characters are used most frequently. Once MultiByteCharSetProber has fed enough text to the distribution analyzer, it calculates a confidence rating based on the number of frequently-used characters, the total number of characters, and a language-specific distribution ratio. If the confidence is high enough, MultiByteCharSetProber returns the result to MBCSGroupProber, which returns it to UniversalDetector, which returns it to the caller.

+

The case of Japanese is more difficult. Single-character distribution analysis is not always sufficient to distinguish between EUC-JP and SHIFT_JIS, so the SJISProber (defined in sjisprober.py) also uses 2-character distribution analysis. SJISContextAnalysis and EUCJPContextAnalysis (both defined in jpcntx.py and both inheriting from a common JapaneseContextAnalysis class) check the frequency of Hiragana syllabary characters within the text. Once enough text has been processed, they return a confidence level to SJISProber, which checks both analyzers and returns the higher confidence level to MBCSGroupProber.

+
+
+
+

+ Single-byte encodings

+
+
+

The single-byte encoding prober, SBCSGroupProber (defined in sbcsgroupprober.py), is also just a shell that manages a group of other probers, one for each combination of single-byte encoding and language: windows-1251, KOI8-R, ISO-8859-5, MacCyrillic, IBM855, and IBM866 (Russian); ISO-8859-7 and windows-1253 (Greek); ISO-8859-5 and windows-1251 (Bulgarian); ISO-8859-2 and windows-1250 (Hungarian); TIS-620 (Thai); windows-1255 and ISO-8859-8 (Hebrew).

+

SBCSGroupProber feeds the text to each of these encoding+language-specific probers and checks the results. These probers are all implemented as a single class, SingleByteCharSetProber (defined in sbcharsetprober.py), which takes a language model as an argument. The language model defines how frequently different 2-character sequences appear in typical text. SingleByteCharSetProber processes the text and tallies the most frequently used 2-character sequences. Once enough text has been processed, it calculates a confidence level based on the number of frequently-used sequences, the total number of characters, and a language-specific distribution ratio.

+

Hebrew is handled as a special case. If the text appears to be Hebrew based on 2-character distribution analysis, HebrewProber (defined in hebrewprober.py) tries to distinguish between Visual Hebrew (where the source text actually stored “backwards†line-by-line, and then displayed verbatim so it can be read from right to left) and Logical Hebrew (where the source text is stored in reading order and then rendered right-to-left by the client). Because certain characters are encoded differently based on whether they appear in the middle of or at the end of a word, we can make a reasonable guess about direction of the source text, and return the appropriate encoding (windows-1255 for Logical Hebrew, or ISO-8859-8 for Visual Hebrew).

+
+
+
+

+ windows-1252

+
+
+

If UniversalDetector detects a high-bit character in the text, but none of the other multi-byte or single-byte encoding probers return a confident result, it creates a Latin1Prober (defined in latin1prober.py) to try to detect English text in a windows-1252 encoding. This detection is inherently unreliable, because English letters are encoded in the same way in many different encodings. The only way to distinguish windows-1252 is through commonly used symbols like smart quotes, curly apostrophes, copyright symbols, and the like. Latin1Prober automatically reduces its confidence rating to allow more accurate probers to win if at all possible.

+
+
+
+
â†Â Usage +
+
+Revision history →
+
+
+ +
+ + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/caution.png b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/caution.png new file mode 100644 index 0000000..5b7809c Binary files /dev/null and b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/caution.png differ diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/important.png b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/important.png new file mode 100644 index 0000000..fc1db35 Binary files /dev/null and b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/important.png differ diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/note.png b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/note.png new file mode 100644 index 0000000..d0c3c64 Binary files /dev/null and b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/note.png differ diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/permalink.gif b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/permalink.gif new file mode 100644 index 0000000..b843ea8 Binary files /dev/null and b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/permalink.gif differ diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/tip.png b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/tip.png new file mode 100644 index 0000000..5c4aab3 Binary files /dev/null and b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/tip.png differ diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/warning.png b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/warning.png new file mode 100644 index 0000000..1c33db8 Binary files /dev/null and b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/images/warning.png differ diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/index.html b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/index.html new file mode 100644 index 0000000..b727180 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/index.html @@ -0,0 +1,74 @@ + + + + +Documentation [Universal Encoding Detector] + + + + + + + + +
+ +
+
+ + + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/license.html b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/license.html new file mode 100644 index 0000000..f989161 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/license.html @@ -0,0 +1,62 @@ + + + + +Terms of use [Universal Encoding Detector] + + + + + + + + + +
+ +
+
+
+ +
+
+

+ Terms of use

+
+
+

+ Software

+

The Universal Encoding Detector library is copyright © 2006-2009 Mark Pilgrim. All rights reserved.

+

Portions copyright © 1998-2001 Netscape Communications Corporation. All rights reserved.

+

The Universal Encoding Detector library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

+

This library 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 Lesser General Public License for more details.

+

You should have received a copy of the GNU Lesser General Public License along with this library (in a file named COPYING); if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

+

+ Documentation

+

The Universal Encoding Detector documentation is copyright © 2006-2009 Mark Pilgrim. All rights reserved.

+

Redistribution and use in source (XML DocBook) and “compiled†forms (SGML, HTML, PDF, PostScript, RTF and so forth) with or without modification, are permitted provided that the following conditions are met:

+
    +
  1. Redistributions of source code (XML DocBook) must retain the above copyright notice, this list of conditions and the following disclaimer unmodified.
  2. +
  3. Redistributions in compiled form (transformed to other DTDs, converted to PDF, PostScript, RTF and other formats) 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.
  4. +
+

THIS DOCUMENTATION 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 DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+
+
+
â†Â Revision history +
+
+
+
+ +
+ + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/supported-encodings.html b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/supported-encodings.html new file mode 100644 index 0000000..d47488e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/supported-encodings.html @@ -0,0 +1,86 @@ + + + + +Supported encodings [Universal Encoding Detector] + + + + + + + + + + +
+ +
+
+
+ +
+
+
+

+ Supported encodings

+
+

+

Universal Encoding Detector currently supports over two dozen character encodings.

+
+
+
+
+
    +
  • +Big5, GB2312/GB18030, EUC-TW, HZ-GB-2312, and ISO-2022-CN (Traditional and Simplified Chinese)
  • +
  • +EUC-JP, SHIFT_JIS, and ISO-2022-JP (Japanese)
  • +
  • +EUC-KR and ISO-2022-KR (Korean)
  • +
  • +KOI8-R, MacCyrillic, IBM855, IBM866, ISO-8859-5, and windows-1251 (Russian)
  • +
  • +ISO-8859-2 and windows-1250 (Hungarian)
  • +
  • +ISO-8859-5 and windows-1251 (Bulgarian)
  • +
  • windows-1252
  • +
  • +ISO-8859-7 and windows-1253 (Greek)
  • +
  • +ISO-8859-8 and windows-1255 (Visual and Logical Hebrew)
  • +
  • +TIS-620 (Thai)
  • +
  • +UTF-32 BE, LE, 3412-ordered, or 2143-ordered (with a BOM)
  • +
  • +UTF-16 BE or LE (with a BOM)
  • +
  • +UTF-8 (with or without a BOM)
  • +
  • ASCII
  • +
+ + + +
Caution
Due to inherent similarities between certain encodings, some encodings may be detected incorrectly. In my tests, the most problematic case was Hungarian text encoded as ISO-8859-2 or windows-1250 (encoded as one but reported as the other). Also, Greek text encoded as ISO-8859-7 was often mis-reported as ISO-8859-2. Your mileage may vary.
+
+
+ +
+Usage →
+
+
+ +
+ + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/usage.html b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/usage.html new file mode 100644 index 0000000..9dbb8cf --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/docs/usage.html @@ -0,0 +1,107 @@ + + + + +Usage [Universal Encoding Detector] + + + + + + + + + + +
+ +
+
+
+ +
+
+

+ Usage

+
+
+
+
+

+ Basic usage

+
+
+

The easiest way to use the Universal Encoding Detector library is with the detect function.

+
+

Example: Using the detect function

+

The detect function takes one argument, a non-Unicode string. It returns a dictionary containing the auto-detected character encoding and a confidence level from 0 to 1.

+
>>> import urllib
+>>> rawdata = urllib.urlopen('http://yahoo.co.jp/').read()
+>>> import chardet
+>>> chardet.detect(rawdata)
+{'encoding': 'EUC-JP', 'confidence': 0.99}
+
+
+
+
+

+ Advanced usage

+
+
+

If you’re dealing with a large amount of text, you can call the Universal Encoding Detector library incrementally, and it will stop as soon as it is confident enough to report its results.

+

Create a UniversalDetector object, then call its feed method repeatedly with each block of text. If the detector reaches a minimum threshold of confidence, it will set detector.done to True.

+

Once you’ve exhausted the source text, call detector.close(), which will do some final calculations in case the detector didn’t hit its minimum confidence threshold earlier. Then detector.result will be a dictionary containing the auto-detected character encoding and confidence level (the same as the chardet.detect function returns).

+
+

Example: Detecting encoding incrementally

+
import urllib
+from chardet.universaldetector import UniversalDetector
+
+usock = urllib.urlopen('http://yahoo.co.jp/')
+detector = UniversalDetector()
+for line in usock.readlines():
+    detector.feed(line)
+    if detector.done: break
+detector.close()
+usock.close()
+print detector.result
+
{'encoding': 'EUC-JP', 'confidence': 0.99}
+
+

If you want to detect the encoding of multiple texts (such as separate files), you can re-use a single UniversalDetector object. Just call detector.reset() at the start of each file, call detector.feed as many times as you like, and then call detector.close() and check the detector.result dictionary for the file’s results.

+
+

Example: Detecting encodings of multiple files

+
import glob
+from charset.universaldetector import UniversalDetector
+
+detector = UniversalDetector()
+for filename in glob.glob('*.xml'):
+    print filename.ljust(60),
+    detector.reset()
+    for line in file(filename, 'rb'):
+        detector.feed(line)
+        if detector.done: break
+    detector.close()
+    print detector.result
+
+
+
+
+
+ +
+How it works →
+
+
+ +
+ + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/escprober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/escprober.py new file mode 100755 index 0000000..572ed7b --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/escprober.py @@ -0,0 +1,79 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants, sys +from escsm import HZSMModel, ISO2022CNSMModel, ISO2022JPSMModel, ISO2022KRSMModel +from charsetprober import CharSetProber +from codingstatemachine import CodingStateMachine + +class EscCharSetProber(CharSetProber): + def __init__(self): + CharSetProber.__init__(self) + self._mCodingSM = [ \ + CodingStateMachine(HZSMModel), + CodingStateMachine(ISO2022CNSMModel), + CodingStateMachine(ISO2022JPSMModel), + CodingStateMachine(ISO2022KRSMModel) + ] + self.reset() + + def reset(self): + CharSetProber.reset(self) + for codingSM in self._mCodingSM: + if not codingSM: continue + codingSM.active = constants.True + codingSM.reset() + self._mActiveSM = len(self._mCodingSM) + self._mDetectedCharset = None + + def get_charset_name(self): + return self._mDetectedCharset + + def get_confidence(self): + if self._mDetectedCharset: + return 0.99 + else: + return 0.00 + + def feed(self, aBuf): + for c in aBuf: + for codingSM in self._mCodingSM: + if not codingSM: continue + if not codingSM.active: continue + codingState = codingSM.next_state(c) + if codingState == constants.eError: + codingSM.active = constants.False + self._mActiveSM -= 1 + if self._mActiveSM <= 0: + self._mState = constants.eNotMe + return self.get_state() + elif codingState == constants.eItsMe: + self._mState = constants.eFoundIt + self._mDetectedCharset = codingSM.get_coding_state_machine() + return self.get_state() + + return self.get_state() diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/escsm.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/escsm.py new file mode 100755 index 0000000..9fa2295 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/escsm.py @@ -0,0 +1,240 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from constants import eStart, eError, eItsMe + +HZ_cls = ( \ +1,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,0,0,0,0, # 20 - 27 +0,0,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,0,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,4,0,5,2,0, # 78 - 7f +1,1,1,1,1,1,1,1, # 80 - 87 +1,1,1,1,1,1,1,1, # 88 - 8f +1,1,1,1,1,1,1,1, # 90 - 97 +1,1,1,1,1,1,1,1, # 98 - 9f +1,1,1,1,1,1,1,1, # a0 - a7 +1,1,1,1,1,1,1,1, # a8 - af +1,1,1,1,1,1,1,1, # b0 - b7 +1,1,1,1,1,1,1,1, # b8 - bf +1,1,1,1,1,1,1,1, # c0 - c7 +1,1,1,1,1,1,1,1, # c8 - cf +1,1,1,1,1,1,1,1, # d0 - d7 +1,1,1,1,1,1,1,1, # d8 - df +1,1,1,1,1,1,1,1, # e0 - e7 +1,1,1,1,1,1,1,1, # e8 - ef +1,1,1,1,1,1,1,1, # f0 - f7 +1,1,1,1,1,1,1,1, # f8 - ff +) + +HZ_st = ( \ +eStart,eError, 3,eStart,eStart,eStart,eError,eError,# 00-07 +eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,# 08-0f +eItsMe,eItsMe,eError,eError,eStart,eStart, 4,eError,# 10-17 + 5,eError, 6,eError, 5, 5, 4,eError,# 18-1f + 4,eError, 4, 4, 4,eError, 4,eError,# 20-27 + 4,eItsMe,eStart,eStart,eStart,eStart,eStart,eStart,# 28-2f +) + +HZCharLenTable = (0, 0, 0, 0, 0, 0) + +HZSMModel = {'classTable': HZ_cls, + 'classFactor': 6, + 'stateTable': HZ_st, + 'charLenTable': HZCharLenTable, + 'name': "HZ-GB-2312"} + +ISO2022CN_cls = ( \ +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,0,0,0,0, # 20 - 27 +0,3,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,4,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022CN_st = ( \ +eStart, 3,eError,eStart,eStart,eStart,eStart,eStart,# 00-07 +eStart,eError,eError,eError,eError,eError,eError,eError,# 08-0f +eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,# 10-17 +eItsMe,eItsMe,eItsMe,eError,eError,eError, 4,eError,# 18-1f +eError,eError,eError,eItsMe,eError,eError,eError,eError,# 20-27 + 5, 6,eError,eError,eError,eError,eError,eError,# 28-2f +eError,eError,eError,eItsMe,eError,eError,eError,eError,# 30-37 +eError,eError,eError,eError,eError,eItsMe,eError,eStart,# 38-3f +) + +ISO2022CNCharLenTable = (0, 0, 0, 0, 0, 0, 0, 0, 0) + +ISO2022CNSMModel = {'classTable': ISO2022CN_cls, + 'classFactor': 9, + 'stateTable': ISO2022CN_st, + 'charLenTable': ISO2022CNCharLenTable, + 'name': "ISO-2022-CN"} + +ISO2022JP_cls = ( \ +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,2,2, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,7,0,0,0, # 20 - 27 +3,0,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +6,0,4,0,8,0,0,0, # 40 - 47 +0,9,5,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022JP_st = ( \ +eStart, 3,eError,eStart,eStart,eStart,eStart,eStart,# 00-07 +eStart,eStart,eError,eError,eError,eError,eError,eError,# 08-0f +eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,# 10-17 +eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eError,eError,# 18-1f +eError, 5,eError,eError,eError, 4,eError,eError,# 20-27 +eError,eError,eError, 6,eItsMe,eError,eItsMe,eError,# 28-2f +eError,eError,eError,eError,eError,eError,eItsMe,eItsMe,# 30-37 +eError,eError,eError,eItsMe,eError,eError,eError,eError,# 38-3f +eError,eError,eError,eError,eItsMe,eError,eStart,eStart,# 40-47 +) + +ISO2022JPCharLenTable = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + +ISO2022JPSMModel = {'classTable': ISO2022JP_cls, + 'classFactor': 10, + 'stateTable': ISO2022JP_st, + 'charLenTable': ISO2022JPCharLenTable, + 'name': "ISO-2022-JP"} + +ISO2022KR_cls = ( \ +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,3,0,0,0, # 20 - 27 +0,4,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,5,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022KR_st = ( \ +eStart, 3,eError,eStart,eStart,eStart,eError,eError,# 00-07 +eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,# 08-0f +eItsMe,eItsMe,eError,eError,eError, 4,eError,eError,# 10-17 +eError,eError,eError,eError, 5,eError,eError,eError,# 18-1f +eError,eError,eError,eItsMe,eStart,eStart,eStart,eStart,# 20-27 +) + +ISO2022KRCharLenTable = (0, 0, 0, 0, 0, 0) + +ISO2022KRSMModel = {'classTable': ISO2022KR_cls, + 'classFactor': 6, + 'stateTable': ISO2022KR_st, + 'charLenTable': ISO2022KRCharLenTable, + 'name': "ISO-2022-KR"} diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/eucjpprober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/eucjpprober.py new file mode 100755 index 0000000..46a8b38 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/eucjpprober.py @@ -0,0 +1,85 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants, sys +from constants import eStart, eError, eItsMe +from mbcharsetprober import MultiByteCharSetProber +from codingstatemachine import CodingStateMachine +from chardistribution import EUCJPDistributionAnalysis +from jpcntx import EUCJPContextAnalysis +from mbcssm import EUCJPSMModel + +class EUCJPProber(MultiByteCharSetProber): + def __init__(self): + MultiByteCharSetProber.__init__(self) + self._mCodingSM = CodingStateMachine(EUCJPSMModel) + self._mDistributionAnalyzer = EUCJPDistributionAnalysis() + self._mContextAnalyzer = EUCJPContextAnalysis() + self.reset() + + def reset(self): + MultiByteCharSetProber.reset(self) + self._mContextAnalyzer.reset() + + def get_charset_name(self): + return "EUC-JP" + + def feed(self, aBuf): + aLen = len(aBuf) + for i in range(0, aLen): + codingState = self._mCodingSM.next_state(aBuf[i]) + if codingState == eError: + if constants._debug: + sys.stderr.write(self.get_charset_name() + ' prober hit error at byte ' + str(i) + '\n') + self._mState = constants.eNotMe + break + elif codingState == eItsMe: + self._mState = constants.eFoundIt + break + elif codingState == eStart: + charLen = self._mCodingSM.get_current_charlen() + if i == 0: + self._mLastChar[1] = aBuf[0] + self._mContextAnalyzer.feed(self._mLastChar, charLen) + self._mDistributionAnalyzer.feed(self._mLastChar, charLen) + else: + self._mContextAnalyzer.feed(aBuf[i-1:i+1], charLen) + self._mDistributionAnalyzer.feed(aBuf[i-1:i+1], charLen) + + self._mLastChar[0] = aBuf[aLen - 1] + + if self.get_state() == constants.eDetecting: + if self._mContextAnalyzer.got_enough_data() and \ + (self.get_confidence() > constants.SHORTCUT_THRESHOLD): + self._mState = constants.eFoundIt + + return self.get_state() + + def get_confidence(self): + contxtCf = self._mContextAnalyzer.get_confidence() + distribCf = self._mDistributionAnalyzer.get_confidence() + return max(contxtCf, distribCf) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/euckrfreq.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/euckrfreq.py new file mode 100755 index 0000000..1463fa1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/euckrfreq.py @@ -0,0 +1,594 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Sampling from about 20M text materials include literature and computer technology + +# 128 --> 0.79 +# 256 --> 0.92 +# 512 --> 0.986 +# 1024 --> 0.99944 +# 2048 --> 0.99999 +# +# Idea Distribution Ratio = 0.98653 / (1-0.98653) = 73.24 +# Random Distribution Ration = 512 / (2350-512) = 0.279. +# +# Typical Distribution Ratio + +EUCKR_TYPICAL_DISTRIBUTION_RATIO = 6.0 + +EUCKR_TABLE_SIZE = 2352 + +# Char to FreqOrder table , +EUCKRCharToFreqOrder = ( \ + 13, 130, 120,1396, 481,1719,1720, 328, 609, 212,1721, 707, 400, 299,1722, 87, +1397,1723, 104, 536,1117,1203,1724,1267, 685,1268, 508,1725,1726,1727,1728,1398, +1399,1729,1730,1731, 141, 621, 326,1057, 368,1732, 267, 488, 20,1733,1269,1734, + 945,1400,1735, 47, 904,1270,1736,1737, 773, 248,1738, 409, 313, 786, 429,1739, + 116, 987, 813,1401, 683, 75,1204, 145,1740,1741,1742,1743, 16, 847, 667, 622, + 708,1744,1745,1746, 966, 787, 304, 129,1747, 60, 820, 123, 676,1748,1749,1750, +1751, 617,1752, 626,1753,1754,1755,1756, 653,1757,1758,1759,1760,1761,1762, 856, + 344,1763,1764,1765,1766, 89, 401, 418, 806, 905, 848,1767,1768,1769, 946,1205, + 709,1770,1118,1771, 241,1772,1773,1774,1271,1775, 569,1776, 999,1777,1778,1779, +1780, 337, 751,1058, 28, 628, 254,1781, 177, 906, 270, 349, 891,1079,1782, 19, +1783, 379,1784, 315,1785, 629, 754,1402, 559,1786, 636, 203,1206,1787, 710, 567, +1788, 935, 814,1789,1790,1207, 766, 528,1791,1792,1208,1793,1794,1795,1796,1797, +1403,1798,1799, 533,1059,1404,1405,1156,1406, 936, 884,1080,1800, 351,1801,1802, +1803,1804,1805, 801,1806,1807,1808,1119,1809,1157, 714, 474,1407,1810, 298, 899, + 885,1811,1120, 802,1158,1812, 892,1813,1814,1408, 659,1815,1816,1121,1817,1818, +1819,1820,1821,1822, 319,1823, 594, 545,1824, 815, 937,1209,1825,1826, 573,1409, +1022,1827,1210,1828,1829,1830,1831,1832,1833, 556, 722, 807,1122,1060,1834, 697, +1835, 900, 557, 715,1836,1410, 540,1411, 752,1159, 294, 597,1211, 976, 803, 770, +1412,1837,1838, 39, 794,1413, 358,1839, 371, 925,1840, 453, 661, 788, 531, 723, + 544,1023,1081, 869, 91,1841, 392, 430, 790, 602,1414, 677,1082, 457,1415,1416, +1842,1843, 475, 327,1024,1417, 795, 121,1844, 733, 403,1418,1845,1846,1847, 300, + 119, 711,1212, 627,1848,1272, 207,1849,1850, 796,1213, 382,1851, 519,1852,1083, + 893,1853,1854,1855, 367, 809, 487, 671,1856, 663,1857,1858, 956, 471, 306, 857, +1859,1860,1160,1084,1861,1862,1863,1864,1865,1061,1866,1867,1868,1869,1870,1871, + 282, 96, 574,1872, 502,1085,1873,1214,1874, 907,1875,1876, 827, 977,1419,1420, +1421, 268,1877,1422,1878,1879,1880, 308,1881, 2, 537,1882,1883,1215,1884,1885, + 127, 791,1886,1273,1423,1887, 34, 336, 404, 643,1888, 571, 654, 894, 840,1889, + 0, 886,1274, 122, 575, 260, 908, 938,1890,1275, 410, 316,1891,1892, 100,1893, +1894,1123, 48,1161,1124,1025,1895, 633, 901,1276,1896,1897, 115, 816,1898, 317, +1899, 694,1900, 909, 734,1424, 572, 866,1425, 691, 85, 524,1010, 543, 394, 841, +1901,1902,1903,1026,1904,1905,1906,1907,1908,1909, 30, 451, 651, 988, 310,1910, +1911,1426, 810,1216, 93,1912,1913,1277,1217,1914, 858, 759, 45, 58, 181, 610, + 269,1915,1916, 131,1062, 551, 443,1000, 821,1427, 957, 895,1086,1917,1918, 375, +1919, 359,1920, 687,1921, 822,1922, 293,1923,1924, 40, 662, 118, 692, 29, 939, + 887, 640, 482, 174,1925, 69,1162, 728,1428, 910,1926,1278,1218,1279, 386, 870, + 217, 854,1163, 823,1927,1928,1929,1930, 834,1931, 78,1932, 859,1933,1063,1934, +1935,1936,1937, 438,1164, 208, 595,1938,1939,1940,1941,1219,1125,1942, 280, 888, +1429,1430,1220,1431,1943,1944,1945,1946,1947,1280, 150, 510,1432,1948,1949,1950, +1951,1952,1953,1954,1011,1087,1955,1433,1043,1956, 881,1957, 614, 958,1064,1065, +1221,1958, 638,1001, 860, 967, 896,1434, 989, 492, 553,1281,1165,1959,1282,1002, +1283,1222,1960,1961,1962,1963, 36, 383, 228, 753, 247, 454,1964, 876, 678,1965, +1966,1284, 126, 464, 490, 835, 136, 672, 529, 940,1088,1435, 473,1967,1968, 467, + 50, 390, 227, 587, 279, 378, 598, 792, 968, 240, 151, 160, 849, 882,1126,1285, + 639,1044, 133, 140, 288, 360, 811, 563,1027, 561, 142, 523,1969,1970,1971, 7, + 103, 296, 439, 407, 506, 634, 990,1972,1973,1974,1975, 645,1976,1977,1978,1979, +1980,1981, 236,1982,1436,1983,1984,1089, 192, 828, 618, 518,1166, 333,1127,1985, + 818,1223,1986,1987,1988,1989,1990,1991,1992,1993, 342,1128,1286, 746, 842,1994, +1995, 560, 223,1287, 98, 8, 189, 650, 978,1288,1996,1437,1997, 17, 345, 250, + 423, 277, 234, 512, 226, 97, 289, 42, 167,1998, 201,1999,2000, 843, 836, 824, + 532, 338, 783,1090, 182, 576, 436,1438,1439, 527, 500,2001, 947, 889,2002,2003, +2004,2005, 262, 600, 314, 447,2006, 547,2007, 693, 738,1129,2008, 71,1440, 745, + 619, 688,2009, 829,2010,2011, 147,2012, 33, 948,2013,2014, 74, 224,2015, 61, + 191, 918, 399, 637,2016,1028,1130, 257, 902,2017,2018,2019,2020,2021,2022,2023, +2024,2025,2026, 837,2027,2028,2029,2030, 179, 874, 591, 52, 724, 246,2031,2032, +2033,2034,1167, 969,2035,1289, 630, 605, 911,1091,1168,2036,2037,2038,1441, 912, +2039, 623,2040,2041, 253,1169,1290,2042,1442, 146, 620, 611, 577, 433,2043,1224, + 719,1170, 959, 440, 437, 534, 84, 388, 480,1131, 159, 220, 198, 679,2044,1012, + 819,1066,1443, 113,1225, 194, 318,1003,1029,2045,2046,2047,2048,1067,2049,2050, +2051,2052,2053, 59, 913, 112,2054, 632,2055, 455, 144, 739,1291,2056, 273, 681, + 499,2057, 448,2058,2059, 760,2060,2061, 970, 384, 169, 245,1132,2062,2063, 414, +1444,2064,2065, 41, 235,2066, 157, 252, 877, 568, 919, 789, 580,2067, 725,2068, +2069,1292,2070,2071,1445,2072,1446,2073,2074, 55, 588, 66,1447, 271,1092,2075, +1226,2076, 960,1013, 372,2077,2078,2079,2080,2081,1293,2082,2083,2084,2085, 850, +2086,2087,2088,2089,2090, 186,2091,1068, 180,2092,2093,2094, 109,1227, 522, 606, +2095, 867,1448,1093, 991,1171, 926, 353,1133,2096, 581,2097,2098,2099,1294,1449, +1450,2100, 596,1172,1014,1228,2101,1451,1295,1173,1229,2102,2103,1296,1134,1452, + 949,1135,2104,2105,1094,1453,1454,1455,2106,1095,2107,2108,2109,2110,2111,2112, +2113,2114,2115,2116,2117, 804,2118,2119,1230,1231, 805,1456, 405,1136,2120,2121, +2122,2123,2124, 720, 701,1297, 992,1457, 927,1004,2125,2126,2127,2128,2129,2130, + 22, 417,2131, 303,2132, 385,2133, 971, 520, 513,2134,1174, 73,1096, 231, 274, + 962,1458, 673,2135,1459,2136, 152,1137,2137,2138,2139,2140,1005,1138,1460,1139, +2141,2142,2143,2144, 11, 374, 844,2145, 154,1232, 46,1461,2146, 838, 830, 721, +1233, 106,2147, 90, 428, 462, 578, 566,1175, 352,2148,2149, 538,1234, 124,1298, +2150,1462, 761, 565,2151, 686,2152, 649,2153, 72, 173,2154, 460, 415,2155,1463, +2156,1235, 305,2157,2158,2159,2160,2161,2162, 579,2163,2164,2165,2166,2167, 747, +2168,2169,2170,2171,1464, 669,2172,2173,2174,2175,2176,1465,2177, 23, 530, 285, +2178, 335, 729,2179, 397,2180,2181,2182,1030,2183,2184, 698,2185,2186, 325,2187, +2188, 369,2189, 799,1097,1015, 348,2190,1069, 680,2191, 851,1466,2192,2193, 10, +2194, 613, 424,2195, 979, 108, 449, 589, 27, 172, 81,1031, 80, 774, 281, 350, +1032, 525, 301, 582,1176,2196, 674,1045,2197,2198,1467, 730, 762,2199,2200,2201, +2202,1468,2203, 993,2204,2205, 266,1070, 963,1140,2206,2207,2208, 664,1098, 972, +2209,2210,2211,1177,1469,1470, 871,2212,2213,2214,2215,2216,1471,2217,2218,2219, +2220,2221,2222,2223,2224,2225,2226,2227,1472,1236,2228,2229,2230,2231,2232,2233, +2234,2235,1299,2236,2237, 200,2238, 477, 373,2239,2240, 731, 825, 777,2241,2242, +2243, 521, 486, 548,2244,2245,2246,1473,1300, 53, 549, 137, 875, 76, 158,2247, +1301,1474, 469, 396,1016, 278, 712,2248, 321, 442, 503, 767, 744, 941,1237,1178, +1475,2249, 82, 178,1141,1179, 973,2250,1302,2251, 297,2252,2253, 570,2254,2255, +2256, 18, 450, 206,2257, 290, 292,1142,2258, 511, 162, 99, 346, 164, 735,2259, +1476,1477, 4, 554, 343, 798,1099,2260,1100,2261, 43, 171,1303, 139, 215,2262, +2263, 717, 775,2264,1033, 322, 216,2265, 831,2266, 149,2267,1304,2268,2269, 702, +1238, 135, 845, 347, 309,2270, 484,2271, 878, 655, 238,1006,1478,2272, 67,2273, + 295,2274,2275, 461,2276, 478, 942, 412,2277,1034,2278,2279,2280, 265,2281, 541, +2282,2283,2284,2285,2286, 70, 852,1071,2287,2288,2289,2290, 21, 56, 509, 117, + 432,2291,2292, 331, 980, 552,1101, 148, 284, 105, 393,1180,1239, 755,2293, 187, +2294,1046,1479,2295, 340,2296, 63,1047, 230,2297,2298,1305, 763,1306, 101, 800, + 808, 494,2299,2300,2301, 903,2302, 37,1072, 14, 5,2303, 79, 675,2304, 312, +2305,2306,2307,2308,2309,1480, 6,1307,2310,2311,2312, 1, 470, 35, 24, 229, +2313, 695, 210, 86, 778, 15, 784, 592, 779, 32, 77, 855, 964,2314, 259,2315, + 501, 380,2316,2317, 83, 981, 153, 689,1308,1481,1482,1483,2318,2319, 716,1484, +2320,2321,2322,2323,2324,2325,1485,2326,2327, 128, 57, 68, 261,1048, 211, 170, +1240, 31,2328, 51, 435, 742,2329,2330,2331, 635,2332, 264, 456,2333,2334,2335, + 425,2336,1486, 143, 507, 263, 943,2337, 363, 920,1487, 256,1488,1102, 243, 601, +1489,2338,2339,2340,2341,2342,2343,2344, 861,2345,2346,2347,2348,2349,2350, 395, +2351,1490,1491, 62, 535, 166, 225,2352,2353, 668, 419,1241, 138, 604, 928,2354, +1181,2355,1492,1493,2356,2357,2358,1143,2359, 696,2360, 387, 307,1309, 682, 476, +2361,2362, 332, 12, 222, 156,2363, 232,2364, 641, 276, 656, 517,1494,1495,1035, + 416, 736,1496,2365,1017, 586,2366,2367,2368,1497,2369, 242,2370,2371,2372,1498, +2373, 965, 713,2374,2375,2376,2377, 740, 982,1499, 944,1500,1007,2378,2379,1310, +1501,2380,2381,2382, 785, 329,2383,2384,1502,2385,2386,2387, 932,2388,1503,2389, +2390,2391,2392,1242,2393,2394,2395,2396,2397, 994, 950,2398,2399,2400,2401,1504, +1311,2402,2403,2404,2405,1049, 749,2406,2407, 853, 718,1144,1312,2408,1182,1505, +2409,2410, 255, 516, 479, 564, 550, 214,1506,1507,1313, 413, 239, 444, 339,1145, +1036,1508,1509,1314,1037,1510,1315,2411,1511,2412,2413,2414, 176, 703, 497, 624, + 593, 921, 302,2415, 341, 165,1103,1512,2416,1513,2417,2418,2419, 376,2420, 700, +2421,2422,2423, 258, 768,1316,2424,1183,2425, 995, 608,2426,2427,2428,2429, 221, +2430,2431,2432,2433,2434,2435,2436,2437, 195, 323, 726, 188, 897, 983,1317, 377, + 644,1050, 879,2438, 452,2439,2440,2441,2442,2443,2444, 914,2445,2446,2447,2448, + 915, 489,2449,1514,1184,2450,2451, 515, 64, 427, 495,2452, 583,2453, 483, 485, +1038, 562, 213,1515, 748, 666,2454,2455,2456,2457, 334,2458, 780, 996,1008, 705, +1243,2459,2460,2461,2462,2463, 114,2464, 493,1146, 366, 163,1516, 961,1104,2465, + 291,2466,1318,1105,2467,1517, 365,2468, 355, 951,1244,2469,1319,2470, 631,2471, +2472, 218,1320, 364, 320, 756,1518,1519,1321,1520,1322,2473,2474,2475,2476, 997, +2477,2478,2479,2480, 665,1185,2481, 916,1521,2482,2483,2484, 584, 684,2485,2486, + 797,2487,1051,1186,2488,2489,2490,1522,2491,2492, 370,2493,1039,1187, 65,2494, + 434, 205, 463,1188,2495, 125, 812, 391, 402, 826, 699, 286, 398, 155, 781, 771, + 585,2496, 590, 505,1073,2497, 599, 244, 219, 917,1018, 952, 646,1523,2498,1323, +2499,2500, 49, 984, 354, 741,2501, 625,2502,1324,2503,1019, 190, 357, 757, 491, + 95, 782, 868,2504,2505,2506,2507,2508,2509, 134,1524,1074, 422,1525, 898,2510, + 161,2511,2512,2513,2514, 769,2515,1526,2516,2517, 411,1325,2518, 472,1527,2519, +2520,2521,2522,2523,2524, 985,2525,2526,2527,2528,2529,2530, 764,2531,1245,2532, +2533, 25, 204, 311,2534, 496,2535,1052,2536,2537,2538,2539,2540,2541,2542, 199, + 704, 504, 468, 758, 657,1528, 196, 44, 839,1246, 272, 750,2543, 765, 862,2544, +2545,1326,2546, 132, 615, 933,2547, 732,2548,2549,2550,1189,1529,2551, 283,1247, +1053, 607, 929,2552,2553,2554, 930, 183, 872, 616,1040,1147,2555,1148,1020, 441, + 249,1075,2556,2557,2558, 466, 743,2559,2560,2561, 92, 514, 426, 420, 526,2562, +2563,2564,2565,2566,2567,2568, 185,2569,2570,2571,2572, 776,1530, 658,2573, 362, +2574, 361, 922,1076, 793,2575,2576,2577,2578,2579,2580,1531, 251,2581,2582,2583, +2584,1532, 54, 612, 237,1327,2585,2586, 275, 408, 647, 111,2587,1533,1106, 465, + 3, 458, 9, 38,2588, 107, 110, 890, 209, 26, 737, 498,2589,1534,2590, 431, + 202, 88,1535, 356, 287,1107, 660,1149,2591, 381,1536, 986,1150, 445,1248,1151, + 974,2592,2593, 846,2594, 446, 953, 184,1249,1250, 727,2595, 923, 193, 883,2596, +2597,2598, 102, 324, 539, 817,2599, 421,1041,2600, 832,2601, 94, 175, 197, 406, +2602, 459,2603,2604,2605,2606,2607, 330, 555,2608,2609,2610, 706,1108, 389,2611, +2612,2613,2614, 233,2615, 833, 558, 931, 954,1251,2616,2617,1537, 546,2618,2619, +1009,2620,2621,2622,1538, 690,1328,2623, 955,2624,1539,2625,2626, 772,2627,2628, +2629,2630,2631, 924, 648, 863, 603,2632,2633, 934,1540, 864, 865,2634, 642,1042, + 670,1190,2635,2636,2637,2638, 168,2639, 652, 873, 542,1054,1541,2640,2641,2642, # 512, 256 +#Everything below is of no interest for detection purpose +2643,2644,2645,2646,2647,2648,2649,2650,2651,2652,2653,2654,2655,2656,2657,2658, +2659,2660,2661,2662,2663,2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2674, +2675,2676,2677,2678,2679,2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690, +2691,2692,2693,2694,2695,2696,2697,2698,2699,1542, 880,2700,2701,2702,2703,2704, +2705,2706,2707,2708,2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720, +2721,2722,2723,2724,2725,1543,2726,2727,2728,2729,2730,2731,2732,1544,2733,2734, +2735,2736,2737,2738,2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750, +2751,2752,2753,2754,1545,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765, +2766,1546,2767,1547,2768,2769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779, +2780,2781,2782,2783,2784,2785,2786,1548,2787,2788,2789,1109,2790,2791,2792,2793, +2794,2795,2796,2797,2798,2799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809, +2810,2811,2812,1329,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824, +2825,2826,2827,2828,2829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840, +2841,2842,2843,2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856, +1549,2857,2858,2859,2860,1550,2861,2862,1551,2863,2864,2865,2866,2867,2868,2869, +2870,2871,2872,2873,2874,1110,1330,2875,2876,2877,2878,2879,2880,2881,2882,2883, +2884,2885,2886,2887,2888,2889,2890,2891,2892,2893,2894,2895,2896,2897,2898,2899, +2900,2901,2902,2903,2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915, +2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,1331, +2931,2932,2933,2934,2935,2936,2937,2938,2939,2940,2941,2942,2943,1552,2944,2945, +2946,2947,2948,2949,2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961, +2962,2963,2964,1252,2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976, +2977,2978,2979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992, +2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008, +3009,3010,3011,3012,1553,3013,3014,3015,3016,3017,1554,3018,1332,3019,3020,3021, +3022,3023,3024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037, +3038,3039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,1555,3051,3052, +3053,1556,1557,3054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066, +3067,1558,3068,3069,3070,3071,3072,3073,3074,3075,3076,1559,3077,3078,3079,3080, +3081,3082,3083,1253,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095, +3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,1152,3109,3110, +3111,3112,3113,1560,3114,3115,3116,3117,1111,3118,3119,3120,3121,3122,3123,3124, +3125,3126,3127,3128,3129,3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140, +3141,3142,3143,3144,3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156, +3157,3158,3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172, +3173,3174,3175,3176,1333,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187, +3188,3189,1561,3190,3191,1334,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201, +3202,3203,3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217, +3218,3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233, +3234,1562,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248, +3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264, +3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,1563,3278,3279, +3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,3295, +3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311, +3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,3325,3326,3327, +3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,3340,3341,3342,3343, +3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,3359, +3360,3361,3362,3363,3364,1335,3365,3366,3367,3368,3369,3370,3371,3372,3373,3374, +3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387,1336,3388,3389, +3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,3401,3402,3403,3404,3405, +3406,3407,3408,3409,3410,3411,3412,3413,3414,1337,3415,3416,3417,3418,3419,1338, +3420,3421,3422,1564,1565,3423,3424,3425,3426,3427,3428,3429,3430,3431,1254,3432, +3433,3434,1339,3435,3436,3437,3438,3439,1566,3440,3441,3442,3443,3444,3445,3446, +3447,3448,3449,3450,3451,3452,3453,3454,1255,3455,3456,3457,3458,3459,1567,1191, +3460,1568,1569,3461,3462,3463,1570,3464,3465,3466,3467,3468,1571,3469,3470,3471, +3472,3473,1572,3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486, +1340,3487,3488,3489,3490,3491,3492,1021,3493,3494,3495,3496,3497,3498,1573,3499, +1341,3500,3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511,1342,3512,3513, +3514,3515,3516,1574,1343,3517,3518,3519,1575,3520,1576,3521,3522,3523,3524,3525, +3526,3527,3528,3529,3530,3531,3532,3533,3534,3535,3536,3537,3538,3539,3540,3541, +3542,3543,3544,3545,3546,3547,3548,3549,3550,3551,3552,3553,3554,3555,3556,3557, +3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,3569,3570,3571,3572,3573, +3574,3575,3576,3577,3578,3579,3580,1577,3581,3582,1578,3583,3584,3585,3586,3587, +3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603, +3604,1579,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618, +3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,1580,3630,3631,1581,3632, +3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,3644,3645,3646,3647,3648, +3649,3650,3651,3652,3653,3654,3655,3656,1582,3657,3658,3659,3660,3661,3662,3663, +3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,3676,3677,3678,3679, +3680,3681,3682,3683,3684,3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695, +3696,3697,3698,3699,3700,1192,3701,3702,3703,3704,1256,3705,3706,3707,3708,1583, +1257,3709,3710,3711,3712,3713,3714,3715,3716,1584,3717,3718,3719,3720,3721,3722, +3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737,3738, +3739,3740,3741,3742,3743,3744,3745,1344,3746,3747,3748,3749,3750,3751,3752,3753, +3754,3755,3756,1585,3757,3758,3759,3760,3761,3762,3763,3764,3765,3766,1586,3767, +3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,1345,3779,3780,3781,3782, +3783,3784,3785,3786,3787,3788,3789,3790,3791,3792,3793,3794,3795,1346,1587,3796, +3797,1588,3798,3799,3800,3801,3802,3803,3804,3805,3806,1347,3807,3808,3809,3810, +3811,1589,3812,3813,3814,3815,3816,3817,3818,3819,3820,3821,1590,3822,3823,1591, +1348,3824,3825,3826,3827,3828,3829,3830,1592,3831,3832,1593,3833,3834,3835,3836, +3837,3838,3839,3840,3841,3842,3843,3844,1349,3845,3846,3847,3848,3849,3850,3851, +3852,3853,3854,3855,3856,3857,3858,1594,3859,3860,3861,3862,3863,3864,3865,3866, +3867,3868,3869,1595,3870,3871,3872,3873,1596,3874,3875,3876,3877,3878,3879,3880, +3881,3882,3883,3884,3885,3886,1597,3887,3888,3889,3890,3891,3892,3893,3894,3895, +1598,3896,3897,3898,1599,1600,3899,1350,3900,1351,3901,3902,1352,3903,3904,3905, +3906,3907,3908,3909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921, +3922,3923,3924,1258,3925,3926,3927,3928,3929,3930,3931,1193,3932,1601,3933,3934, +3935,3936,3937,3938,3939,3940,3941,3942,3943,1602,3944,3945,3946,3947,3948,1603, +3949,3950,3951,3952,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964, +3965,1604,3966,3967,3968,3969,3970,3971,3972,3973,3974,3975,3976,3977,1353,3978, +3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990,3991,1354,3992,3993, +3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009, +4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,1355,4024, +4025,4026,4027,4028,4029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040, +1605,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055, +4056,4057,4058,4059,4060,1606,4061,4062,4063,4064,1607,4065,4066,4067,4068,4069, +4070,4071,4072,4073,4074,4075,4076,1194,4077,4078,1608,4079,4080,4081,4082,4083, +4084,4085,4086,4087,1609,4088,4089,4090,4091,4092,4093,4094,4095,4096,4097,4098, +4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,1259,4109,4110,4111,4112,4113, +4114,4115,4116,4117,4118,4119,4120,4121,4122,4123,4124,1195,4125,4126,4127,1610, +4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,1356,4138,4139,4140,4141,4142, +4143,4144,1611,4145,4146,4147,4148,4149,4150,4151,4152,4153,4154,4155,4156,4157, +4158,4159,4160,4161,4162,4163,4164,4165,4166,4167,4168,4169,4170,4171,4172,4173, +4174,4175,4176,4177,4178,4179,4180,4181,4182,4183,4184,4185,4186,4187,4188,4189, +4190,4191,4192,4193,4194,4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205, +4206,4207,4208,4209,4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,1612,4220, +4221,4222,4223,4224,4225,4226,4227,1357,4228,1613,4229,4230,4231,4232,4233,4234, +4235,4236,4237,4238,4239,4240,4241,4242,4243,1614,4244,4245,4246,4247,4248,4249, +4250,4251,4252,4253,4254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265, +4266,4267,4268,4269,4270,1196,1358,4271,4272,4273,4274,4275,4276,4277,4278,4279, +4280,4281,4282,4283,4284,4285,4286,4287,1615,4288,4289,4290,4291,4292,4293,4294, +4295,4296,4297,4298,4299,4300,4301,4302,4303,4304,4305,4306,4307,4308,4309,4310, +4311,4312,4313,4314,4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326, +4327,4328,4329,4330,4331,4332,4333,4334,1616,4335,4336,4337,4338,4339,4340,4341, +4342,4343,4344,4345,4346,4347,4348,4349,4350,4351,4352,4353,4354,4355,4356,4357, +4358,4359,4360,1617,4361,4362,4363,4364,4365,1618,4366,4367,4368,4369,4370,4371, +4372,4373,4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387, +4388,4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403, +4404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,1619,4417,4418, +4419,4420,4421,4422,4423,4424,4425,1112,4426,4427,4428,4429,4430,1620,4431,4432, +4433,4434,4435,4436,4437,4438,4439,4440,4441,4442,1260,1261,4443,4444,4445,4446, +4447,4448,4449,4450,4451,4452,4453,4454,4455,1359,4456,4457,4458,4459,4460,4461, +4462,4463,4464,4465,1621,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476, +4477,4478,4479,4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,1055,4490,4491, +4492,4493,4494,4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507, +4508,4509,4510,4511,4512,4513,4514,4515,4516,4517,4518,1622,4519,4520,4521,1623, +4522,4523,4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,1360,4536, +4537,4538,4539,4540,4541,4542,4543, 975,4544,4545,4546,4547,4548,4549,4550,4551, +4552,4553,4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567, +4568,4569,4570,4571,1624,4572,4573,4574,4575,4576,1625,4577,4578,4579,4580,4581, +4582,4583,4584,1626,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,1627, +4596,4597,4598,4599,4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611, +4612,4613,4614,4615,1628,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626, +4627,4628,4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642, +4643,4644,4645,4646,4647,4648,4649,1361,4650,4651,4652,4653,4654,4655,4656,4657, +4658,4659,4660,4661,1362,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672, +4673,4674,4675,4676,4677,4678,4679,4680,4681,4682,1629,4683,4684,4685,4686,4687, +1630,4688,4689,4690,4691,1153,4692,4693,4694,1113,4695,4696,4697,4698,4699,4700, +4701,4702,4703,4704,4705,4706,4707,4708,4709,4710,4711,1197,4712,4713,4714,4715, +4716,4717,4718,4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731, +4732,4733,4734,4735,1631,4736,1632,4737,4738,4739,4740,4741,4742,4743,4744,1633, +4745,4746,4747,4748,4749,1262,4750,4751,4752,4753,4754,1363,4755,4756,4757,4758, +4759,4760,4761,4762,4763,4764,4765,4766,4767,4768,1634,4769,4770,4771,4772,4773, +4774,4775,4776,4777,4778,1635,4779,4780,4781,4782,4783,4784,4785,4786,4787,4788, +4789,1636,4790,4791,4792,4793,4794,4795,4796,4797,4798,4799,4800,4801,4802,4803, +4804,4805,4806,1637,4807,4808,4809,1638,4810,4811,4812,4813,4814,4815,4816,4817, +4818,1639,4819,4820,4821,4822,4823,4824,4825,4826,4827,4828,4829,4830,4831,4832, +4833,1077,4834,4835,4836,4837,4838,4839,4840,4841,4842,4843,4844,4845,4846,4847, +4848,4849,4850,4851,4852,4853,4854,4855,4856,4857,4858,4859,4860,4861,4862,4863, +4864,4865,4866,4867,4868,4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879, +4880,4881,4882,4883,1640,4884,4885,1641,4886,4887,4888,4889,4890,4891,4892,4893, +4894,4895,4896,4897,4898,4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909, +4910,4911,1642,4912,4913,4914,1364,4915,4916,4917,4918,4919,4920,4921,4922,4923, +4924,4925,4926,4927,4928,4929,4930,4931,1643,4932,4933,4934,4935,4936,4937,4938, +4939,4940,4941,4942,4943,4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954, +4955,4956,4957,4958,4959,4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970, +4971,4972,4973,4974,4975,4976,4977,4978,4979,4980,1644,4981,4982,4983,4984,1645, +4985,4986,1646,4987,4988,4989,4990,4991,4992,4993,4994,4995,4996,4997,4998,4999, +5000,5001,5002,5003,5004,5005,1647,5006,1648,5007,5008,5009,5010,5011,5012,1078, +5013,5014,5015,5016,5017,5018,5019,5020,5021,5022,5023,5024,5025,5026,5027,5028, +1365,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,1649,5040,5041,5042, +5043,5044,5045,1366,5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,1650,5056, +5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072, +5073,5074,5075,5076,5077,1651,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087, +5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103, +5104,5105,5106,5107,5108,5109,5110,1652,5111,5112,5113,5114,5115,5116,5117,5118, +1367,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,1653,5130,5131,5132, +5133,5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148, +5149,1368,5150,1654,5151,1369,5152,5153,5154,5155,5156,5157,5158,5159,5160,5161, +5162,5163,5164,5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,5176,5177, +5178,1370,5179,5180,5181,5182,5183,5184,5185,5186,5187,5188,5189,5190,5191,5192, +5193,5194,5195,5196,5197,5198,1655,5199,5200,5201,5202,1656,5203,5204,5205,5206, +1371,5207,1372,5208,5209,5210,5211,1373,5212,5213,1374,5214,5215,5216,5217,5218, +5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234, +5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,5247,1657,5248,5249, +5250,5251,1658,1263,5252,5253,5254,5255,5256,1375,5257,5258,5259,5260,5261,5262, +5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278, +5279,5280,5281,5282,5283,1659,5284,5285,5286,5287,5288,5289,5290,5291,5292,5293, +5294,5295,5296,5297,5298,5299,5300,1660,5301,5302,5303,5304,5305,5306,5307,5308, +5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,1376,5322,5323, +5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,1198,5334,5335,5336,5337,5338, +5339,5340,5341,5342,5343,1661,5344,5345,5346,5347,5348,5349,5350,5351,5352,5353, +5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368,5369, +5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,5380,5381,5382,5383,5384,5385, +5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,5397,5398,1264,5399,5400, +5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,5411,5412,1662,5413,5414,5415, +5416,1663,5417,5418,5419,5420,5421,5422,5423,5424,5425,5426,5427,5428,5429,5430, +5431,5432,5433,5434,5435,5436,5437,5438,1664,5439,5440,5441,5442,5443,5444,5445, +5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456,5457,5458,5459,5460,5461, +5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472,5473,5474,5475,5476,5477, +5478,1154,5479,5480,5481,5482,5483,5484,5485,1665,5486,5487,5488,5489,5490,5491, +5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504,5505,5506,5507, +5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520,5521,5522,5523, +5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539, +5540,5541,5542,5543,5544,5545,5546,5547,5548,1377,5549,5550,5551,5552,5553,5554, +5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570, +1114,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585, +5586,5587,5588,5589,5590,5591,5592,1378,5593,5594,5595,5596,5597,5598,5599,5600, +5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,1379,5615, +5616,5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631, +5632,5633,5634,1380,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646, +5647,5648,5649,1381,1056,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660, +1666,5661,5662,5663,5664,5665,5666,5667,5668,1667,5669,1668,5670,5671,5672,5673, +5674,5675,5676,5677,5678,1155,5679,5680,5681,5682,5683,5684,5685,5686,5687,5688, +5689,5690,5691,5692,5693,5694,5695,5696,5697,5698,1669,5699,5700,5701,5702,5703, +5704,5705,1670,5706,5707,5708,5709,5710,1671,5711,5712,5713,5714,1382,5715,5716, +5717,5718,5719,5720,5721,5722,5723,5724,5725,1672,5726,5727,1673,1674,5728,5729, +5730,5731,5732,5733,5734,5735,5736,1675,5737,5738,5739,5740,5741,5742,5743,5744, +1676,5745,5746,5747,5748,5749,5750,5751,1383,5752,5753,5754,5755,5756,5757,5758, +5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,1677,5769,5770,5771,5772,5773, +1678,5774,5775,5776, 998,5777,5778,5779,5780,5781,5782,5783,5784,5785,1384,5786, +5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,5799,5800,1679,5801, +5802,5803,1115,1116,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,5815, +5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,5829,5830,5831, +5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,5845,5846,5847, +5848,5849,5850,5851,5852,5853,5854,5855,1680,5856,5857,5858,5859,5860,5861,5862, +5863,5864,1681,5865,5866,5867,1682,5868,5869,5870,5871,5872,5873,5874,5875,5876, +5877,5878,5879,1683,5880,1684,5881,5882,5883,5884,1685,5885,5886,5887,5888,5889, +5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,5905, +5906,5907,1686,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920, +5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,1687, +5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951, +5952,1688,1689,5953,1199,5954,5955,5956,5957,5958,5959,5960,5961,1690,5962,5963, +5964,5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979, +5980,5981,1385,5982,1386,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993, +5994,5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009, +6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,6024,6025, +6026,6027,1265,6028,6029,1691,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039, +6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,6055, +6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,6069,6070,6071, +6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,1692,6085,6086, +6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6100,6101,6102, +6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,6115,6116,6117,6118, +6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,6130,6131,1693,6132,6133, +6134,6135,6136,1694,6137,6138,6139,6140,6141,1695,6142,6143,6144,6145,6146,6147, +6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,6160,6161,6162,6163, +6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,6175,6176,6177,6178,6179, +6180,6181,6182,6183,6184,6185,1696,6186,6187,6188,6189,6190,6191,6192,6193,6194, +6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,6205,6206,6207,6208,6209,6210, +6211,6212,6213,6214,6215,6216,6217,6218,6219,1697,6220,6221,6222,6223,6224,6225, +6226,6227,6228,6229,6230,6231,6232,6233,6234,6235,6236,6237,6238,6239,6240,6241, +6242,6243,6244,6245,6246,6247,6248,6249,6250,6251,6252,6253,1698,6254,6255,6256, +6257,6258,6259,6260,6261,6262,6263,1200,6264,6265,6266,6267,6268,6269,6270,6271, #1024 +6272,6273,6274,6275,6276,6277,6278,6279,6280,6281,6282,6283,6284,6285,6286,6287, +6288,6289,6290,6291,6292,6293,6294,6295,6296,6297,6298,6299,6300,6301,6302,1699, +6303,6304,1700,6305,6306,6307,6308,6309,6310,6311,6312,6313,6314,6315,6316,6317, +6318,6319,6320,6321,6322,6323,6324,6325,6326,6327,6328,6329,6330,6331,6332,6333, +6334,6335,6336,6337,6338,6339,1701,6340,6341,6342,6343,6344,1387,6345,6346,6347, +6348,6349,6350,6351,6352,6353,6354,6355,6356,6357,6358,6359,6360,6361,6362,6363, +6364,6365,6366,6367,6368,6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379, +6380,6381,6382,6383,6384,6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395, +6396,6397,6398,6399,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411, +6412,6413,1702,6414,6415,6416,6417,6418,6419,6420,6421,6422,1703,6423,6424,6425, +6426,6427,6428,6429,6430,6431,6432,6433,6434,6435,6436,6437,6438,1704,6439,6440, +6441,6442,6443,6444,6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456, +6457,6458,6459,6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472, +6473,6474,6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488, +6489,6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,1266, +6504,6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,6519, +6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,6534,6535, +6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,6550,6551, +1705,1706,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,6565, +6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,6579,6580,6581, +6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,6594,6595,6596,6597, +6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,6609,6610,6611,6612,6613, +6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,6624,6625,6626,6627,6628,6629, +6630,6631,6632,6633,6634,6635,6636,6637,1388,6638,6639,6640,6641,6642,6643,6644, +1707,6645,6646,6647,6648,6649,6650,6651,6652,6653,6654,6655,6656,6657,6658,6659, +6660,6661,6662,6663,1708,6664,6665,6666,6667,6668,6669,6670,6671,6672,6673,6674, +1201,6675,6676,6677,6678,6679,6680,6681,6682,6683,6684,6685,6686,6687,6688,6689, +6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,6700,6701,6702,6703,6704,6705, +6706,6707,6708,6709,6710,6711,6712,6713,6714,6715,6716,6717,6718,6719,6720,6721, +6722,6723,6724,6725,1389,6726,6727,6728,6729,6730,6731,6732,6733,6734,6735,6736, +1390,1709,6737,6738,6739,6740,6741,6742,1710,6743,6744,6745,6746,1391,6747,6748, +6749,6750,6751,6752,6753,6754,6755,6756,6757,1392,6758,6759,6760,6761,6762,6763, +6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777,6778,6779, +6780,1202,6781,6782,6783,6784,6785,6786,6787,6788,6789,6790,6791,6792,6793,6794, +6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,6805,6806,6807,6808,6809,1711, +6810,6811,6812,6813,6814,6815,6816,6817,6818,6819,6820,6821,6822,6823,6824,6825, +6826,6827,6828,6829,6830,6831,6832,6833,6834,6835,6836,1393,6837,6838,6839,6840, +6841,6842,6843,6844,6845,6846,6847,6848,6849,6850,6851,6852,6853,6854,6855,6856, +6857,6858,6859,6860,6861,6862,6863,6864,6865,6866,6867,6868,6869,6870,6871,6872, +6873,6874,6875,6876,6877,6878,6879,6880,6881,6882,6883,6884,6885,6886,6887,6888, +6889,6890,6891,6892,6893,6894,6895,6896,6897,6898,6899,6900,6901,6902,1712,6903, +6904,6905,6906,6907,6908,6909,6910,1713,6911,6912,6913,6914,6915,6916,6917,6918, +6919,6920,6921,6922,6923,6924,6925,6926,6927,6928,6929,6930,6931,6932,6933,6934, +6935,6936,6937,6938,6939,6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950, +6951,6952,6953,6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966, +6967,6968,6969,6970,6971,6972,6973,6974,1714,6975,6976,6977,6978,6979,6980,6981, +6982,6983,6984,6985,6986,6987,6988,1394,6989,6990,6991,6992,6993,6994,6995,6996, +6997,6998,6999,7000,1715,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011, +7012,7013,7014,7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027, +7028,1716,7029,7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042, +7043,7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058, +7059,7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,7074, +7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,7089,7090, +7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,7104,7105,7106, +7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,7120,7121,7122, +7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,7135,7136,7137,7138, +7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,7149,7150,7151,7152,7153,7154, +7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,7165,7166,7167,7168,7169,7170, +7171,7172,7173,7174,7175,7176,7177,7178,7179,7180,7181,7182,7183,7184,7185,7186, +7187,7188,7189,7190,7191,7192,7193,7194,7195,7196,7197,7198,7199,7200,7201,7202, +7203,7204,7205,7206,7207,1395,7208,7209,7210,7211,7212,7213,1717,7214,7215,7216, +7217,7218,7219,7220,7221,7222,7223,7224,7225,7226,7227,7228,7229,7230,7231,7232, +7233,7234,7235,7236,7237,7238,7239,7240,7241,7242,7243,7244,7245,7246,7247,7248, +7249,7250,7251,7252,7253,7254,7255,7256,7257,7258,7259,7260,7261,7262,7263,7264, +7265,7266,7267,7268,7269,7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280, +7281,7282,7283,7284,7285,7286,7287,7288,7289,7290,7291,7292,7293,7294,7295,7296, +7297,7298,7299,7300,7301,7302,7303,7304,7305,7306,7307,7308,7309,7310,7311,7312, +7313,1718,7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327, +7328,7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,7343, +7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,7358,7359, +7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,7373,7374,7375, +7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,7388,7389,7390,7391, +7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,7403,7404,7405,7406,7407, +7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,7418,7419,7420,7421,7422,7423, +7424,7425,7426,7427,7428,7429,7430,7431,7432,7433,7434,7435,7436,7437,7438,7439, +7440,7441,7442,7443,7444,7445,7446,7447,7448,7449,7450,7451,7452,7453,7454,7455, +7456,7457,7458,7459,7460,7461,7462,7463,7464,7465,7466,7467,7468,7469,7470,7471, +7472,7473,7474,7475,7476,7477,7478,7479,7480,7481,7482,7483,7484,7485,7486,7487, +7488,7489,7490,7491,7492,7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,7503, +7504,7505,7506,7507,7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519, +7520,7521,7522,7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535, +7536,7537,7538,7539,7540,7541,7542,7543,7544,7545,7546,7547,7548,7549,7550,7551, +7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567, +7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582,7583, +7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,7598,7599, +7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,7613,7614,7615, +7616,7617,7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628,7629,7630,7631, +7632,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643,7644,7645,7646,7647, +7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659,7660,7661,7662,7663, +7664,7665,7666,7667,7668,7669,7670,7671,7672,7673,7674,7675,7676,7677,7678,7679, +7680,7681,7682,7683,7684,7685,7686,7687,7688,7689,7690,7691,7692,7693,7694,7695, +7696,7697,7698,7699,7700,7701,7702,7703,7704,7705,7706,7707,7708,7709,7710,7711, +7712,7713,7714,7715,7716,7717,7718,7719,7720,7721,7722,7723,7724,7725,7726,7727, +7728,7729,7730,7731,7732,7733,7734,7735,7736,7737,7738,7739,7740,7741,7742,7743, +7744,7745,7746,7747,7748,7749,7750,7751,7752,7753,7754,7755,7756,7757,7758,7759, +7760,7761,7762,7763,7764,7765,7766,7767,7768,7769,7770,7771,7772,7773,7774,7775, +7776,7777,7778,7779,7780,7781,7782,7783,7784,7785,7786,7787,7788,7789,7790,7791, +7792,7793,7794,7795,7796,7797,7798,7799,7800,7801,7802,7803,7804,7805,7806,7807, +7808,7809,7810,7811,7812,7813,7814,7815,7816,7817,7818,7819,7820,7821,7822,7823, +7824,7825,7826,7827,7828,7829,7830,7831,7832,7833,7834,7835,7836,7837,7838,7839, +7840,7841,7842,7843,7844,7845,7846,7847,7848,7849,7850,7851,7852,7853,7854,7855, +7856,7857,7858,7859,7860,7861,7862,7863,7864,7865,7866,7867,7868,7869,7870,7871, +7872,7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886,7887, +7888,7889,7890,7891,7892,7893,7894,7895,7896,7897,7898,7899,7900,7901,7902,7903, +7904,7905,7906,7907,7908,7909,7910,7911,7912,7913,7914,7915,7916,7917,7918,7919, +7920,7921,7922,7923,7924,7925,7926,7927,7928,7929,7930,7931,7932,7933,7934,7935, +7936,7937,7938,7939,7940,7941,7942,7943,7944,7945,7946,7947,7948,7949,7950,7951, +7952,7953,7954,7955,7956,7957,7958,7959,7960,7961,7962,7963,7964,7965,7966,7967, +7968,7969,7970,7971,7972,7973,7974,7975,7976,7977,7978,7979,7980,7981,7982,7983, +7984,7985,7986,7987,7988,7989,7990,7991,7992,7993,7994,7995,7996,7997,7998,7999, +8000,8001,8002,8003,8004,8005,8006,8007,8008,8009,8010,8011,8012,8013,8014,8015, +8016,8017,8018,8019,8020,8021,8022,8023,8024,8025,8026,8027,8028,8029,8030,8031, +8032,8033,8034,8035,8036,8037,8038,8039,8040,8041,8042,8043,8044,8045,8046,8047, +8048,8049,8050,8051,8052,8053,8054,8055,8056,8057,8058,8059,8060,8061,8062,8063, +8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079, +8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095, +8096,8097,8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110,8111, +8112,8113,8114,8115,8116,8117,8118,8119,8120,8121,8122,8123,8124,8125,8126,8127, +8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,8138,8139,8140,8141,8142,8143, +8144,8145,8146,8147,8148,8149,8150,8151,8152,8153,8154,8155,8156,8157,8158,8159, +8160,8161,8162,8163,8164,8165,8166,8167,8168,8169,8170,8171,8172,8173,8174,8175, +8176,8177,8178,8179,8180,8181,8182,8183,8184,8185,8186,8187,8188,8189,8190,8191, +8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8203,8204,8205,8206,8207, +8208,8209,8210,8211,8212,8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223, +8224,8225,8226,8227,8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239, +8240,8241,8242,8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,8255, +8256,8257,8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,8270,8271, +8272,8273,8274,8275,8276,8277,8278,8279,8280,8281,8282,8283,8284,8285,8286,8287, +8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,8303, +8304,8305,8306,8307,8308,8309,8310,8311,8312,8313,8314,8315,8316,8317,8318,8319, +8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,8330,8331,8332,8333,8334,8335, +8336,8337,8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,8348,8349,8350,8351, +8352,8353,8354,8355,8356,8357,8358,8359,8360,8361,8362,8363,8364,8365,8366,8367, +8368,8369,8370,8371,8372,8373,8374,8375,8376,8377,8378,8379,8380,8381,8382,8383, +8384,8385,8386,8387,8388,8389,8390,8391,8392,8393,8394,8395,8396,8397,8398,8399, +8400,8401,8402,8403,8404,8405,8406,8407,8408,8409,8410,8411,8412,8413,8414,8415, +8416,8417,8418,8419,8420,8421,8422,8423,8424,8425,8426,8427,8428,8429,8430,8431, +8432,8433,8434,8435,8436,8437,8438,8439,8440,8441,8442,8443,8444,8445,8446,8447, +8448,8449,8450,8451,8452,8453,8454,8455,8456,8457,8458,8459,8460,8461,8462,8463, +8464,8465,8466,8467,8468,8469,8470,8471,8472,8473,8474,8475,8476,8477,8478,8479, +8480,8481,8482,8483,8484,8485,8486,8487,8488,8489,8490,8491,8492,8493,8494,8495, +8496,8497,8498,8499,8500,8501,8502,8503,8504,8505,8506,8507,8508,8509,8510,8511, +8512,8513,8514,8515,8516,8517,8518,8519,8520,8521,8522,8523,8524,8525,8526,8527, +8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538,8539,8540,8541,8542,8543, +8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559, +8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,8570,8571,8572,8573,8574,8575, +8576,8577,8578,8579,8580,8581,8582,8583,8584,8585,8586,8587,8588,8589,8590,8591, +8592,8593,8594,8595,8596,8597,8598,8599,8600,8601,8602,8603,8604,8605,8606,8607, +8608,8609,8610,8611,8612,8613,8614,8615,8616,8617,8618,8619,8620,8621,8622,8623, +8624,8625,8626,8627,8628,8629,8630,8631,8632,8633,8634,8635,8636,8637,8638,8639, +8640,8641,8642,8643,8644,8645,8646,8647,8648,8649,8650,8651,8652,8653,8654,8655, +8656,8657,8658,8659,8660,8661,8662,8663,8664,8665,8666,8667,8668,8669,8670,8671, +8672,8673,8674,8675,8676,8677,8678,8679,8680,8681,8682,8683,8684,8685,8686,8687, +8688,8689,8690,8691,8692,8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703, +8704,8705,8706,8707,8708,8709,8710,8711,8712,8713,8714,8715,8716,8717,8718,8719, +8720,8721,8722,8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,8734,8735, +8736,8737,8738,8739,8740,8741) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/euckrprober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/euckrprober.py new file mode 100755 index 0000000..bd697eb --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/euckrprober.py @@ -0,0 +1,41 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from mbcharsetprober import MultiByteCharSetProber +from codingstatemachine import CodingStateMachine +from chardistribution import EUCKRDistributionAnalysis +from mbcssm import EUCKRSMModel + +class EUCKRProber(MultiByteCharSetProber): + def __init__(self): + MultiByteCharSetProber.__init__(self) + self._mCodingSM = CodingStateMachine(EUCKRSMModel) + self._mDistributionAnalyzer = EUCKRDistributionAnalysis() + self.reset() + + def get_charset_name(self): + return "EUC-KR" diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/euctwfreq.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/euctwfreq.py new file mode 100755 index 0000000..c057209 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/euctwfreq.py @@ -0,0 +1,426 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# EUCTW frequency table +# Converted from big5 work +# by Taiwan's Mandarin Promotion Council +# + +# 128 --> 0.42261 +# 256 --> 0.57851 +# 512 --> 0.74851 +# 1024 --> 0.89384 +# 2048 --> 0.97583 +# +# Idea Distribution Ratio = 0.74851/(1-0.74851) =2.98 +# Random Distribution Ration = 512/(5401-512)=0.105 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR + +EUCTW_TYPICAL_DISTRIBUTION_RATIO = 0.75 + +# Char to FreqOrder table , +EUCTW_TABLE_SIZE = 8102 + +EUCTWCharToFreqOrder = ( \ + 1,1800,1506, 255,1431, 198, 9, 82, 6,7310, 177, 202,3615,1256,2808, 110, # 2742 +3735, 33,3241, 261, 76, 44,2113, 16,2931,2184,1176, 659,3868, 26,3404,2643, # 2758 +1198,3869,3313,4060, 410,2211, 302, 590, 361,1963, 8, 204, 58,4296,7311,1931, # 2774 + 63,7312,7313, 317,1614, 75, 222, 159,4061,2412,1480,7314,3500,3068, 224,2809, # 2790 +3616, 3, 10,3870,1471, 29,2774,1135,2852,1939, 873, 130,3242,1123, 312,7315, # 2806 +4297,2051, 507, 252, 682,7316, 142,1914, 124, 206,2932, 34,3501,3173, 64, 604, # 2822 +7317,2494,1976,1977, 155,1990, 645, 641,1606,7318,3405, 337, 72, 406,7319, 80, # 2838 + 630, 238,3174,1509, 263, 939,1092,2644, 756,1440,1094,3406, 449, 69,2969, 591, # 2854 + 179,2095, 471, 115,2034,1843, 60, 50,2970, 134, 806,1868, 734,2035,3407, 180, # 2870 + 995,1607, 156, 537,2893, 688,7320, 319,1305, 779,2144, 514,2374, 298,4298, 359, # 2886 +2495, 90,2707,1338, 663, 11, 906,1099,2545, 20,2436, 182, 532,1716,7321, 732, # 2902 +1376,4062,1311,1420,3175, 25,2312,1056, 113, 399, 382,1949, 242,3408,2467, 529, # 2918 +3243, 475,1447,3617,7322, 117, 21, 656, 810,1297,2295,2329,3502,7323, 126,4063, # 2934 + 706, 456, 150, 613,4299, 71,1118,2036,4064, 145,3069, 85, 835, 486,2114,1246, # 2950 +1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,7324,2127,2354, 347,3736, 221, # 2966 +3503,3110,7325,1955,1153,4065, 83, 296,1199,3070, 192, 624, 93,7326, 822,1897, # 2982 +2810,3111, 795,2064, 991,1554,1542,1592, 27, 43,2853, 859, 139,1456, 860,4300, # 2998 + 437, 712,3871, 164,2392,3112, 695, 211,3017,2096, 195,3872,1608,3504,3505,3618, # 3014 +3873, 234, 811,2971,2097,3874,2229,1441,3506,1615,2375, 668,2076,1638, 305, 228, # 3030 +1664,4301, 467, 415,7327, 262,2098,1593, 239, 108, 300, 200,1033, 512,1247,2077, # 3046 +7328,7329,2173,3176,3619,2673, 593, 845,1062,3244, 88,1723,2037,3875,1950, 212, # 3062 + 266, 152, 149, 468,1898,4066,4302, 77, 187,7330,3018, 37, 5,2972,7331,3876, # 3078 +7332,7333, 39,2517,4303,2894,3177,2078, 55, 148, 74,4304, 545, 483,1474,1029, # 3094 +1665, 217,1869,1531,3113,1104,2645,4067, 24, 172,3507, 900,3877,3508,3509,4305, # 3110 + 32,1408,2811,1312, 329, 487,2355,2247,2708, 784,2674, 4,3019,3314,1427,1788, # 3126 + 188, 109, 499,7334,3620,1717,1789, 888,1217,3020,4306,7335,3510,7336,3315,1520, # 3142 +3621,3878, 196,1034, 775,7337,7338, 929,1815, 249, 439, 38,7339,1063,7340, 794, # 3158 +3879,1435,2296, 46, 178,3245,2065,7341,2376,7342, 214,1709,4307, 804, 35, 707, # 3174 + 324,3622,1601,2546, 140, 459,4068,7343,7344,1365, 839, 272, 978,2257,2572,3409, # 3190 +2128,1363,3623,1423, 697, 100,3071, 48, 70,1231, 495,3114,2193,7345,1294,7346, # 3206 +2079, 462, 586,1042,3246, 853, 256, 988, 185,2377,3410,1698, 434,1084,7347,3411, # 3222 + 314,2615,2775,4308,2330,2331, 569,2280, 637,1816,2518, 757,1162,1878,1616,3412, # 3238 + 287,1577,2115, 768,4309,1671,2854,3511,2519,1321,3737, 909,2413,7348,4069, 933, # 3254 +3738,7349,2052,2356,1222,4310, 765,2414,1322, 786,4311,7350,1919,1462,1677,2895, # 3270 +1699,7351,4312,1424,2437,3115,3624,2590,3316,1774,1940,3413,3880,4070, 309,1369, # 3286 +1130,2812, 364,2230,1653,1299,3881,3512,3882,3883,2646, 525,1085,3021, 902,2000, # 3302 +1475, 964,4313, 421,1844,1415,1057,2281, 940,1364,3116, 376,4314,4315,1381, 7, # 3318 +2520, 983,2378, 336,1710,2675,1845, 321,3414, 559,1131,3022,2742,1808,1132,1313, # 3334 + 265,1481,1857,7352, 352,1203,2813,3247, 167,1089, 420,2814, 776, 792,1724,3513, # 3350 +4071,2438,3248,7353,4072,7354, 446, 229, 333,2743, 901,3739,1200,1557,4316,2647, # 3366 +1920, 395,2744,2676,3740,4073,1835, 125, 916,3178,2616,4317,7355,7356,3741,7357, # 3382 +7358,7359,4318,3117,3625,1133,2547,1757,3415,1510,2313,1409,3514,7360,2145, 438, # 3398 +2591,2896,2379,3317,1068, 958,3023, 461, 311,2855,2677,4074,1915,3179,4075,1978, # 3414 + 383, 750,2745,2617,4076, 274, 539, 385,1278,1442,7361,1154,1964, 384, 561, 210, # 3430 + 98,1295,2548,3515,7362,1711,2415,1482,3416,3884,2897,1257, 129,7363,3742, 642, # 3446 + 523,2776,2777,2648,7364, 141,2231,1333, 68, 176, 441, 876, 907,4077, 603,2592, # 3462 + 710, 171,3417, 404, 549, 18,3118,2393,1410,3626,1666,7365,3516,4319,2898,4320, # 3478 +7366,2973, 368,7367, 146, 366, 99, 871,3627,1543, 748, 807,1586,1185, 22,2258, # 3494 + 379,3743,3180,7368,3181, 505,1941,2618,1991,1382,2314,7369, 380,2357, 218, 702, # 3510 +1817,1248,3418,3024,3517,3318,3249,7370,2974,3628, 930,3250,3744,7371, 59,7372, # 3526 + 585, 601,4078, 497,3419,1112,1314,4321,1801,7373,1223,1472,2174,7374, 749,1836, # 3542 + 690,1899,3745,1772,3885,1476, 429,1043,1790,2232,2116, 917,4079, 447,1086,1629, # 3558 +7375, 556,7376,7377,2020,1654, 844,1090, 105, 550, 966,1758,2815,1008,1782, 686, # 3574 +1095,7378,2282, 793,1602,7379,3518,2593,4322,4080,2933,2297,4323,3746, 980,2496, # 3590 + 544, 353, 527,4324, 908,2678,2899,7380, 381,2619,1942,1348,7381,1341,1252, 560, # 3606 +3072,7382,3420,2856,7383,2053, 973, 886,2080, 143,4325,7384,7385, 157,3886, 496, # 3622 +4081, 57, 840, 540,2038,4326,4327,3421,2117,1445, 970,2259,1748,1965,2081,4082, # 3638 +3119,1234,1775,3251,2816,3629, 773,1206,2129,1066,2039,1326,3887,1738,1725,4083, # 3654 + 279,3120, 51,1544,2594, 423,1578,2130,2066, 173,4328,1879,7386,7387,1583, 264, # 3670 + 610,3630,4329,2439, 280, 154,7388,7389,7390,1739, 338,1282,3073, 693,2857,1411, # 3686 +1074,3747,2440,7391,4330,7392,7393,1240, 952,2394,7394,2900,1538,2679, 685,1483, # 3702 +4084,2468,1436, 953,4085,2054,4331, 671,2395, 79,4086,2441,3252, 608, 567,2680, # 3718 +3422,4087,4088,1691, 393,1261,1791,2396,7395,4332,7396,7397,7398,7399,1383,1672, # 3734 +3748,3182,1464, 522,1119, 661,1150, 216, 675,4333,3888,1432,3519, 609,4334,2681, # 3750 +2397,7400,7401,7402,4089,3025, 0,7403,2469, 315, 231,2442, 301,3319,4335,2380, # 3766 +7404, 233,4090,3631,1818,4336,4337,7405, 96,1776,1315,2082,7406, 257,7407,1809, # 3782 +3632,2709,1139,1819,4091,2021,1124,2163,2778,1777,2649,7408,3074, 363,1655,3183, # 3798 +7409,2975,7410,7411,7412,3889,1567,3890, 718, 103,3184, 849,1443, 341,3320,2934, # 3814 +1484,7413,1712, 127, 67, 339,4092,2398, 679,1412, 821,7414,7415, 834, 738, 351, # 3830 +2976,2146, 846, 235,1497,1880, 418,1992,3749,2710, 186,1100,2147,2746,3520,1545, # 3846 +1355,2935,2858,1377, 583,3891,4093,2573,2977,7416,1298,3633,1078,2549,3634,2358, # 3862 + 78,3750,3751, 267,1289,2099,2001,1594,4094, 348, 369,1274,2194,2175,1837,4338, # 3878 +1820,2817,3635,2747,2283,2002,4339,2936,2748, 144,3321, 882,4340,3892,2749,3423, # 3894 +4341,2901,7417,4095,1726, 320,7418,3893,3026, 788,2978,7419,2818,1773,1327,2859, # 3910 +3894,2819,7420,1306,4342,2003,1700,3752,3521,2359,2650, 787,2022, 506, 824,3636, # 3926 + 534, 323,4343,1044,3322,2023,1900, 946,3424,7421,1778,1500,1678,7422,1881,4344, # 3942 + 165, 243,4345,3637,2521, 123, 683,4096, 764,4346, 36,3895,1792, 589,2902, 816, # 3958 + 626,1667,3027,2233,1639,1555,1622,3753,3896,7423,3897,2860,1370,1228,1932, 891, # 3974 +2083,2903, 304,4097,7424, 292,2979,2711,3522, 691,2100,4098,1115,4347, 118, 662, # 3990 +7425, 611,1156, 854,2381,1316,2861, 2, 386, 515,2904,7426,7427,3253, 868,2234, # 4006 +1486, 855,2651, 785,2212,3028,7428,1040,3185,3523,7429,3121, 448,7430,1525,7431, # 4022 +2164,4348,7432,3754,7433,4099,2820,3524,3122, 503, 818,3898,3123,1568, 814, 676, # 4038 +1444, 306,1749,7434,3755,1416,1030, 197,1428, 805,2821,1501,4349,7435,7436,7437, # 4054 +1993,7438,4350,7439,7440,2195, 13,2779,3638,2980,3124,1229,1916,7441,3756,2131, # 4070 +7442,4100,4351,2399,3525,7443,2213,1511,1727,1120,7444,7445, 646,3757,2443, 307, # 4086 +7446,7447,1595,3186,7448,7449,7450,3639,1113,1356,3899,1465,2522,2523,7451, 519, # 4102 +7452, 128,2132, 92,2284,1979,7453,3900,1512, 342,3125,2196,7454,2780,2214,1980, # 4118 +3323,7455, 290,1656,1317, 789, 827,2360,7456,3758,4352, 562, 581,3901,7457, 401, # 4134 +4353,2248, 94,4354,1399,2781,7458,1463,2024,4355,3187,1943,7459, 828,1105,4101, # 4150 +1262,1394,7460,4102, 605,4356,7461,1783,2862,7462,2822, 819,2101, 578,2197,2937, # 4166 +7463,1502, 436,3254,4103,3255,2823,3902,2905,3425,3426,7464,2712,2315,7465,7466, # 4182 +2332,2067, 23,4357, 193, 826,3759,2102, 699,1630,4104,3075, 390,1793,1064,3526, # 4198 +7467,1579,3076,3077,1400,7468,4105,1838,1640,2863,7469,4358,4359, 137,4106, 598, # 4214 +3078,1966, 780, 104, 974,2938,7470, 278, 899, 253, 402, 572, 504, 493,1339,7471, # 4230 +3903,1275,4360,2574,2550,7472,3640,3029,3079,2249, 565,1334,2713, 863, 41,7473, # 4246 +7474,4361,7475,1657,2333, 19, 463,2750,4107, 606,7476,2981,3256,1087,2084,1323, # 4262 +2652,2982,7477,1631,1623,1750,4108,2682,7478,2864, 791,2714,2653,2334, 232,2416, # 4278 +7479,2983,1498,7480,2654,2620, 755,1366,3641,3257,3126,2025,1609, 119,1917,3427, # 4294 + 862,1026,4109,7481,3904,3760,4362,3905,4363,2260,1951,2470,7482,1125, 817,4110, # 4310 +4111,3906,1513,1766,2040,1487,4112,3030,3258,2824,3761,3127,7483,7484,1507,7485, # 4326 +2683, 733, 40,1632,1106,2865, 345,4113, 841,2524, 230,4364,2984,1846,3259,3428, # 4342 +7486,1263, 986,3429,7487, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562,3907, # 4358 +3908,2939, 967,2751,2655,1349, 592,2133,1692,3324,2985,1994,4114,1679,3909,1901, # 4374 +2185,7488, 739,3642,2715,1296,1290,7489,4115,2198,2199,1921,1563,2595,2551,1870, # 4390 +2752,2986,7490, 435,7491, 343,1108, 596, 17,1751,4365,2235,3430,3643,7492,4366, # 4406 + 294,3527,2940,1693, 477, 979, 281,2041,3528, 643,2042,3644,2621,2782,2261,1031, # 4422 +2335,2134,2298,3529,4367, 367,1249,2552,7493,3530,7494,4368,1283,3325,2004, 240, # 4438 +1762,3326,4369,4370, 836,1069,3128, 474,7495,2148,2525, 268,3531,7496,3188,1521, # 4454 +1284,7497,1658,1546,4116,7498,3532,3533,7499,4117,3327,2684,1685,4118, 961,1673, # 4470 +2622, 190,2005,2200,3762,4371,4372,7500, 570,2497,3645,1490,7501,4373,2623,3260, # 4486 +1956,4374, 584,1514, 396,1045,1944,7502,4375,1967,2444,7503,7504,4376,3910, 619, # 4502 +7505,3129,3261, 215,2006,2783,2553,3189,4377,3190,4378, 763,4119,3763,4379,7506, # 4518 +7507,1957,1767,2941,3328,3646,1174, 452,1477,4380,3329,3130,7508,2825,1253,2382, # 4534 +2186,1091,2285,4120, 492,7509, 638,1169,1824,2135,1752,3911, 648, 926,1021,1324, # 4550 +4381, 520,4382, 997, 847,1007, 892,4383,3764,2262,1871,3647,7510,2400,1784,4384, # 4566 +1952,2942,3080,3191,1728,4121,2043,3648,4385,2007,1701,3131,1551, 30,2263,4122, # 4582 +7511,2026,4386,3534,7512, 501,7513,4123, 594,3431,2165,1821,3535,3432,3536,3192, # 4598 + 829,2826,4124,7514,1680,3132,1225,4125,7515,3262,4387,4126,3133,2336,7516,4388, # 4614 +4127,7517,3912,3913,7518,1847,2383,2596,3330,7519,4389, 374,3914, 652,4128,4129, # 4630 + 375,1140, 798,7520,7521,7522,2361,4390,2264, 546,1659, 138,3031,2445,4391,7523, # 4646 +2250, 612,1848, 910, 796,3765,1740,1371, 825,3766,3767,7524,2906,2554,7525, 692, # 4662 + 444,3032,2624, 801,4392,4130,7526,1491, 244,1053,3033,4131,4132, 340,7527,3915, # 4678 +1041,2987, 293,1168, 87,1357,7528,1539, 959,7529,2236, 721, 694,4133,3768, 219, # 4694 +1478, 644,1417,3331,2656,1413,1401,1335,1389,3916,7530,7531,2988,2362,3134,1825, # 4710 + 730,1515, 184,2827, 66,4393,7532,1660,2943, 246,3332, 378,1457, 226,3433, 975, # 4726 +3917,2944,1264,3537, 674, 696,7533, 163,7534,1141,2417,2166, 713,3538,3333,4394, # 4742 +3918,7535,7536,1186, 15,7537,1079,1070,7538,1522,3193,3539, 276,1050,2716, 758, # 4758 +1126, 653,2945,3263,7539,2337, 889,3540,3919,3081,2989, 903,1250,4395,3920,3434, # 4774 +3541,1342,1681,1718, 766,3264, 286, 89,2946,3649,7540,1713,7541,2597,3334,2990, # 4790 +7542,2947,2215,3194,2866,7543,4396,2498,2526, 181, 387,1075,3921, 731,2187,3335, # 4806 +7544,3265, 310, 313,3435,2299, 770,4134, 54,3034, 189,4397,3082,3769,3922,7545, # 4822 +1230,1617,1849, 355,3542,4135,4398,3336, 111,4136,3650,1350,3135,3436,3035,4137, # 4838 +2149,3266,3543,7546,2784,3923,3924,2991, 722,2008,7547,1071, 247,1207,2338,2471, # 4854 +1378,4399,2009, 864,1437,1214,4400, 373,3770,1142,2216, 667,4401, 442,2753,2555, # 4870 +3771,3925,1968,4138,3267,1839, 837, 170,1107, 934,1336,1882,7548,7549,2118,4139, # 4886 +2828, 743,1569,7550,4402,4140, 582,2384,1418,3437,7551,1802,7552, 357,1395,1729, # 4902 +3651,3268,2418,1564,2237,7553,3083,3772,1633,4403,1114,2085,4141,1532,7554, 482, # 4918 +2446,4404,7555,7556,1492, 833,1466,7557,2717,3544,1641,2829,7558,1526,1272,3652, # 4934 +4142,1686,1794, 416,2556,1902,1953,1803,7559,3773,2785,3774,1159,2316,7560,2867, # 4950 +4405,1610,1584,3036,2419,2754, 443,3269,1163,3136,7561,7562,3926,7563,4143,2499, # 4966 +3037,4406,3927,3137,2103,1647,3545,2010,1872,4144,7564,4145, 431,3438,7565, 250, # 4982 + 97, 81,4146,7566,1648,1850,1558, 160, 848,7567, 866, 740,1694,7568,2201,2830, # 4998 +3195,4147,4407,3653,1687, 950,2472, 426, 469,3196,3654,3655,3928,7569,7570,1188, # 5014 + 424,1995, 861,3546,4148,3775,2202,2685, 168,1235,3547,4149,7571,2086,1674,4408, # 5030 +3337,3270, 220,2557,1009,7572,3776, 670,2992, 332,1208, 717,7573,7574,3548,2447, # 5046 +3929,3338,7575, 513,7576,1209,2868,3339,3138,4409,1080,7577,7578,7579,7580,2527, # 5062 +3656,3549, 815,1587,3930,3931,7581,3550,3439,3777,1254,4410,1328,3038,1390,3932, # 5078 +1741,3933,3778,3934,7582, 236,3779,2448,3271,7583,7584,3657,3780,1273,3781,4411, # 5094 +7585, 308,7586,4412, 245,4413,1851,2473,1307,2575, 430, 715,2136,2449,7587, 270, # 5110 + 199,2869,3935,7588,3551,2718,1753, 761,1754, 725,1661,1840,4414,3440,3658,7589, # 5126 +7590, 587, 14,3272, 227,2598, 326, 480,2265, 943,2755,3552, 291, 650,1883,7591, # 5142 +1702,1226, 102,1547, 62,3441, 904,4415,3442,1164,4150,7592,7593,1224,1548,2756, # 5158 + 391, 498,1493,7594,1386,1419,7595,2055,1177,4416, 813, 880,1081,2363, 566,1145, # 5174 +4417,2286,1001,1035,2558,2599,2238, 394,1286,7596,7597,2068,7598, 86,1494,1730, # 5190 +3936, 491,1588, 745, 897,2948, 843,3340,3937,2757,2870,3273,1768, 998,2217,2069, # 5206 + 397,1826,1195,1969,3659,2993,3341, 284,7599,3782,2500,2137,2119,1903,7600,3938, # 5222 +2150,3939,4151,1036,3443,1904, 114,2559,4152, 209,1527,7601,7602,2949,2831,2625, # 5238 +2385,2719,3139, 812,2560,7603,3274,7604,1559, 737,1884,3660,1210, 885, 28,2686, # 5254 +3553,3783,7605,4153,1004,1779,4418,7606, 346,1981,2218,2687,4419,3784,1742, 797, # 5270 +1642,3940,1933,1072,1384,2151, 896,3941,3275,3661,3197,2871,3554,7607,2561,1958, # 5286 +4420,2450,1785,7608,7609,7610,3942,4154,1005,1308,3662,4155,2720,4421,4422,1528, # 5302 +2600, 161,1178,4156,1982, 987,4423,1101,4157, 631,3943,1157,3198,2420,1343,1241, # 5318 +1016,2239,2562, 372, 877,2339,2501,1160, 555,1934, 911,3944,7611, 466,1170, 169, # 5334 +1051,2907,2688,3663,2474,2994,1182,2011,2563,1251,2626,7612, 992,2340,3444,1540, # 5350 +2721,1201,2070,2401,1996,2475,7613,4424, 528,1922,2188,1503,1873,1570,2364,3342, # 5366 +3276,7614, 557,1073,7615,1827,3445,2087,2266,3140,3039,3084, 767,3085,2786,4425, # 5382 +1006,4158,4426,2341,1267,2176,3664,3199, 778,3945,3200,2722,1597,2657,7616,4427, # 5398 +7617,3446,7618,7619,7620,3277,2689,1433,3278, 131, 95,1504,3946, 723,4159,3141, # 5414 +1841,3555,2758,2189,3947,2027,2104,3665,7621,2995,3948,1218,7622,3343,3201,3949, # 5430 +4160,2576, 248,1634,3785, 912,7623,2832,3666,3040,3786, 654, 53,7624,2996,7625, # 5446 +1688,4428, 777,3447,1032,3950,1425,7626, 191, 820,2120,2833, 971,4429, 931,3202, # 5462 + 135, 664, 783,3787,1997, 772,2908,1935,3951,3788,4430,2909,3203, 282,2723, 640, # 5478 +1372,3448,1127, 922, 325,3344,7627,7628, 711,2044,7629,7630,3952,2219,2787,1936, # 5494 +3953,3345,2220,2251,3789,2300,7631,4431,3790,1258,3279,3954,3204,2138,2950,3955, # 5510 +3956,7632,2221, 258,3205,4432, 101,1227,7633,3280,1755,7634,1391,3281,7635,2910, # 5526 +2056, 893,7636,7637,7638,1402,4161,2342,7639,7640,3206,3556,7641,7642, 878,1325, # 5542 +1780,2788,4433, 259,1385,2577, 744,1183,2267,4434,7643,3957,2502,7644, 684,1024, # 5558 +4162,7645, 472,3557,3449,1165,3282,3958,3959, 322,2152, 881, 455,1695,1152,1340, # 5574 + 660, 554,2153,4435,1058,4436,4163, 830,1065,3346,3960,4437,1923,7646,1703,1918, # 5590 +7647, 932,2268, 122,7648,4438, 947, 677,7649,3791,2627, 297,1905,1924,2269,4439, # 5606 +2317,3283,7650,7651,4164,7652,4165, 84,4166, 112, 989,7653, 547,1059,3961, 701, # 5622 +3558,1019,7654,4167,7655,3450, 942, 639, 457,2301,2451, 993,2951, 407, 851, 494, # 5638 +4440,3347, 927,7656,1237,7657,2421,3348, 573,4168, 680, 921,2911,1279,1874, 285, # 5654 + 790,1448,1983, 719,2167,7658,7659,4441,3962,3963,1649,7660,1541, 563,7661,1077, # 5670 +7662,3349,3041,3451, 511,2997,3964,3965,3667,3966,1268,2564,3350,3207,4442,4443, # 5686 +7663, 535,1048,1276,1189,2912,2028,3142,1438,1373,2834,2952,1134,2012,7664,4169, # 5702 +1238,2578,3086,1259,7665, 700,7666,2953,3143,3668,4170,7667,4171,1146,1875,1906, # 5718 +4444,2601,3967, 781,2422, 132,1589, 203, 147, 273,2789,2402, 898,1786,2154,3968, # 5734 +3969,7668,3792,2790,7669,7670,4445,4446,7671,3208,7672,1635,3793, 965,7673,1804, # 5750 +2690,1516,3559,1121,1082,1329,3284,3970,1449,3794, 65,1128,2835,2913,2759,1590, # 5766 +3795,7674,7675, 12,2658, 45, 976,2579,3144,4447, 517,2528,1013,1037,3209,7676, # 5782 +3796,2836,7677,3797,7678,3452,7679,2602, 614,1998,2318,3798,3087,2724,2628,7680, # 5798 +2580,4172, 599,1269,7681,1810,3669,7682,2691,3088, 759,1060, 489,1805,3351,3285, # 5814 +1358,7683,7684,2386,1387,1215,2629,2252, 490,7685,7686,4173,1759,2387,2343,7687, # 5830 +4448,3799,1907,3971,2630,1806,3210,4449,3453,3286,2760,2344, 874,7688,7689,3454, # 5846 +3670,1858, 91,2914,3671,3042,3800,4450,7690,3145,3972,2659,7691,3455,1202,1403, # 5862 +3801,2954,2529,1517,2503,4451,3456,2504,7692,4452,7693,2692,1885,1495,1731,3973, # 5878 +2365,4453,7694,2029,7695,7696,3974,2693,1216, 237,2581,4174,2319,3975,3802,4454, # 5894 +4455,2694,3560,3457, 445,4456,7697,7698,7699,7700,2761, 61,3976,3672,1822,3977, # 5910 +7701, 687,2045, 935, 925, 405,2660, 703,1096,1859,2725,4457,3978,1876,1367,2695, # 5926 +3352, 918,2105,1781,2476, 334,3287,1611,1093,4458, 564,3146,3458,3673,3353, 945, # 5942 +2631,2057,4459,7702,1925, 872,4175,7703,3459,2696,3089, 349,4176,3674,3979,4460, # 5958 +3803,4177,3675,2155,3980,4461,4462,4178,4463,2403,2046, 782,3981, 400, 251,4179, # 5974 +1624,7704,7705, 277,3676, 299,1265, 476,1191,3804,2121,4180,4181,1109, 205,7706, # 5990 +2582,1000,2156,3561,1860,7707,7708,7709,4464,7710,4465,2565, 107,2477,2157,3982, # 6006 +3460,3147,7711,1533, 541,1301, 158, 753,4182,2872,3562,7712,1696, 370,1088,4183, # 6022 +4466,3563, 579, 327, 440, 162,2240, 269,1937,1374,3461, 968,3043, 56,1396,3090, # 6038 +2106,3288,3354,7713,1926,2158,4467,2998,7714,3564,7715,7716,3677,4468,2478,7717, # 6054 +2791,7718,1650,4469,7719,2603,7720,7721,3983,2661,3355,1149,3356,3984,3805,3985, # 6070 +7722,1076, 49,7723, 951,3211,3289,3290, 450,2837, 920,7724,1811,2792,2366,4184, # 6086 +1908,1138,2367,3806,3462,7725,3212,4470,1909,1147,1518,2423,4471,3807,7726,4472, # 6102 +2388,2604, 260,1795,3213,7727,7728,3808,3291, 708,7729,3565,1704,7730,3566,1351, # 6118 +1618,3357,2999,1886, 944,4185,3358,4186,3044,3359,4187,7731,3678, 422, 413,1714, # 6134 +3292, 500,2058,2345,4188,2479,7732,1344,1910, 954,7733,1668,7734,7735,3986,2404, # 6150 +4189,3567,3809,4190,7736,2302,1318,2505,3091, 133,3092,2873,4473, 629, 31,2838, # 6166 +2697,3810,4474, 850, 949,4475,3987,2955,1732,2088,4191,1496,1852,7737,3988, 620, # 6182 +3214, 981,1242,3679,3360,1619,3680,1643,3293,2139,2452,1970,1719,3463,2168,7738, # 6198 +3215,7739,7740,3361,1828,7741,1277,4476,1565,2047,7742,1636,3568,3093,7743, 869, # 6214 +2839, 655,3811,3812,3094,3989,3000,3813,1310,3569,4477,7744,7745,7746,1733, 558, # 6230 +4478,3681, 335,1549,3045,1756,4192,3682,1945,3464,1829,1291,1192, 470,2726,2107, # 6246 +2793, 913,1054,3990,7747,1027,7748,3046,3991,4479, 982,2662,3362,3148,3465,3216, # 6262 +3217,1946,2794,7749, 571,4480,7750,1830,7751,3570,2583,1523,2424,7752,2089, 984, # 6278 +4481,3683,1959,7753,3684, 852, 923,2795,3466,3685, 969,1519, 999,2048,2320,1705, # 6294 +7754,3095, 615,1662, 151, 597,3992,2405,2321,1049, 275,4482,3686,4193, 568,3687, # 6310 +3571,2480,4194,3688,7755,2425,2270, 409,3218,7756,1566,2874,3467,1002, 769,2840, # 6326 + 194,2090,3149,3689,2222,3294,4195, 628,1505,7757,7758,1763,2177,3001,3993, 521, # 6342 +1161,2584,1787,2203,2406,4483,3994,1625,4196,4197, 412, 42,3096, 464,7759,2632, # 6358 +4484,3363,1760,1571,2875,3468,2530,1219,2204,3814,2633,2140,2368,4485,4486,3295, # 6374 +1651,3364,3572,7760,7761,3573,2481,3469,7762,3690,7763,7764,2271,2091, 460,7765, # 6390 +4487,7766,3002, 962, 588,3574, 289,3219,2634,1116, 52,7767,3047,1796,7768,7769, # 6406 +7770,1467,7771,1598,1143,3691,4198,1984,1734,1067,4488,1280,3365, 465,4489,1572, # 6422 + 510,7772,1927,2241,1812,1644,3575,7773,4490,3692,7774,7775,2663,1573,1534,7776, # 6438 +7777,4199, 536,1807,1761,3470,3815,3150,2635,7778,7779,7780,4491,3471,2915,1911, # 6454 +2796,7781,3296,1122, 377,3220,7782, 360,7783,7784,4200,1529, 551,7785,2059,3693, # 6470 +1769,2426,7786,2916,4201,3297,3097,2322,2108,2030,4492,1404, 136,1468,1479, 672, # 6486 +1171,3221,2303, 271,3151,7787,2762,7788,2049, 678,2727, 865,1947,4493,7789,2013, # 6502 +3995,2956,7790,2728,2223,1397,3048,3694,4494,4495,1735,2917,3366,3576,7791,3816, # 6518 + 509,2841,2453,2876,3817,7792,7793,3152,3153,4496,4202,2531,4497,2304,1166,1010, # 6534 + 552, 681,1887,7794,7795,2957,2958,3996,1287,1596,1861,3154, 358, 453, 736, 175, # 6550 + 478,1117, 905,1167,1097,7796,1853,1530,7797,1706,7798,2178,3472,2287,3695,3473, # 6566 +3577,4203,2092,4204,7799,3367,1193,2482,4205,1458,2190,2205,1862,1888,1421,3298, # 6582 +2918,3049,2179,3474, 595,2122,7800,3997,7801,7802,4206,1707,2636, 223,3696,1359, # 6598 + 751,3098, 183,3475,7803,2797,3003, 419,2369, 633, 704,3818,2389, 241,7804,7805, # 6614 +7806, 838,3004,3697,2272,2763,2454,3819,1938,2050,3998,1309,3099,2242,1181,7807, # 6630 +1136,2206,3820,2370,1446,4207,2305,4498,7808,7809,4208,1055,2605, 484,3698,7810, # 6646 +3999, 625,4209,2273,3368,1499,4210,4000,7811,4001,4211,3222,2274,2275,3476,7812, # 6662 +7813,2764, 808,2606,3699,3369,4002,4212,3100,2532, 526,3370,3821,4213, 955,7814, # 6678 +1620,4214,2637,2427,7815,1429,3700,1669,1831, 994, 928,7816,3578,1260,7817,7818, # 6694 +7819,1948,2288, 741,2919,1626,4215,2729,2455, 867,1184, 362,3371,1392,7820,7821, # 6710 +4003,4216,1770,1736,3223,2920,4499,4500,1928,2698,1459,1158,7822,3050,3372,2877, # 6726 +1292,1929,2506,2842,3701,1985,1187,2071,2014,2607,4217,7823,2566,2507,2169,3702, # 6742 +2483,3299,7824,3703,4501,7825,7826, 666,1003,3005,1022,3579,4218,7827,4502,1813, # 6758 +2253, 574,3822,1603, 295,1535, 705,3823,4219, 283, 858, 417,7828,7829,3224,4503, # 6774 +4504,3051,1220,1889,1046,2276,2456,4004,1393,1599, 689,2567, 388,4220,7830,2484, # 6790 + 802,7831,2798,3824,2060,1405,2254,7832,4505,3825,2109,1052,1345,3225,1585,7833, # 6806 + 809,7834,7835,7836, 575,2730,3477, 956,1552,1469,1144,2323,7837,2324,1560,2457, # 6822 +3580,3226,4005, 616,2207,3155,2180,2289,7838,1832,7839,3478,4506,7840,1319,3704, # 6838 +3705,1211,3581,1023,3227,1293,2799,7841,7842,7843,3826, 607,2306,3827, 762,2878, # 6854 +1439,4221,1360,7844,1485,3052,7845,4507,1038,4222,1450,2061,2638,4223,1379,4508, # 6870 +2585,7846,7847,4224,1352,1414,2325,2921,1172,7848,7849,3828,3829,7850,1797,1451, # 6886 +7851,7852,7853,7854,2922,4006,4007,2485,2346, 411,4008,4009,3582,3300,3101,4509, # 6902 +1561,2664,1452,4010,1375,7855,7856, 47,2959, 316,7857,1406,1591,2923,3156,7858, # 6918 +1025,2141,3102,3157, 354,2731, 884,2224,4225,2407, 508,3706, 726,3583, 996,2428, # 6934 +3584, 729,7859, 392,2191,1453,4011,4510,3707,7860,7861,2458,3585,2608,1675,2800, # 6950 + 919,2347,2960,2348,1270,4511,4012, 73,7862,7863, 647,7864,3228,2843,2255,1550, # 6966 +1346,3006,7865,1332, 883,3479,7866,7867,7868,7869,3301,2765,7870,1212, 831,1347, # 6982 +4226,4512,2326,3830,1863,3053, 720,3831,4513,4514,3832,7871,4227,7872,7873,4515, # 6998 +7874,7875,1798,4516,3708,2609,4517,3586,1645,2371,7876,7877,2924, 669,2208,2665, # 7014 +2429,7878,2879,7879,7880,1028,3229,7881,4228,2408,7882,2256,1353,7883,7884,4518, # 7030 +3158, 518,7885,4013,7886,4229,1960,7887,2142,4230,7888,7889,3007,2349,2350,3833, # 7046 + 516,1833,1454,4014,2699,4231,4519,2225,2610,1971,1129,3587,7890,2766,7891,2961, # 7062 +1422, 577,1470,3008,1524,3373,7892,7893, 432,4232,3054,3480,7894,2586,1455,2508, # 7078 +2226,1972,1175,7895,1020,2732,4015,3481,4520,7896,2733,7897,1743,1361,3055,3482, # 7094 +2639,4016,4233,4521,2290, 895, 924,4234,2170, 331,2243,3056, 166,1627,3057,1098, # 7110 +7898,1232,2880,2227,3374,4522, 657, 403,1196,2372, 542,3709,3375,1600,4235,3483, # 7126 +7899,4523,2767,3230, 576, 530,1362,7900,4524,2533,2666,3710,4017,7901, 842,3834, # 7142 +7902,2801,2031,1014,4018, 213,2700,3376, 665, 621,4236,7903,3711,2925,2430,7904, # 7158 +2431,3302,3588,3377,7905,4237,2534,4238,4525,3589,1682,4239,3484,1380,7906, 724, # 7174 +2277, 600,1670,7907,1337,1233,4526,3103,2244,7908,1621,4527,7909, 651,4240,7910, # 7190 +1612,4241,2611,7911,2844,7912,2734,2307,3058,7913, 716,2459,3059, 174,1255,2701, # 7206 +4019,3590, 548,1320,1398, 728,4020,1574,7914,1890,1197,3060,4021,7915,3061,3062, # 7222 +3712,3591,3713, 747,7916, 635,4242,4528,7917,7918,7919,4243,7920,7921,4529,7922, # 7238 +3378,4530,2432, 451,7923,3714,2535,2072,4244,2735,4245,4022,7924,1764,4531,7925, # 7254 +4246, 350,7926,2278,2390,2486,7927,4247,4023,2245,1434,4024, 488,4532, 458,4248, # 7270 +4025,3715, 771,1330,2391,3835,2568,3159,2159,2409,1553,2667,3160,4249,7928,2487, # 7286 +2881,2612,1720,2702,4250,3379,4533,7929,2536,4251,7930,3231,4252,2768,7931,2015, # 7302 +2736,7932,1155,1017,3716,3836,7933,3303,2308, 201,1864,4253,1430,7934,4026,7935, # 7318 +7936,7937,7938,7939,4254,1604,7940, 414,1865, 371,2587,4534,4535,3485,2016,3104, # 7334 +4536,1708, 960,4255, 887, 389,2171,1536,1663,1721,7941,2228,4027,2351,2926,1580, # 7350 +7942,7943,7944,1744,7945,2537,4537,4538,7946,4539,7947,2073,7948,7949,3592,3380, # 7366 +2882,4256,7950,4257,2640,3381,2802, 673,2703,2460, 709,3486,4028,3593,4258,7951, # 7382 +1148, 502, 634,7952,7953,1204,4540,3594,1575,4541,2613,3717,7954,3718,3105, 948, # 7398 +3232, 121,1745,3837,1110,7955,4259,3063,2509,3009,4029,3719,1151,1771,3838,1488, # 7414 +4030,1986,7956,2433,3487,7957,7958,2093,7959,4260,3839,1213,1407,2803, 531,2737, # 7430 +2538,3233,1011,1537,7960,2769,4261,3106,1061,7961,3720,3721,1866,2883,7962,2017, # 7446 + 120,4262,4263,2062,3595,3234,2309,3840,2668,3382,1954,4542,7963,7964,3488,1047, # 7462 +2704,1266,7965,1368,4543,2845, 649,3383,3841,2539,2738,1102,2846,2669,7966,7967, # 7478 +1999,7968,1111,3596,2962,7969,2488,3842,3597,2804,1854,3384,3722,7970,7971,3385, # 7494 +2410,2884,3304,3235,3598,7972,2569,7973,3599,2805,4031,1460, 856,7974,3600,7975, # 7510 +2885,2963,7976,2886,3843,7977,4264, 632,2510, 875,3844,1697,3845,2291,7978,7979, # 7526 +4544,3010,1239, 580,4545,4265,7980, 914, 936,2074,1190,4032,1039,2123,7981,7982, # 7542 +7983,3386,1473,7984,1354,4266,3846,7985,2172,3064,4033, 915,3305,4267,4268,3306, # 7558 +1605,1834,7986,2739, 398,3601,4269,3847,4034, 328,1912,2847,4035,3848,1331,4270, # 7574 +3011, 937,4271,7987,3602,4036,4037,3387,2160,4546,3388, 524, 742, 538,3065,1012, # 7590 +7988,7989,3849,2461,7990, 658,1103, 225,3850,7991,7992,4547,7993,4548,7994,3236, # 7606 +1243,7995,4038, 963,2246,4549,7996,2705,3603,3161,7997,7998,2588,2327,7999,4550, # 7622 +8000,8001,8002,3489,3307, 957,3389,2540,2032,1930,2927,2462, 870,2018,3604,1746, # 7638 +2770,2771,2434,2463,8003,3851,8004,3723,3107,3724,3490,3390,3725,8005,1179,3066, # 7654 +8006,3162,2373,4272,3726,2541,3163,3108,2740,4039,8007,3391,1556,2542,2292, 977, # 7670 +2887,2033,4040,1205,3392,8008,1765,3393,3164,2124,1271,1689, 714,4551,3491,8009, # 7686 +2328,3852, 533,4273,3605,2181, 617,8010,2464,3308,3492,2310,8011,8012,3165,8013, # 7702 +8014,3853,1987, 618, 427,2641,3493,3394,8015,8016,1244,1690,8017,2806,4274,4552, # 7718 +8018,3494,8019,8020,2279,1576, 473,3606,4275,3395, 972,8021,3607,8022,3067,8023, # 7734 +8024,4553,4554,8025,3727,4041,4042,8026, 153,4555, 356,8027,1891,2888,4276,2143, # 7750 + 408, 803,2352,8028,3854,8029,4277,1646,2570,2511,4556,4557,3855,8030,3856,4278, # 7766 +8031,2411,3396, 752,8032,8033,1961,2964,8034, 746,3012,2465,8035,4279,3728, 698, # 7782 +4558,1892,4280,3608,2543,4559,3609,3857,8036,3166,3397,8037,1823,1302,4043,2706, # 7798 +3858,1973,4281,8038,4282,3167, 823,1303,1288,1236,2848,3495,4044,3398, 774,3859, # 7814 +8039,1581,4560,1304,2849,3860,4561,8040,2435,2161,1083,3237,4283,4045,4284, 344, # 7830 +1173, 288,2311, 454,1683,8041,8042,1461,4562,4046,2589,8043,8044,4563, 985, 894, # 7846 +8045,3399,3168,8046,1913,2928,3729,1988,8047,2110,1974,8048,4047,8049,2571,1194, # 7862 + 425,8050,4564,3169,1245,3730,4285,8051,8052,2850,8053, 636,4565,1855,3861, 760, # 7878 +1799,8054,4286,2209,1508,4566,4048,1893,1684,2293,8055,8056,8057,4287,4288,2210, # 7894 + 479,8058,8059, 832,8060,4049,2489,8061,2965,2490,3731, 990,3109, 627,1814,2642, # 7910 +4289,1582,4290,2125,2111,3496,4567,8062, 799,4291,3170,8063,4568,2112,1737,3013, # 7926 +1018, 543, 754,4292,3309,1676,4569,4570,4050,8064,1489,8065,3497,8066,2614,2889, # 7942 +4051,8067,8068,2966,8069,8070,8071,8072,3171,4571,4572,2182,1722,8073,3238,3239, # 7958 +1842,3610,1715, 481, 365,1975,1856,8074,8075,1962,2491,4573,8076,2126,3611,3240, # 7974 + 433,1894,2063,2075,8077, 602,2741,8078,8079,8080,8081,8082,3014,1628,3400,8083, # 7990 +3172,4574,4052,2890,4575,2512,8084,2544,2772,8085,8086,8087,3310,4576,2891,8088, # 8006 +4577,8089,2851,4578,4579,1221,2967,4053,2513,8090,8091,8092,1867,1989,8093,8094, # 8022 +8095,1895,8096,8097,4580,1896,4054, 318,8098,2094,4055,4293,8099,8100, 485,8101, # 8038 + 938,3862, 553,2670, 116,8102,3863,3612,8103,3498,2671,2773,3401,3311,2807,8104, # 8054 +3613,2929,4056,1747,2930,2968,8105,8106, 207,8107,8108,2672,4581,2514,8109,3015, # 8070 + 890,3614,3864,8110,1877,3732,3402,8111,2183,2353,3403,1652,8112,8113,8114, 941, # 8086 +2294, 208,3499,4057,2019, 330,4294,3865,2892,2492,3733,4295,8115,8116,8117,8118, # 8102 +#Everything below is of no interest for detection purpose +2515,1613,4582,8119,3312,3866,2516,8120,4058,8121,1637,4059,2466,4583,3867,8122, # 8118 +2493,3016,3734,8123,8124,2192,8125,8126,2162,8127,8128,8129,8130,8131,8132,8133, # 8134 +8134,8135,8136,8137,8138,8139,8140,8141,8142,8143,8144,8145,8146,8147,8148,8149, # 8150 +8150,8151,8152,8153,8154,8155,8156,8157,8158,8159,8160,8161,8162,8163,8164,8165, # 8166 +8166,8167,8168,8169,8170,8171,8172,8173,8174,8175,8176,8177,8178,8179,8180,8181, # 8182 +8182,8183,8184,8185,8186,8187,8188,8189,8190,8191,8192,8193,8194,8195,8196,8197, # 8198 +8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8208,8209,8210,8211,8212,8213, # 8214 +8214,8215,8216,8217,8218,8219,8220,8221,8222,8223,8224,8225,8226,8227,8228,8229, # 8230 +8230,8231,8232,8233,8234,8235,8236,8237,8238,8239,8240,8241,8242,8243,8244,8245, # 8246 +8246,8247,8248,8249,8250,8251,8252,8253,8254,8255,8256,8257,8258,8259,8260,8261, # 8262 +8262,8263,8264,8265,8266,8267,8268,8269,8270,8271,8272,8273,8274,8275,8276,8277, # 8278 +8278,8279,8280,8281,8282,8283,8284,8285,8286,8287,8288,8289,8290,8291,8292,8293, # 8294 +8294,8295,8296,8297,8298,8299,8300,8301,8302,8303,8304,8305,8306,8307,8308,8309, # 8310 +8310,8311,8312,8313,8314,8315,8316,8317,8318,8319,8320,8321,8322,8323,8324,8325, # 8326 +8326,8327,8328,8329,8330,8331,8332,8333,8334,8335,8336,8337,8338,8339,8340,8341, # 8342 +8342,8343,8344,8345,8346,8347,8348,8349,8350,8351,8352,8353,8354,8355,8356,8357, # 8358 +8358,8359,8360,8361,8362,8363,8364,8365,8366,8367,8368,8369,8370,8371,8372,8373, # 8374 +8374,8375,8376,8377,8378,8379,8380,8381,8382,8383,8384,8385,8386,8387,8388,8389, # 8390 +8390,8391,8392,8393,8394,8395,8396,8397,8398,8399,8400,8401,8402,8403,8404,8405, # 8406 +8406,8407,8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,8420,8421, # 8422 +8422,8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,8433,8434,8435,8436,8437, # 8438 +8438,8439,8440,8441,8442,8443,8444,8445,8446,8447,8448,8449,8450,8451,8452,8453, # 8454 +8454,8455,8456,8457,8458,8459,8460,8461,8462,8463,8464,8465,8466,8467,8468,8469, # 8470 +8470,8471,8472,8473,8474,8475,8476,8477,8478,8479,8480,8481,8482,8483,8484,8485, # 8486 +8486,8487,8488,8489,8490,8491,8492,8493,8494,8495,8496,8497,8498,8499,8500,8501, # 8502 +8502,8503,8504,8505,8506,8507,8508,8509,8510,8511,8512,8513,8514,8515,8516,8517, # 8518 +8518,8519,8520,8521,8522,8523,8524,8525,8526,8527,8528,8529,8530,8531,8532,8533, # 8534 +8534,8535,8536,8537,8538,8539,8540,8541,8542,8543,8544,8545,8546,8547,8548,8549, # 8550 +8550,8551,8552,8553,8554,8555,8556,8557,8558,8559,8560,8561,8562,8563,8564,8565, # 8566 +8566,8567,8568,8569,8570,8571,8572,8573,8574,8575,8576,8577,8578,8579,8580,8581, # 8582 +8582,8583,8584,8585,8586,8587,8588,8589,8590,8591,8592,8593,8594,8595,8596,8597, # 8598 +8598,8599,8600,8601,8602,8603,8604,8605,8606,8607,8608,8609,8610,8611,8612,8613, # 8614 +8614,8615,8616,8617,8618,8619,8620,8621,8622,8623,8624,8625,8626,8627,8628,8629, # 8630 +8630,8631,8632,8633,8634,8635,8636,8637,8638,8639,8640,8641,8642,8643,8644,8645, # 8646 +8646,8647,8648,8649,8650,8651,8652,8653,8654,8655,8656,8657,8658,8659,8660,8661, # 8662 +8662,8663,8664,8665,8666,8667,8668,8669,8670,8671,8672,8673,8674,8675,8676,8677, # 8678 +8678,8679,8680,8681,8682,8683,8684,8685,8686,8687,8688,8689,8690,8691,8692,8693, # 8694 +8694,8695,8696,8697,8698,8699,8700,8701,8702,8703,8704,8705,8706,8707,8708,8709, # 8710 +8710,8711,8712,8713,8714,8715,8716,8717,8718,8719,8720,8721,8722,8723,8724,8725, # 8726 +8726,8727,8728,8729,8730,8731,8732,8733,8734,8735,8736,8737,8738,8739,8740,8741) # 8742 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/euctwprober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/euctwprober.py new file mode 100755 index 0000000..b073f13 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/euctwprober.py @@ -0,0 +1,41 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from mbcharsetprober import MultiByteCharSetProber +from codingstatemachine import CodingStateMachine +from chardistribution import EUCTWDistributionAnalysis +from mbcssm import EUCTWSMModel + +class EUCTWProber(MultiByteCharSetProber): + def __init__(self): + MultiByteCharSetProber.__init__(self) + self._mCodingSM = CodingStateMachine(EUCTWSMModel) + self._mDistributionAnalyzer = EUCTWDistributionAnalysis() + self.reset() + + def get_charset_name(self): + return "EUC-TW" diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/gb2312freq.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/gb2312freq.py new file mode 100755 index 0000000..7a4d5a1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/gb2312freq.py @@ -0,0 +1,471 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# GB2312 most frequently used character table +# +# Char to FreqOrder table , from hz6763 + +# 512 --> 0.79 -- 0.79 +# 1024 --> 0.92 -- 0.13 +# 2048 --> 0.98 -- 0.06 +# 6768 --> 1.00 -- 0.02 +# +# Ideal Distribution Ratio = 0.79135/(1-0.79135) = 3.79 +# Random Distribution Ration = 512 / (3755 - 512) = 0.157 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher that RDR + +GB2312_TYPICAL_DISTRIBUTION_RATIO = 0.9 + +GB2312_TABLE_SIZE = 3760 + +GB2312CharToFreqOrder = ( \ +1671, 749,1443,2364,3924,3807,2330,3921,1704,3463,2691,1511,1515, 572,3191,2205, +2361, 224,2558, 479,1711, 963,3162, 440,4060,1905,2966,2947,3580,2647,3961,3842, +2204, 869,4207, 970,2678,5626,2944,2956,1479,4048, 514,3595, 588,1346,2820,3409, + 249,4088,1746,1873,2047,1774, 581,1813, 358,1174,3590,1014,1561,4844,2245, 670, +1636,3112, 889,1286, 953, 556,2327,3060,1290,3141, 613, 185,3477,1367, 850,3820, +1715,2428,2642,2303,2732,3041,2562,2648,3566,3946,1349, 388,3098,2091,1360,3585, + 152,1687,1539, 738,1559, 59,1232,2925,2267,1388,1249,1741,1679,2960, 151,1566, +1125,1352,4271, 924,4296, 385,3166,4459, 310,1245,2850, 70,3285,2729,3534,3575, +2398,3298,3466,1960,2265, 217,3647, 864,1909,2084,4401,2773,1010,3269,5152, 853, +3051,3121,1244,4251,1895, 364,1499,1540,2313,1180,3655,2268, 562, 715,2417,3061, + 544, 336,3768,2380,1752,4075, 950, 280,2425,4382, 183,2759,3272, 333,4297,2155, +1688,2356,1444,1039,4540, 736,1177,3349,2443,2368,2144,2225, 565, 196,1482,3406, + 927,1335,4147, 692, 878,1311,1653,3911,3622,1378,4200,1840,2969,3149,2126,1816, +2534,1546,2393,2760, 737,2494, 13, 447, 245,2747, 38,2765,2129,2589,1079, 606, + 360, 471,3755,2890, 404, 848, 699,1785,1236, 370,2221,1023,3746,2074,2026,2023, +2388,1581,2119, 812,1141,3091,2536,1519, 804,2053, 406,1596,1090, 784, 548,4414, +1806,2264,2936,1100, 343,4114,5096, 622,3358, 743,3668,1510,1626,5020,3567,2513, +3195,4115,5627,2489,2991, 24,2065,2697,1087,2719, 48,1634, 315, 68, 985,2052, + 198,2239,1347,1107,1439, 597,2366,2172, 871,3307, 919,2487,2790,1867, 236,2570, +1413,3794, 906,3365,3381,1701,1982,1818,1524,2924,1205, 616,2586,2072,2004, 575, + 253,3099, 32,1365,1182, 197,1714,2454,1201, 554,3388,3224,2748, 756,2587, 250, +2567,1507,1517,3529,1922,2761,2337,3416,1961,1677,2452,2238,3153, 615, 911,1506, +1474,2495,1265,1906,2749,3756,3280,2161, 898,2714,1759,3450,2243,2444, 563, 26, +3286,2266,3769,3344,2707,3677, 611,1402, 531,1028,2871,4548,1375, 261,2948, 835, +1190,4134, 353, 840,2684,1900,3082,1435,2109,1207,1674, 329,1872,2781,4055,2686, +2104, 608,3318,2423,2957,2768,1108,3739,3512,3271,3985,2203,1771,3520,1418,2054, +1681,1153, 225,1627,2929, 162,2050,2511,3687,1954, 124,1859,2431,1684,3032,2894, + 585,4805,3969,2869,2704,2088,2032,2095,3656,2635,4362,2209, 256, 518,2042,2105, +3777,3657, 643,2298,1148,1779, 190, 989,3544, 414, 11,2135,2063,2979,1471, 403, +3678, 126, 770,1563, 671,2499,3216,2877, 600,1179, 307,2805,4937,1268,1297,2694, + 252,4032,1448,1494,1331,1394, 127,2256, 222,1647,1035,1481,3056,1915,1048, 873, +3651, 210, 33,1608,2516, 200,1520, 415, 102, 0,3389,1287, 817, 91,3299,2940, + 836,1814, 549,2197,1396,1669,2987,3582,2297,2848,4528,1070, 687, 20,1819, 121, +1552,1364,1461,1968,2617,3540,2824,2083, 177, 948,4938,2291, 110,4549,2066, 648, +3359,1755,2110,2114,4642,4845,1693,3937,3308,1257,1869,2123, 208,1804,3159,2992, +2531,2549,3361,2418,1350,2347,2800,2568,1291,2036,2680, 72, 842,1990, 212,1233, +1154,1586, 75,2027,3410,4900,1823,1337,2710,2676, 728,2810,1522,3026,4995, 157, + 755,1050,4022, 710, 785,1936,2194,2085,1406,2777,2400, 150,1250,4049,1206, 807, +1910, 534, 529,3309,1721,1660, 274, 39,2827, 661,2670,1578, 925,3248,3815,1094, +4278,4901,4252, 41,1150,3747,2572,2227,4501,3658,4902,3813,3357,3617,2884,2258, + 887, 538,4187,3199,1294,2439,3042,2329,2343,2497,1255, 107, 543,1527, 521,3478, +3568, 194,5062, 15, 961,3870,1241,1192,2664, 66,5215,3260,2111,1295,1127,2152, +3805,4135, 901,1164,1976, 398,1278, 530,1460, 748, 904,1054,1966,1426, 53,2909, + 509, 523,2279,1534, 536,1019, 239,1685, 460,2353, 673,1065,2401,3600,4298,2272, +1272,2363, 284,1753,3679,4064,1695, 81, 815,2677,2757,2731,1386, 859, 500,4221, +2190,2566, 757,1006,2519,2068,1166,1455, 337,2654,3203,1863,1682,1914,3025,1252, +1409,1366, 847, 714,2834,2038,3209, 964,2970,1901, 885,2553,1078,1756,3049, 301, +1572,3326, 688,2130,1996,2429,1805,1648,2930,3421,2750,3652,3088, 262,1158,1254, + 389,1641,1812, 526,1719, 923,2073,1073,1902, 468, 489,4625,1140, 857,2375,3070, +3319,2863, 380, 116,1328,2693,1161,2244, 273,1212,1884,2769,3011,1775,1142, 461, +3066,1200,2147,2212, 790, 702,2695,4222,1601,1058, 434,2338,5153,3640, 67,2360, +4099,2502, 618,3472,1329, 416,1132, 830,2782,1807,2653,3211,3510,1662, 192,2124, + 296,3979,1739,1611,3684, 23, 118, 324, 446,1239,1225, 293,2520,3814,3795,2535, +3116, 17,1074, 467,2692,2201, 387,2922, 45,1326,3055,1645,3659,2817, 958, 243, +1903,2320,1339,2825,1784,3289, 356, 576, 865,2315,2381,3377,3916,1088,3122,1713, +1655, 935, 628,4689,1034,1327, 441, 800, 720, 894,1979,2183,1528,5289,2702,1071, +4046,3572,2399,1571,3281, 79, 761,1103, 327, 134, 758,1899,1371,1615, 879, 442, + 215,2605,2579, 173,2048,2485,1057,2975,3317,1097,2253,3801,4263,1403,1650,2946, + 814,4968,3487,1548,2644,1567,1285, 2, 295,2636, 97, 946,3576, 832, 141,4257, +3273, 760,3821,3521,3156,2607, 949,1024,1733,1516,1803,1920,2125,2283,2665,3180, +1501,2064,3560,2171,1592, 803,3518,1416, 732,3897,4258,1363,1362,2458, 119,1427, + 602,1525,2608,1605,1639,3175, 694,3064, 10, 465, 76,2000,4846,4208, 444,3781, +1619,3353,2206,1273,3796, 740,2483, 320,1723,2377,3660,2619,1359,1137,1762,1724, +2345,2842,1850,1862, 912, 821,1866, 612,2625,1735,2573,3369,1093, 844, 89, 937, + 930,1424,3564,2413,2972,1004,3046,3019,2011, 711,3171,1452,4178, 428, 801,1943, + 432, 445,2811, 206,4136,1472, 730, 349, 73, 397,2802,2547, 998,1637,1167, 789, + 396,3217, 154,1218, 716,1120,1780,2819,4826,1931,3334,3762,2139,1215,2627, 552, +3664,3628,3232,1405,2383,3111,1356,2652,3577,3320,3101,1703, 640,1045,1370,1246, +4996, 371,1575,2436,1621,2210, 984,4033,1734,2638, 16,4529, 663,2755,3255,1451, +3917,2257,1253,1955,2234,1263,2951, 214,1229, 617, 485, 359,1831,1969, 473,2310, + 750,2058, 165, 80,2864,2419, 361,4344,2416,2479,1134, 796,3726,1266,2943, 860, +2715, 938, 390,2734,1313,1384, 248, 202, 877,1064,2854, 522,3907, 279,1602, 297, +2357, 395,3740, 137,2075, 944,4089,2584,1267,3802, 62,1533,2285, 178, 176, 780, +2440, 201,3707, 590, 478,1560,4354,2117,1075, 30, 74,4643,4004,1635,1441,2745, + 776,2596, 238,1077,1692,1912,2844, 605, 499,1742,3947, 241,3053, 980,1749, 936, +2640,4511,2582, 515,1543,2162,5322,2892,2993, 890,2148,1924, 665,1827,3581,1032, + 968,3163, 339,1044,1896, 270, 583,1791,1720,4367,1194,3488,3669, 43,2523,1657, + 163,2167, 290,1209,1622,3378, 550, 634,2508,2510, 695,2634,2384,2512,1476,1414, + 220,1469,2341,2138,2852,3183,2900,4939,2865,3502,1211,3680, 854,3227,1299,2976, +3172, 186,2998,1459, 443,1067,3251,1495, 321,1932,3054, 909, 753,1410,1828, 436, +2441,1119,1587,3164,2186,1258, 227, 231,1425,1890,3200,3942, 247, 959, 725,5254, +2741, 577,2158,2079, 929, 120, 174, 838,2813, 591,1115, 417,2024, 40,3240,1536, +1037, 291,4151,2354, 632,1298,2406,2500,3535,1825,1846,3451, 205,1171, 345,4238, + 18,1163, 811, 685,2208,1217, 425,1312,1508,1175,4308,2552,1033, 587,1381,3059, +2984,3482, 340,1316,4023,3972, 792,3176, 519, 777,4690, 918, 933,4130,2981,3741, + 90,3360,2911,2200,5184,4550, 609,3079,2030, 272,3379,2736, 363,3881,1130,1447, + 286, 779, 357,1169,3350,3137,1630,1220,2687,2391, 747,1277,3688,2618,2682,2601, +1156,3196,5290,4034,3102,1689,3596,3128, 874, 219,2783, 798, 508,1843,2461, 269, +1658,1776,1392,1913,2983,3287,2866,2159,2372, 829,4076, 46,4253,2873,1889,1894, + 915,1834,1631,2181,2318, 298, 664,2818,3555,2735, 954,3228,3117, 527,3511,2173, + 681,2712,3033,2247,2346,3467,1652, 155,2164,3382, 113,1994, 450, 899, 494, 994, +1237,2958,1875,2336,1926,3727, 545,1577,1550, 633,3473, 204,1305,3072,2410,1956, +2471, 707,2134, 841,2195,2196,2663,3843,1026,4940, 990,3252,4997, 368,1092, 437, +3212,3258,1933,1829, 675,2977,2893, 412, 943,3723,4644,3294,3283,2230,2373,5154, +2389,2241,2661,2323,1404,2524, 593, 787, 677,3008,1275,2059, 438,2709,2609,2240, +2269,2246,1446, 36,1568,1373,3892,1574,2301,1456,3962, 693,2276,5216,2035,1143, +2720,1919,1797,1811,2763,4137,2597,1830,1699,1488,1198,2090, 424,1694, 312,3634, +3390,4179,3335,2252,1214, 561,1059,3243,2295,2561, 975,5155,2321,2751,3772, 472, +1537,3282,3398,1047,2077,2348,2878,1323,3340,3076, 690,2906, 51, 369, 170,3541, +1060,2187,2688,3670,2541,1083,1683, 928,3918, 459, 109,4427, 599,3744,4286, 143, +2101,2730,2490, 82,1588,3036,2121, 281,1860, 477,4035,1238,2812,3020,2716,3312, +1530,2188,2055,1317, 843, 636,1808,1173,3495, 649, 181,1002, 147,3641,1159,2414, +3750,2289,2795, 813,3123,2610,1136,4368, 5,3391,4541,2174, 420, 429,1728, 754, +1228,2115,2219, 347,2223,2733, 735,1518,3003,2355,3134,1764,3948,3329,1888,2424, +1001,1234,1972,3321,3363,1672,1021,1450,1584, 226, 765, 655,2526,3404,3244,2302, +3665, 731, 594,2184, 319,1576, 621, 658,2656,4299,2099,3864,1279,2071,2598,2739, + 795,3086,3699,3908,1707,2352,2402,1382,3136,2475,1465,4847,3496,3865,1085,3004, +2591,1084, 213,2287,1963,3565,2250, 822, 793,4574,3187,1772,1789,3050, 595,1484, +1959,2770,1080,2650, 456, 422,2996, 940,3322,4328,4345,3092,2742, 965,2784, 739, +4124, 952,1358,2498,2949,2565, 332,2698,2378, 660,2260,2473,4194,3856,2919, 535, +1260,2651,1208,1428,1300,1949,1303,2942, 433,2455,2450,1251,1946, 614,1269, 641, +1306,1810,2737,3078,2912, 564,2365,1419,1415,1497,4460,2367,2185,1379,3005,1307, +3218,2175,1897,3063, 682,1157,4040,4005,1712,1160,1941,1399, 394, 402,2952,1573, +1151,2986,2404, 862, 299,2033,1489,3006, 346, 171,2886,3401,1726,2932, 168,2533, + 47,2507,1030,3735,1145,3370,1395,1318,1579,3609,4560,2857,4116,1457,2529,1965, + 504,1036,2690,2988,2405, 745,5871, 849,2397,2056,3081, 863,2359,3857,2096, 99, +1397,1769,2300,4428,1643,3455,1978,1757,3718,1440, 35,4879,3742,1296,4228,2280, + 160,5063,1599,2013, 166, 520,3479,1646,3345,3012, 490,1937,1545,1264,2182,2505, +1096,1188,1369,1436,2421,1667,2792,2460,1270,2122, 727,3167,2143, 806,1706,1012, +1800,3037, 960,2218,1882, 805, 139,2456,1139,1521, 851,1052,3093,3089, 342,2039, + 744,5097,1468,1502,1585,2087, 223, 939, 326,2140,2577, 892,2481,1623,4077, 982, +3708, 135,2131, 87,2503,3114,2326,1106, 876,1616, 547,2997,2831,2093,3441,4530, +4314, 9,3256,4229,4148, 659,1462,1986,1710,2046,2913,2231,4090,4880,5255,3392, +3274,1368,3689,4645,1477, 705,3384,3635,1068,1529,2941,1458,3782,1509, 100,1656, +2548, 718,2339, 408,1590,2780,3548,1838,4117,3719,1345,3530, 717,3442,2778,3220, +2898,1892,4590,3614,3371,2043,1998,1224,3483, 891, 635, 584,2559,3355, 733,1766, +1729,1172,3789,1891,2307, 781,2982,2271,1957,1580,5773,2633,2005,4195,3097,1535, +3213,1189,1934,5693,3262, 586,3118,1324,1598, 517,1564,2217,1868,1893,4445,3728, +2703,3139,1526,1787,1992,3882,2875,1549,1199,1056,2224,1904,2711,5098,4287, 338, +1993,3129,3489,2689,1809,2815,1997, 957,1855,3898,2550,3275,3057,1105,1319, 627, +1505,1911,1883,3526, 698,3629,3456,1833,1431, 746, 77,1261,2017,2296,1977,1885, + 125,1334,1600, 525,1798,1109,2222,1470,1945, 559,2236,1186,3443,2476,1929,1411, +2411,3135,1777,3372,2621,1841,1613,3229, 668,1430,1839,2643,2916, 195,1989,2671, +2358,1387, 629,3205,2293,5256,4439, 123,1310, 888,1879,4300,3021,3605,1003,1162, +3192,2910,2010, 140,2395,2859, 55,1082,2012,2901, 662, 419,2081,1438, 680,2774, +4654,3912,1620,1731,1625,5035,4065,2328, 512,1344, 802,5443,2163,2311,2537, 524, +3399, 98,1155,2103,1918,2606,3925,2816,1393,2465,1504,3773,2177,3963,1478,4346, + 180,1113,4655,3461,2028,1698, 833,2696,1235,1322,1594,4408,3623,3013,3225,2040, +3022, 541,2881, 607,3632,2029,1665,1219, 639,1385,1686,1099,2803,3231,1938,3188, +2858, 427, 676,2772,1168,2025, 454,3253,2486,3556, 230,1950, 580, 791,1991,1280, +1086,1974,2034, 630, 257,3338,2788,4903,1017, 86,4790, 966,2789,1995,1696,1131, + 259,3095,4188,1308, 179,1463,5257, 289,4107,1248, 42,3413,1725,2288, 896,1947, + 774,4474,4254, 604,3430,4264, 392,2514,2588, 452, 237,1408,3018, 988,4531,1970, +3034,3310, 540,2370,1562,1288,2990, 502,4765,1147, 4,1853,2708, 207, 294,2814, +4078,2902,2509, 684, 34,3105,3532,2551, 644, 709,2801,2344, 573,1727,3573,3557, +2021,1081,3100,4315,2100,3681, 199,2263,1837,2385, 146,3484,1195,2776,3949, 997, +1939,3973,1008,1091,1202,1962,1847,1149,4209,5444,1076, 493, 117,5400,2521, 972, +1490,2934,1796,4542,2374,1512,2933,2657, 413,2888,1135,2762,2314,2156,1355,2369, + 766,2007,2527,2170,3124,2491,2593,2632,4757,2437, 234,3125,3591,1898,1750,1376, +1942,3468,3138, 570,2127,2145,3276,4131, 962, 132,1445,4196, 19, 941,3624,3480, +3366,1973,1374,4461,3431,2629, 283,2415,2275, 808,2887,3620,2112,2563,1353,3610, + 955,1089,3103,1053, 96, 88,4097, 823,3808,1583, 399, 292,4091,3313, 421,1128, + 642,4006, 903,2539,1877,2082, 596, 29,4066,1790, 722,2157, 130, 995,1569, 769, +1485, 464, 513,2213, 288,1923,1101,2453,4316, 133, 486,2445, 50, 625, 487,2207, + 57, 423, 481,2962, 159,3729,1558, 491, 303, 482, 501, 240,2837, 112,3648,2392, +1783, 362, 8,3433,3422, 610,2793,3277,1390,1284,1654, 21,3823, 734, 367, 623, + 193, 287, 374,1009,1483, 816, 476, 313,2255,2340,1262,2150,2899,1146,2581, 782, +2116,1659,2018,1880, 255,3586,3314,1110,2867,2137,2564, 986,2767,5185,2006, 650, + 158, 926, 762, 881,3157,2717,2362,3587, 306,3690,3245,1542,3077,2427,1691,2478, +2118,2985,3490,2438, 539,2305, 983, 129,1754, 355,4201,2386, 827,2923, 104,1773, +2838,2771, 411,2905,3919, 376, 767, 122,1114, 828,2422,1817,3506, 266,3460,1007, +1609,4998, 945,2612,4429,2274, 726,1247,1964,2914,2199,2070,4002,4108, 657,3323, +1422, 579, 455,2764,4737,1222,2895,1670, 824,1223,1487,2525, 558, 861,3080, 598, +2659,2515,1967, 752,2583,2376,2214,4180, 977, 704,2464,4999,2622,4109,1210,2961, + 819,1541, 142,2284, 44, 418, 457,1126,3730,4347,4626,1644,1876,3671,1864, 302, +1063,5694, 624, 723,1984,3745,1314,1676,2488,1610,1449,3558,3569,2166,2098, 409, +1011,2325,3704,2306, 818,1732,1383,1824,1844,3757, 999,2705,3497,1216,1423,2683, +2426,2954,2501,2726,2229,1475,2554,5064,1971,1794,1666,2014,1343, 783, 724, 191, +2434,1354,2220,5065,1763,2752,2472,4152, 131, 175,2885,3434, 92,1466,4920,2616, +3871,3872,3866, 128,1551,1632, 669,1854,3682,4691,4125,1230, 188,2973,3290,1302, +1213, 560,3266, 917, 763,3909,3249,1760, 868,1958, 764,1782,2097, 145,2277,3774, +4462, 64,1491,3062, 971,2132,3606,2442, 221,1226,1617, 218, 323,1185,3207,3147, + 571, 619,1473,1005,1744,2281, 449,1887,2396,3685, 275, 375,3816,1743,3844,3731, + 845,1983,2350,4210,1377, 773, 967,3499,3052,3743,2725,4007,1697,1022,3943,1464, +3264,2855,2722,1952,1029,2839,2467, 84,4383,2215, 820,1391,2015,2448,3672, 377, +1948,2168, 797,2545,3536,2578,2645, 94,2874,1678, 405,1259,3071, 771, 546,1315, + 470,1243,3083, 895,2468, 981, 969,2037, 846,4181, 653,1276,2928, 14,2594, 557, +3007,2474, 156, 902,1338,1740,2574, 537,2518, 973,2282,2216,2433,1928, 138,2903, +1293,2631,1612, 646,3457, 839,2935, 111, 496,2191,2847, 589,3186, 149,3994,2060, +4031,2641,4067,3145,1870, 37,3597,2136,1025,2051,3009,3383,3549,1121,1016,3261, +1301, 251,2446,2599,2153, 872,3246, 637, 334,3705, 831, 884, 921,3065,3140,4092, +2198,1944, 246,2964, 108,2045,1152,1921,2308,1031, 203,3173,4170,1907,3890, 810, +1401,2003,1690, 506, 647,1242,2828,1761,1649,3208,2249,1589,3709,2931,5156,1708, + 498, 666,2613, 834,3817,1231, 184,2851,1124, 883,3197,2261,3710,1765,1553,2658, +1178,2639,2351, 93,1193, 942,2538,2141,4402, 235,1821, 870,1591,2192,1709,1871, +3341,1618,4126,2595,2334, 603, 651, 69, 701, 268,2662,3411,2555,1380,1606, 503, + 448, 254,2371,2646, 574,1187,2309,1770, 322,2235,1292,1801, 305, 566,1133, 229, +2067,2057, 706, 167, 483,2002,2672,3295,1820,3561,3067, 316, 378,2746,3452,1112, + 136,1981, 507,1651,2917,1117, 285,4591, 182,2580,3522,1304, 335,3303,1835,2504, +1795,1792,2248, 674,1018,2106,2449,1857,2292,2845, 976,3047,1781,2600,2727,1389, +1281, 52,3152, 153, 265,3950, 672,3485,3951,4463, 430,1183, 365, 278,2169, 27, +1407,1336,2304, 209,1340,1730,2202,1852,2403,2883, 979,1737,1062, 631,2829,2542, +3876,2592, 825,2086,2226,3048,3625, 352,1417,3724, 542, 991, 431,1351,3938,1861, +2294, 826,1361,2927,3142,3503,1738, 463,2462,2723, 582,1916,1595,2808, 400,3845, +3891,2868,3621,2254, 58,2492,1123, 910,2160,2614,1372,1603,1196,1072,3385,1700, +3267,1980, 696, 480,2430, 920, 799,1570,2920,1951,2041,4047,2540,1321,4223,2469, +3562,2228,1271,2602, 401,2833,3351,2575,5157, 907,2312,1256, 410, 263,3507,1582, + 996, 678,1849,2316,1480, 908,3545,2237, 703,2322, 667,1826,2849,1531,2604,2999, +2407,3146,2151,2630,1786,3711, 469,3542, 497,3899,2409, 858, 837,4446,3393,1274, + 786, 620,1845,2001,3311, 484, 308,3367,1204,1815,3691,2332,1532,2557,1842,2020, +2724,1927,2333,4440, 567, 22,1673,2728,4475,1987,1858,1144,1597, 101,1832,3601, + 12, 974,3783,4391, 951,1412, 1,3720, 453,4608,4041, 528,1041,1027,3230,2628, +1129, 875,1051,3291,1203,2262,1069,2860,2799,2149,2615,3278, 144,1758,3040, 31, + 475,1680, 366,2685,3184, 311,1642,4008,2466,5036,1593,1493,2809, 216,1420,1668, + 233, 304,2128,3284, 232,1429,1768,1040,2008,3407,2740,2967,2543, 242,2133, 778, +1565,2022,2620, 505,2189,2756,1098,2273, 372,1614, 708, 553,2846,2094,2278, 169, +3626,2835,4161, 228,2674,3165, 809,1454,1309, 466,1705,1095, 900,3423, 880,2667, +3751,5258,2317,3109,2571,4317,2766,1503,1342, 866,4447,1118, 63,2076, 314,1881, +1348,1061, 172, 978,3515,1747, 532, 511,3970, 6, 601, 905,2699,3300,1751, 276, +1467,3725,2668, 65,4239,2544,2779,2556,1604, 578,2451,1802, 992,2331,2624,1320, +3446, 713,1513,1013, 103,2786,2447,1661, 886,1702, 916, 654,3574,2031,1556, 751, +2178,2821,2179,1498,1538,2176, 271, 914,2251,2080,1325, 638,1953,2937,3877,2432, +2754, 95,3265,1716, 260,1227,4083, 775, 106,1357,3254, 426,1607, 555,2480, 772, +1985, 244,2546, 474, 495,1046,2611,1851,2061, 71,2089,1675,2590, 742,3758,2843, +3222,1433, 267,2180,2576,2826,2233,2092,3913,2435, 956,1745,3075, 856,2113,1116, + 451, 3,1988,2896,1398, 993,2463,1878,2049,1341,2718,2721,2870,2108, 712,2904, +4363,2753,2324, 277,2872,2349,2649, 384, 987, 435, 691,3000, 922, 164,3939, 652, +1500,1184,4153,2482,3373,2165,4848,2335,3775,3508,3154,2806,2830,1554,2102,1664, +2530,1434,2408, 893,1547,2623,3447,2832,2242,2532,3169,2856,3223,2078, 49,3770, +3469, 462, 318, 656,2259,3250,3069, 679,1629,2758, 344,1138,1104,3120,1836,1283, +3115,2154,1437,4448, 934, 759,1999, 794,2862,1038, 533,2560,1722,2342, 855,2626, +1197,1663,4476,3127, 85,4240,2528, 25,1111,1181,3673, 407,3470,4561,2679,2713, + 768,1925,2841,3986,1544,1165, 932, 373,1240,2146,1930,2673, 721,4766, 354,4333, + 391,2963, 187, 61,3364,1442,1102, 330,1940,1767, 341,3809,4118, 393,2496,2062, +2211, 105, 331, 300, 439, 913,1332, 626, 379,3304,1557, 328, 689,3952, 309,1555, + 931, 317,2517,3027, 325, 569, 686,2107,3084, 60,1042,1333,2794, 264,3177,4014, +1628, 258,3712, 7,4464,1176,1043,1778, 683, 114,1975, 78,1492, 383,1886, 510, + 386, 645,5291,2891,2069,3305,4138,3867,2939,2603,2493,1935,1066,1848,3588,1015, +1282,1289,4609, 697,1453,3044,2666,3611,1856,2412, 54, 719,1330, 568,3778,2459, +1748, 788, 492, 551,1191,1000, 488,3394,3763, 282,1799, 348,2016,1523,3155,2390, +1049, 382,2019,1788,1170, 729,2968,3523, 897,3926,2785,2938,3292, 350,2319,3238, +1718,1717,2655,3453,3143,4465, 161,2889,2980,2009,1421, 56,1908,1640,2387,2232, +1917,1874,2477,4921, 148, 83,3438, 592,4245,2882,1822,1055, 741, 115,1496,1624, + 381,1638,4592,1020, 516,3214, 458, 947,4575,1432, 211,1514,2926,1865,2142, 189, + 852,1221,1400,1486, 882,2299,4036, 351, 28,1122, 700,6479,6480,6481,6482,6483, # last 512 +#Everything below is of no interest for detection purpose +5508,6484,3900,3414,3974,4441,4024,3537,4037,5628,5099,3633,6485,3148,6486,3636, +5509,3257,5510,5973,5445,5872,4941,4403,3174,4627,5873,6276,2286,4230,5446,5874, +5122,6102,6103,4162,5447,5123,5323,4849,6277,3980,3851,5066,4246,5774,5067,6278, +3001,2807,5695,3346,5775,5974,5158,5448,6487,5975,5976,5776,3598,6279,5696,4806, +4211,4154,6280,6488,6489,6490,6281,4212,5037,3374,4171,6491,4562,4807,4722,4827, +5977,6104,4532,4079,5159,5324,5160,4404,3858,5359,5875,3975,4288,4610,3486,4512, +5325,3893,5360,6282,6283,5560,2522,4231,5978,5186,5449,2569,3878,6284,5401,3578, +4415,6285,4656,5124,5979,2506,4247,4449,3219,3417,4334,4969,4329,6492,4576,4828, +4172,4416,4829,5402,6286,3927,3852,5361,4369,4830,4477,4867,5876,4173,6493,6105, +4657,6287,6106,5877,5450,6494,4155,4868,5451,3700,5629,4384,6288,6289,5878,3189, +4881,6107,6290,6495,4513,6496,4692,4515,4723,5100,3356,6497,6291,3810,4080,5561, +3570,4430,5980,6498,4355,5697,6499,4724,6108,6109,3764,4050,5038,5879,4093,3226, +6292,5068,5217,4693,3342,5630,3504,4831,4377,4466,4309,5698,4431,5777,6293,5778, +4272,3706,6110,5326,3752,4676,5327,4273,5403,4767,5631,6500,5699,5880,3475,5039, +6294,5562,5125,4348,4301,4482,4068,5126,4593,5700,3380,3462,5981,5563,3824,5404, +4970,5511,3825,4738,6295,6501,5452,4516,6111,5881,5564,6502,6296,5982,6503,4213, +4163,3454,6504,6112,4009,4450,6113,4658,6297,6114,3035,6505,6115,3995,4904,4739, +4563,4942,4110,5040,3661,3928,5362,3674,6506,5292,3612,4791,5565,4149,5983,5328, +5259,5021,4725,4577,4564,4517,4364,6298,5405,4578,5260,4594,4156,4157,5453,3592, +3491,6507,5127,5512,4709,4922,5984,5701,4726,4289,6508,4015,6116,5128,4628,3424, +4241,5779,6299,4905,6509,6510,5454,5702,5780,6300,4365,4923,3971,6511,5161,3270, +3158,5985,4100, 867,5129,5703,6117,5363,3695,3301,5513,4467,6118,6512,5455,4232, +4242,4629,6513,3959,4478,6514,5514,5329,5986,4850,5162,5566,3846,4694,6119,5456, +4869,5781,3779,6301,5704,5987,5515,4710,6302,5882,6120,4392,5364,5705,6515,6121, +6516,6517,3736,5988,5457,5989,4695,2457,5883,4551,5782,6303,6304,6305,5130,4971, +6122,5163,6123,4870,3263,5365,3150,4871,6518,6306,5783,5069,5706,3513,3498,4409, +5330,5632,5366,5458,5459,3991,5990,4502,3324,5991,5784,3696,4518,5633,4119,6519, +4630,5634,4417,5707,4832,5992,3418,6124,5993,5567,4768,5218,6520,4595,3458,5367, +6125,5635,6126,4202,6521,4740,4924,6307,3981,4069,4385,6308,3883,2675,4051,3834, +4302,4483,5568,5994,4972,4101,5368,6309,5164,5884,3922,6127,6522,6523,5261,5460, +5187,4164,5219,3538,5516,4111,3524,5995,6310,6311,5369,3181,3386,2484,5188,3464, +5569,3627,5708,6524,5406,5165,4677,4492,6312,4872,4851,5885,4468,5996,6313,5709, +5710,6128,2470,5886,6314,5293,4882,5785,3325,5461,5101,6129,5711,5786,6525,4906, +6526,6527,4418,5887,5712,4808,2907,3701,5713,5888,6528,3765,5636,5331,6529,6530, +3593,5889,3637,4943,3692,5714,5787,4925,6315,6130,5462,4405,6131,6132,6316,5262, +6531,6532,5715,3859,5716,5070,4696,5102,3929,5788,3987,4792,5997,6533,6534,3920, +4809,5000,5998,6535,2974,5370,6317,5189,5263,5717,3826,6536,3953,5001,4883,3190, +5463,5890,4973,5999,4741,6133,6134,3607,5570,6000,4711,3362,3630,4552,5041,6318, +6001,2950,2953,5637,4646,5371,4944,6002,2044,4120,3429,6319,6537,5103,4833,6538, +6539,4884,4647,3884,6003,6004,4758,3835,5220,5789,4565,5407,6540,6135,5294,4697, +4852,6320,6321,3206,4907,6541,6322,4945,6542,6136,6543,6323,6005,4631,3519,6544, +5891,6545,5464,3784,5221,6546,5571,4659,6547,6324,6137,5190,6548,3853,6549,4016, +4834,3954,6138,5332,3827,4017,3210,3546,4469,5408,5718,3505,4648,5790,5131,5638, +5791,5465,4727,4318,6325,6326,5792,4553,4010,4698,3439,4974,3638,4335,3085,6006, +5104,5042,5166,5892,5572,6327,4356,4519,5222,5573,5333,5793,5043,6550,5639,5071, +4503,6328,6139,6551,6140,3914,3901,5372,6007,5640,4728,4793,3976,3836,4885,6552, +4127,6553,4451,4102,5002,6554,3686,5105,6555,5191,5072,5295,4611,5794,5296,6556, +5893,5264,5894,4975,5466,5265,4699,4976,4370,4056,3492,5044,4886,6557,5795,4432, +4769,4357,5467,3940,4660,4290,6141,4484,4770,4661,3992,6329,4025,4662,5022,4632, +4835,4070,5297,4663,4596,5574,5132,5409,5895,6142,4504,5192,4664,5796,5896,3885, +5575,5797,5023,4810,5798,3732,5223,4712,5298,4084,5334,5468,6143,4052,4053,4336, +4977,4794,6558,5335,4908,5576,5224,4233,5024,4128,5469,5225,4873,6008,5045,4729, +4742,4633,3675,4597,6559,5897,5133,5577,5003,5641,5719,6330,6560,3017,2382,3854, +4406,4811,6331,4393,3964,4946,6561,2420,3722,6562,4926,4378,3247,1736,4442,6332, +5134,6333,5226,3996,2918,5470,4319,4003,4598,4743,4744,4485,3785,3902,5167,5004, +5373,4394,5898,6144,4874,1793,3997,6334,4085,4214,5106,5642,4909,5799,6009,4419, +4189,3330,5899,4165,4420,5299,5720,5227,3347,6145,4081,6335,2876,3930,6146,3293, +3786,3910,3998,5900,5300,5578,2840,6563,5901,5579,6147,3531,5374,6564,6565,5580, +4759,5375,6566,6148,3559,5643,6336,6010,5517,6337,6338,5721,5902,3873,6011,6339, +6567,5518,3868,3649,5722,6568,4771,4947,6569,6149,4812,6570,2853,5471,6340,6341, +5644,4795,6342,6012,5723,6343,5724,6013,4349,6344,3160,6150,5193,4599,4514,4493, +5168,4320,6345,4927,3666,4745,5169,5903,5005,4928,6346,5725,6014,4730,4203,5046, +4948,3395,5170,6015,4150,6016,5726,5519,6347,5047,3550,6151,6348,4197,4310,5904, +6571,5581,2965,6152,4978,3960,4291,5135,6572,5301,5727,4129,4026,5905,4853,5728, +5472,6153,6349,4533,2700,4505,5336,4678,3583,5073,2994,4486,3043,4554,5520,6350, +6017,5800,4487,6351,3931,4103,5376,6352,4011,4321,4311,4190,5136,6018,3988,3233, +4350,5906,5645,4198,6573,5107,3432,4191,3435,5582,6574,4139,5410,6353,5411,3944, +5583,5074,3198,6575,6354,4358,6576,5302,4600,5584,5194,5412,6577,6578,5585,5413, +5303,4248,5414,3879,4433,6579,4479,5025,4854,5415,6355,4760,4772,3683,2978,4700, +3797,4452,3965,3932,3721,4910,5801,6580,5195,3551,5907,3221,3471,3029,6019,3999, +5908,5909,5266,5267,3444,3023,3828,3170,4796,5646,4979,4259,6356,5647,5337,3694, +6357,5648,5338,4520,4322,5802,3031,3759,4071,6020,5586,4836,4386,5048,6581,3571, +4679,4174,4949,6154,4813,3787,3402,3822,3958,3215,3552,5268,4387,3933,4950,4359, +6021,5910,5075,3579,6358,4234,4566,5521,6359,3613,5049,6022,5911,3375,3702,3178, +4911,5339,4521,6582,6583,4395,3087,3811,5377,6023,6360,6155,4027,5171,5649,4421, +4249,2804,6584,2270,6585,4000,4235,3045,6156,5137,5729,4140,4312,3886,6361,4330, +6157,4215,6158,3500,3676,4929,4331,3713,4930,5912,4265,3776,3368,5587,4470,4855, +3038,4980,3631,6159,6160,4132,4680,6161,6362,3923,4379,5588,4255,6586,4121,6587, +6363,4649,6364,3288,4773,4774,6162,6024,6365,3543,6588,4274,3107,3737,5050,5803, +4797,4522,5589,5051,5730,3714,4887,5378,4001,4523,6163,5026,5522,4701,4175,2791, +3760,6589,5473,4224,4133,3847,4814,4815,4775,3259,5416,6590,2738,6164,6025,5304, +3733,5076,5650,4816,5590,6591,6165,6592,3934,5269,6593,3396,5340,6594,5804,3445, +3602,4042,4488,5731,5732,3525,5591,4601,5196,6166,6026,5172,3642,4612,3202,4506, +4798,6366,3818,5108,4303,5138,5139,4776,3332,4304,2915,3415,4434,5077,5109,4856, +2879,5305,4817,6595,5913,3104,3144,3903,4634,5341,3133,5110,5651,5805,6167,4057, +5592,2945,4371,5593,6596,3474,4182,6367,6597,6168,4507,4279,6598,2822,6599,4777, +4713,5594,3829,6169,3887,5417,6170,3653,5474,6368,4216,2971,5228,3790,4579,6369, +5733,6600,6601,4951,4746,4555,6602,5418,5475,6027,3400,4665,5806,6171,4799,6028, +5052,6172,3343,4800,4747,5006,6370,4556,4217,5476,4396,5229,5379,5477,3839,5914, +5652,5807,4714,3068,4635,5808,6173,5342,4192,5078,5419,5523,5734,6174,4557,6175, +4602,6371,6176,6603,5809,6372,5735,4260,3869,5111,5230,6029,5112,6177,3126,4681, +5524,5915,2706,3563,4748,3130,6178,4018,5525,6604,6605,5478,4012,4837,6606,4534, +4193,5810,4857,3615,5479,6030,4082,3697,3539,4086,5270,3662,4508,4931,5916,4912, +5811,5027,3888,6607,4397,3527,3302,3798,2775,2921,2637,3966,4122,4388,4028,4054, +1633,4858,5079,3024,5007,3982,3412,5736,6608,3426,3236,5595,3030,6179,3427,3336, +3279,3110,6373,3874,3039,5080,5917,5140,4489,3119,6374,5812,3405,4494,6031,4666, +4141,6180,4166,6032,5813,4981,6609,5081,4422,4982,4112,3915,5653,3296,3983,6375, +4266,4410,5654,6610,6181,3436,5082,6611,5380,6033,3819,5596,4535,5231,5306,5113, +6612,4952,5918,4275,3113,6613,6376,6182,6183,5814,3073,4731,4838,5008,3831,6614, +4888,3090,3848,4280,5526,5232,3014,5655,5009,5737,5420,5527,6615,5815,5343,5173, +5381,4818,6616,3151,4953,6617,5738,2796,3204,4360,2989,4281,5739,5174,5421,5197, +3132,5141,3849,5142,5528,5083,3799,3904,4839,5480,2880,4495,3448,6377,6184,5271, +5919,3771,3193,6034,6035,5920,5010,6036,5597,6037,6378,6038,3106,5422,6618,5423, +5424,4142,6619,4889,5084,4890,4313,5740,6620,3437,5175,5307,5816,4199,5198,5529, +5817,5199,5656,4913,5028,5344,3850,6185,2955,5272,5011,5818,4567,4580,5029,5921, +3616,5233,6621,6622,6186,4176,6039,6379,6380,3352,5200,5273,2908,5598,5234,3837, +5308,6623,6624,5819,4496,4323,5309,5201,6625,6626,4983,3194,3838,4167,5530,5922, +5274,6381,6382,3860,3861,5599,3333,4292,4509,6383,3553,5481,5820,5531,4778,6187, +3955,3956,4324,4389,4218,3945,4325,3397,2681,5923,4779,5085,4019,5482,4891,5382, +5383,6040,4682,3425,5275,4094,6627,5310,3015,5483,5657,4398,5924,3168,4819,6628, +5925,6629,5532,4932,4613,6041,6630,4636,6384,4780,4204,5658,4423,5821,3989,4683, +5822,6385,4954,6631,5345,6188,5425,5012,5384,3894,6386,4490,4104,6632,5741,5053, +6633,5823,5926,5659,5660,5927,6634,5235,5742,5824,4840,4933,4820,6387,4859,5928, +4955,6388,4143,3584,5825,5346,5013,6635,5661,6389,5014,5484,5743,4337,5176,5662, +6390,2836,6391,3268,6392,6636,6042,5236,6637,4158,6638,5744,5663,4471,5347,3663, +4123,5143,4293,3895,6639,6640,5311,5929,5826,3800,6189,6393,6190,5664,5348,3554, +3594,4749,4603,6641,5385,4801,6043,5827,4183,6642,5312,5426,4761,6394,5665,6191, +4715,2669,6643,6644,5533,3185,5427,5086,5930,5931,5386,6192,6044,6645,4781,4013, +5745,4282,4435,5534,4390,4267,6045,5746,4984,6046,2743,6193,3501,4087,5485,5932, +5428,4184,4095,5747,4061,5054,3058,3862,5933,5600,6646,5144,3618,6395,3131,5055, +5313,6396,4650,4956,3855,6194,3896,5202,4985,4029,4225,6195,6647,5828,5486,5829, +3589,3002,6648,6397,4782,5276,6649,6196,6650,4105,3803,4043,5237,5830,6398,4096, +3643,6399,3528,6651,4453,3315,4637,6652,3984,6197,5535,3182,3339,6653,3096,2660, +6400,6654,3449,5934,4250,4236,6047,6401,5831,6655,5487,3753,4062,5832,6198,6199, +6656,3766,6657,3403,4667,6048,6658,4338,2897,5833,3880,2797,3780,4326,6659,5748, +5015,6660,5387,4351,5601,4411,6661,3654,4424,5935,4339,4072,5277,4568,5536,6402, +6662,5238,6663,5349,5203,6200,5204,6201,5145,4536,5016,5056,4762,5834,4399,4957, +6202,6403,5666,5749,6664,4340,6665,5936,5177,5667,6666,6667,3459,4668,6404,6668, +6669,4543,6203,6670,4276,6405,4480,5537,6671,4614,5205,5668,6672,3348,2193,4763, +6406,6204,5937,5602,4177,5669,3419,6673,4020,6205,4443,4569,5388,3715,3639,6407, +6049,4058,6206,6674,5938,4544,6050,4185,4294,4841,4651,4615,5488,6207,6408,6051, +5178,3241,3509,5835,6208,4958,5836,4341,5489,5278,6209,2823,5538,5350,5206,5429, +6675,4638,4875,4073,3516,4684,4914,4860,5939,5603,5389,6052,5057,3237,5490,3791, +6676,6409,6677,4821,4915,4106,5351,5058,4243,5539,4244,5604,4842,4916,5239,3028, +3716,5837,5114,5605,5390,5940,5430,6210,4332,6678,5540,4732,3667,3840,6053,4305, +3408,5670,5541,6410,2744,5240,5750,6679,3234,5606,6680,5607,5671,3608,4283,4159, +4400,5352,4783,6681,6411,6682,4491,4802,6211,6412,5941,6413,6414,5542,5751,6683, +4669,3734,5942,6684,6415,5943,5059,3328,4670,4144,4268,6685,6686,6687,6688,4372, +3603,6689,5944,5491,4373,3440,6416,5543,4784,4822,5608,3792,4616,5838,5672,3514, +5391,6417,4892,6690,4639,6691,6054,5673,5839,6055,6692,6056,5392,6212,4038,5544, +5674,4497,6057,6693,5840,4284,5675,4021,4545,5609,6418,4454,6419,6213,4113,4472, +5314,3738,5087,5279,4074,5610,4959,4063,3179,4750,6058,6420,6214,3476,4498,4716, +5431,4960,4685,6215,5241,6694,6421,6216,6695,5841,5945,6422,3748,5946,5179,3905, +5752,5545,5947,4374,6217,4455,6423,4412,6218,4803,5353,6696,3832,5280,6219,4327, +4702,6220,6221,6059,4652,5432,6424,3749,4751,6425,5753,4986,5393,4917,5948,5030, +5754,4861,4733,6426,4703,6697,6222,4671,5949,4546,4961,5180,6223,5031,3316,5281, +6698,4862,4295,4934,5207,3644,6427,5842,5950,6428,6429,4570,5843,5282,6430,6224, +5088,3239,6060,6699,5844,5755,6061,6431,2701,5546,6432,5115,5676,4039,3993,3327, +4752,4425,5315,6433,3941,6434,5677,4617,4604,3074,4581,6225,5433,6435,6226,6062, +4823,5756,5116,6227,3717,5678,4717,5845,6436,5679,5846,6063,5847,6064,3977,3354, +6437,3863,5117,6228,5547,5394,4499,4524,6229,4605,6230,4306,4500,6700,5951,6065, +3693,5952,5089,4366,4918,6701,6231,5548,6232,6702,6438,4704,5434,6703,6704,5953, +4168,6705,5680,3420,6706,5242,4407,6066,3812,5757,5090,5954,4672,4525,3481,5681, +4618,5395,5354,5316,5955,6439,4962,6707,4526,6440,3465,4673,6067,6441,5682,6708, +5435,5492,5758,5683,4619,4571,4674,4804,4893,4686,5493,4753,6233,6068,4269,6442, +6234,5032,4705,5146,5243,5208,5848,6235,6443,4963,5033,4640,4226,6236,5849,3387, +6444,6445,4436,4437,5850,4843,5494,4785,4894,6709,4361,6710,5091,5956,3331,6237, +4987,5549,6069,6711,4342,3517,4473,5317,6070,6712,6071,4706,6446,5017,5355,6713, +6714,4988,5436,6447,4734,5759,6715,4735,4547,4456,4754,6448,5851,6449,6450,3547, +5852,5318,6451,6452,5092,4205,6716,6238,4620,4219,5611,6239,6072,4481,5760,5957, +5958,4059,6240,6453,4227,4537,6241,5761,4030,4186,5244,5209,3761,4457,4876,3337, +5495,5181,6242,5959,5319,5612,5684,5853,3493,5854,6073,4169,5613,5147,4895,6074, +5210,6717,5182,6718,3830,6243,2798,3841,6075,6244,5855,5614,3604,4606,5496,5685, +5118,5356,6719,6454,5960,5357,5961,6720,4145,3935,4621,5119,5962,4261,6721,6455, +4786,5963,4375,4582,6245,6246,6247,6076,5437,4877,5856,3376,4380,6248,4160,6722, +5148,6456,5211,6457,6723,4718,6458,6724,6249,5358,4044,3297,6459,6250,5857,5615, +5497,5245,6460,5498,6725,6251,6252,5550,3793,5499,2959,5396,6461,6462,4572,5093, +5500,5964,3806,4146,6463,4426,5762,5858,6077,6253,4755,3967,4220,5965,6254,4989, +5501,6464,4352,6726,6078,4764,2290,5246,3906,5438,5283,3767,4964,2861,5763,5094, +6255,6256,4622,5616,5859,5860,4707,6727,4285,4708,4824,5617,6257,5551,4787,5212, +4965,4935,4687,6465,6728,6466,5686,6079,3494,4413,2995,5247,5966,5618,6729,5967, +5764,5765,5687,5502,6730,6731,6080,5397,6467,4990,6258,6732,4538,5060,5619,6733, +4719,5688,5439,5018,5149,5284,5503,6734,6081,4607,6259,5120,3645,5861,4583,6260, +4584,4675,5620,4098,5440,6261,4863,2379,3306,4585,5552,5689,4586,5285,6735,4864, +6736,5286,6082,6737,4623,3010,4788,4381,4558,5621,4587,4896,3698,3161,5248,4353, +4045,6262,3754,5183,4588,6738,6263,6739,6740,5622,3936,6741,6468,6742,6264,5095, +6469,4991,5968,6743,4992,6744,6083,4897,6745,4256,5766,4307,3108,3968,4444,5287, +3889,4343,6084,4510,6085,4559,6086,4898,5969,6746,5623,5061,4919,5249,5250,5504, +5441,6265,5320,4878,3242,5862,5251,3428,6087,6747,4237,5624,5442,6266,5553,4539, +6748,2585,3533,5398,4262,6088,5150,4736,4438,6089,6267,5505,4966,6749,6268,6750, +6269,5288,5554,3650,6090,6091,4624,6092,5690,6751,5863,4270,5691,4277,5555,5864, +6752,5692,4720,4865,6470,5151,4688,4825,6753,3094,6754,6471,3235,4653,6755,5213, +5399,6756,3201,4589,5865,4967,6472,5866,6473,5019,3016,6757,5321,4756,3957,4573, +6093,4993,5767,4721,6474,6758,5625,6759,4458,6475,6270,6760,5556,4994,5214,5252, +6271,3875,5768,6094,5034,5506,4376,5769,6761,2120,6476,5253,5770,6762,5771,5970, +3990,5971,5557,5558,5772,6477,6095,2787,4641,5972,5121,6096,6097,6272,6763,3703, +5867,5507,6273,4206,6274,4789,6098,6764,3619,3646,3833,3804,2394,3788,4936,3978, +4866,4899,6099,6100,5559,6478,6765,3599,5868,6101,5869,5870,6275,6766,4527,6767) + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/gb2312prober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/gb2312prober.py new file mode 100755 index 0000000..91eb392 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/gb2312prober.py @@ -0,0 +1,41 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from mbcharsetprober import MultiByteCharSetProber +from codingstatemachine import CodingStateMachine +from chardistribution import GB2312DistributionAnalysis +from mbcssm import GB2312SMModel + +class GB2312Prober(MultiByteCharSetProber): + def __init__(self): + MultiByteCharSetProber.__init__(self) + self._mCodingSM = CodingStateMachine(GB2312SMModel) + self._mDistributionAnalyzer = GB2312DistributionAnalysis() + self.reset() + + def get_charset_name(self): + return "GB2312" diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/hebrewprober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/hebrewprober.py new file mode 100755 index 0000000..a2b1eaa --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/hebrewprober.py @@ -0,0 +1,269 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Shy Shalom +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from charsetprober import CharSetProber +import constants + +# This prober doesn't actually recognize a language or a charset. +# It is a helper prober for the use of the Hebrew model probers + +### General ideas of the Hebrew charset recognition ### +# +# Four main charsets exist in Hebrew: +# "ISO-8859-8" - Visual Hebrew +# "windows-1255" - Logical Hebrew +# "ISO-8859-8-I" - Logical Hebrew +# "x-mac-hebrew" - ?? Logical Hebrew ?? +# +# Both "ISO" charsets use a completely identical set of code points, whereas +# "windows-1255" and "x-mac-hebrew" are two different proper supersets of +# these code points. windows-1255 defines additional characters in the range +# 0x80-0x9F as some misc punctuation marks as well as some Hebrew-specific +# diacritics and additional 'Yiddish' ligature letters in the range 0xc0-0xd6. +# x-mac-hebrew defines similar additional code points but with a different +# mapping. +# +# As far as an average Hebrew text with no diacritics is concerned, all four +# charsets are identical with respect to code points. Meaning that for the +# main Hebrew alphabet, all four map the same values to all 27 Hebrew letters +# (including final letters). +# +# The dominant difference between these charsets is their directionality. +# "Visual" directionality means that the text is ordered as if the renderer is +# not aware of a BIDI rendering algorithm. The renderer sees the text and +# draws it from left to right. The text itself when ordered naturally is read +# backwards. A buffer of Visual Hebrew generally looks like so: +# "[last word of first line spelled backwards] [whole line ordered backwards +# and spelled backwards] [first word of first line spelled backwards] +# [end of line] [last word of second line] ... etc' " +# adding punctuation marks, numbers and English text to visual text is +# naturally also "visual" and from left to right. +# +# "Logical" directionality means the text is ordered "naturally" according to +# the order it is read. It is the responsibility of the renderer to display +# the text from right to left. A BIDI algorithm is used to place general +# punctuation marks, numbers and English text in the text. +# +# Texts in x-mac-hebrew are almost impossible to find on the Internet. From +# what little evidence I could find, it seems that its general directionality +# is Logical. +# +# To sum up all of the above, the Hebrew probing mechanism knows about two +# charsets: +# Visual Hebrew - "ISO-8859-8" - backwards text - Words and sentences are +# backwards while line order is natural. For charset recognition purposes +# the line order is unimportant (In fact, for this implementation, even +# word order is unimportant). +# Logical Hebrew - "windows-1255" - normal, naturally ordered text. +# +# "ISO-8859-8-I" is a subset of windows-1255 and doesn't need to be +# specifically identified. +# "x-mac-hebrew" is also identified as windows-1255. A text in x-mac-hebrew +# that contain special punctuation marks or diacritics is displayed with +# some unconverted characters showing as question marks. This problem might +# be corrected using another model prober for x-mac-hebrew. Due to the fact +# that x-mac-hebrew texts are so rare, writing another model prober isn't +# worth the effort and performance hit. +# +#### The Prober #### +# +# The prober is divided between two SBCharSetProbers and a HebrewProber, +# all of which are managed, created, fed data, inquired and deleted by the +# SBCSGroupProber. The two SBCharSetProbers identify that the text is in +# fact some kind of Hebrew, Logical or Visual. The final decision about which +# one is it is made by the HebrewProber by combining final-letter scores +# with the scores of the two SBCharSetProbers to produce a final answer. +# +# The SBCSGroupProber is responsible for stripping the original text of HTML +# tags, English characters, numbers, low-ASCII punctuation characters, spaces +# and new lines. It reduces any sequence of such characters to a single space. +# The buffer fed to each prober in the SBCS group prober is pure text in +# high-ASCII. +# The two SBCharSetProbers (model probers) share the same language model: +# Win1255Model. +# The first SBCharSetProber uses the model normally as any other +# SBCharSetProber does, to recognize windows-1255, upon which this model was +# built. The second SBCharSetProber is told to make the pair-of-letter +# lookup in the language model backwards. This in practice exactly simulates +# a visual Hebrew model using the windows-1255 logical Hebrew model. +# +# The HebrewProber is not using any language model. All it does is look for +# final-letter evidence suggesting the text is either logical Hebrew or visual +# Hebrew. Disjointed from the model probers, the results of the HebrewProber +# alone are meaningless. HebrewProber always returns 0.00 as confidence +# since it never identifies a charset by itself. Instead, the pointer to the +# HebrewProber is passed to the model probers as a helper "Name Prober". +# When the Group prober receives a positive identification from any prober, +# it asks for the name of the charset identified. If the prober queried is a +# Hebrew model prober, the model prober forwards the call to the +# HebrewProber to make the final decision. In the HebrewProber, the +# decision is made according to the final-letters scores maintained and Both +# model probers scores. The answer is returned in the form of the name of the +# charset identified, either "windows-1255" or "ISO-8859-8". + +# windows-1255 / ISO-8859-8 code points of interest +FINAL_KAF = '\xea' +NORMAL_KAF = '\xeb' +FINAL_MEM = '\xed' +NORMAL_MEM = '\xee' +FINAL_NUN = '\xef' +NORMAL_NUN = '\xf0' +FINAL_PE = '\xf3' +NORMAL_PE = '\xf4' +FINAL_TSADI = '\xf5' +NORMAL_TSADI = '\xf6' + +# Minimum Visual vs Logical final letter score difference. +# If the difference is below this, don't rely solely on the final letter score distance. +MIN_FINAL_CHAR_DISTANCE = 5 + +# Minimum Visual vs Logical model score difference. +# If the difference is below this, don't rely at all on the model score distance. +MIN_MODEL_DISTANCE = 0.01 + +VISUAL_HEBREW_NAME = "ISO-8859-8" +LOGICAL_HEBREW_NAME = "windows-1255" + +class HebrewProber(CharSetProber): + def __init__(self): + CharSetProber.__init__(self) + self._mLogicalProber = None + self._mVisualProber = None + self.reset() + + def reset(self): + self._mFinalCharLogicalScore = 0 + self._mFinalCharVisualScore = 0 + # The two last characters seen in the previous buffer, + # mPrev and mBeforePrev are initialized to space in order to simulate a word + # delimiter at the beginning of the data + self._mPrev = ' ' + self._mBeforePrev = ' ' + # These probers are owned by the group prober. + + def set_model_probers(self, logicalProber, visualProber): + self._mLogicalProber = logicalProber + self._mVisualProber = visualProber + + def is_final(self, c): + return c in [FINAL_KAF, FINAL_MEM, FINAL_NUN, FINAL_PE, FINAL_TSADI] + + def is_non_final(self, c): + # The normal Tsadi is not a good Non-Final letter due to words like + # 'lechotet' (to chat) containing an apostrophe after the tsadi. This + # apostrophe is converted to a space in FilterWithoutEnglishLetters causing + # the Non-Final tsadi to appear at an end of a word even though this is not + # the case in the original text. + # The letters Pe and Kaf rarely display a related behavior of not being a + # good Non-Final letter. Words like 'Pop', 'Winamp' and 'Mubarak' for + # example legally end with a Non-Final Pe or Kaf. However, the benefit of + # these letters as Non-Final letters outweighs the damage since these words + # are quite rare. + return c in [NORMAL_KAF, NORMAL_MEM, NORMAL_NUN, NORMAL_PE] + + def feed(self, aBuf): + # Final letter analysis for logical-visual decision. + # Look for evidence that the received buffer is either logical Hebrew or + # visual Hebrew. + # The following cases are checked: + # 1) A word longer than 1 letter, ending with a final letter. This is an + # indication that the text is laid out "naturally" since the final letter + # really appears at the end. +1 for logical score. + # 2) A word longer than 1 letter, ending with a Non-Final letter. In normal + # Hebrew, words ending with Kaf, Mem, Nun, Pe or Tsadi, should not end with + # the Non-Final form of that letter. Exceptions to this rule are mentioned + # above in isNonFinal(). This is an indication that the text is laid out + # backwards. +1 for visual score + # 3) A word longer than 1 letter, starting with a final letter. Final letters + # should not appear at the beginning of a word. This is an indication that + # the text is laid out backwards. +1 for visual score. + # + # The visual score and logical score are accumulated throughout the text and + # are finally checked against each other in GetCharSetName(). + # No checking for final letters in the middle of words is done since that case + # is not an indication for either Logical or Visual text. + # + # We automatically filter out all 7-bit characters (replace them with spaces) + # so the word boundary detection works properly. [MAP] + + if self.get_state() == constants.eNotMe: + # Both model probers say it's not them. No reason to continue. + return constants.eNotMe + + aBuf = self.filter_high_bit_only(aBuf) + + for cur in aBuf: + if cur == ' ': + # We stand on a space - a word just ended + if self._mBeforePrev != ' ': + # next-to-last char was not a space so self._mPrev is not a 1 letter word + if self.is_final(self._mPrev): + # case (1) [-2:not space][-1:final letter][cur:space] + self._mFinalCharLogicalScore += 1 + elif self.is_non_final(self._mPrev): + # case (2) [-2:not space][-1:Non-Final letter][cur:space] + self._mFinalCharVisualScore += 1 + else: + # Not standing on a space + if (self._mBeforePrev == ' ') and (self.is_final(self._mPrev)) and (cur != ' '): + # case (3) [-2:space][-1:final letter][cur:not space] + self._mFinalCharVisualScore += 1 + self._mBeforePrev = self._mPrev + self._mPrev = cur + + # Forever detecting, till the end or until both model probers return eNotMe (handled above) + return constants.eDetecting + + def get_charset_name(self): + # Make the decision: is it Logical or Visual? + # If the final letter score distance is dominant enough, rely on it. + finalsub = self._mFinalCharLogicalScore - self._mFinalCharVisualScore + if finalsub >= MIN_FINAL_CHAR_DISTANCE: + return LOGICAL_HEBREW_NAME + if finalsub <= -MIN_FINAL_CHAR_DISTANCE: + return VISUAL_HEBREW_NAME + + # It's not dominant enough, try to rely on the model scores instead. + modelsub = self._mLogicalProber.get_confidence() - self._mVisualProber.get_confidence() + if modelsub > MIN_MODEL_DISTANCE: + return LOGICAL_HEBREW_NAME + if modelsub < -MIN_MODEL_DISTANCE: + return VISUAL_HEBREW_NAME + + # Still no good, back to final letter distance, maybe it'll save the day. + if finalsub < 0.0: + return VISUAL_HEBREW_NAME + + # (finalsub > 0 - Logical) or (don't know what to do) default to Logical. + return LOGICAL_HEBREW_NAME + + def get_state(self): + # Remain active as long as any of the model probers are active. + if (self._mLogicalProber.get_state() == constants.eNotMe) and \ + (self._mVisualProber.get_state() == constants.eNotMe): + return constants.eNotMe + return constants.eDetecting diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/jisfreq.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/jisfreq.py new file mode 100755 index 0000000..5fe4a5c --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/jisfreq.py @@ -0,0 +1,567 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Sampling from about 20M text materials include literature and computer technology +# +# Japanese frequency table, applied to both S-JIS and EUC-JP +# They are sorted in order. + +# 128 --> 0.77094 +# 256 --> 0.85710 +# 512 --> 0.92635 +# 1024 --> 0.97130 +# 2048 --> 0.99431 +# +# Ideal Distribution Ratio = 0.92635 / (1-0.92635) = 12.58 +# Random Distribution Ration = 512 / (2965+62+83+86-512) = 0.191 +# +# Typical Distribution Ratio, 25% of IDR + +JIS_TYPICAL_DISTRIBUTION_RATIO = 3.0 + +# Char to FreqOrder table , +JIS_TABLE_SIZE = 4368 + +JISCharToFreqOrder = ( \ + 40, 1, 6, 182, 152, 180, 295,2127, 285, 381,3295,4304,3068,4606,3165,3510, # 16 +3511,1822,2785,4607,1193,2226,5070,4608, 171,2996,1247, 18, 179,5071, 856,1661, # 32 +1262,5072, 619, 127,3431,3512,3230,1899,1700, 232, 228,1294,1298, 284, 283,2041, # 48 +2042,1061,1062, 48, 49, 44, 45, 433, 434,1040,1041, 996, 787,2997,1255,4305, # 64 +2108,4609,1684,1648,5073,5074,5075,5076,5077,5078,3687,5079,4610,5080,3927,3928, # 80 +5081,3296,3432, 290,2285,1471,2187,5082,2580,2825,1303,2140,1739,1445,2691,3375, # 96 +1691,3297,4306,4307,4611, 452,3376,1182,2713,3688,3069,4308,5083,5084,5085,5086, # 112 +5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102, # 128 +5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,4097,5113,5114,5115,5116,5117, # 144 +5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133, # 160 +5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149, # 176 +5150,5151,5152,4612,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164, # 192 +5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,1472, 598, 618, 820,1205, # 208 +1309,1412,1858,1307,1692,5176,5177,5178,5179,5180,5181,5182,1142,1452,1234,1172, # 224 +1875,2043,2149,1793,1382,2973, 925,2404,1067,1241, 960,1377,2935,1491, 919,1217, # 240 +1865,2030,1406,1499,2749,4098,5183,5184,5185,5186,5187,5188,2561,4099,3117,1804, # 256 +2049,3689,4309,3513,1663,5189,3166,3118,3298,1587,1561,3433,5190,3119,1625,2998, # 272 +3299,4613,1766,3690,2786,4614,5191,5192,5193,5194,2161, 26,3377, 2,3929, 20, # 288 +3691, 47,4100, 50, 17, 16, 35, 268, 27, 243, 42, 155, 24, 154, 29, 184, # 304 + 4, 91, 14, 92, 53, 396, 33, 289, 9, 37, 64, 620, 21, 39, 321, 5, # 320 + 12, 11, 52, 13, 3, 208, 138, 0, 7, 60, 526, 141, 151,1069, 181, 275, # 336 +1591, 83, 132,1475, 126, 331, 829, 15, 69, 160, 59, 22, 157, 55,1079, 312, # 352 + 109, 38, 23, 25, 10, 19, 79,5195, 61, 382,1124, 8, 30,5196,5197,5198, # 368 +5199,5200,5201,5202,5203,5204,5205,5206, 89, 62, 74, 34,2416, 112, 139, 196, # 384 + 271, 149, 84, 607, 131, 765, 46, 88, 153, 683, 76, 874, 101, 258, 57, 80, # 400 + 32, 364, 121,1508, 169,1547, 68, 235, 145,2999, 41, 360,3027, 70, 63, 31, # 416 + 43, 259, 262,1383, 99, 533, 194, 66, 93, 846, 217, 192, 56, 106, 58, 565, # 432 + 280, 272, 311, 256, 146, 82, 308, 71, 100, 128, 214, 655, 110, 261, 104,1140, # 448 + 54, 51, 36, 87, 67,3070, 185,2618,2936,2020, 28,1066,2390,2059,5207,5208, # 464 +5209,5210,5211,5212,5213,5214,5215,5216,4615,5217,5218,5219,5220,5221,5222,5223, # 480 +5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,3514,5237,5238, # 496 +5239,5240,5241,5242,5243,5244,2297,2031,4616,4310,3692,5245,3071,5246,3598,5247, # 512 +4617,3231,3515,5248,4101,4311,4618,3808,4312,4102,5249,4103,4104,3599,5250,5251, # 528 +5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267, # 544 +5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283, # 560 +5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299, # 576 +5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315, # 592 +5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331, # 608 +5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347, # 624 +5348,5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363, # 640 +5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379, # 656 +5380,5381, 363, 642,2787,2878,2788,2789,2316,3232,2317,3434,2011, 165,1942,3930, # 672 +3931,3932,3933,5382,4619,5383,4620,5384,5385,5386,5387,5388,5389,5390,5391,5392, # 688 +5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408, # 704 +5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424, # 720 +5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440, # 736 +5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456, # 752 +5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472, # 768 +5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488, # 784 +5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504, # 800 +5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520, # 816 +5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536, # 832 +5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552, # 848 +5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568, # 864 +5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584, # 880 +5585,5586,5587,5588,5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600, # 896 +5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616, # 912 +5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632, # 928 +5633,5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648, # 944 +5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664, # 960 +5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680, # 976 +5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696, # 992 +5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712, # 1008 +5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728, # 1024 +5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5741,5742,5743,5744, # 1040 +5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,5759,5760, # 1056 +5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,5774,5775,5776, # 1072 +5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5787,5788,5789,5790,5791,5792, # 1088 +5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,5804,5805,5806,5807,5808, # 1104 +5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824, # 1120 +5825,5826,5827,5828,5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840, # 1136 +5841,5842,5843,5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856, # 1152 +5857,5858,5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872, # 1168 +5873,5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888, # 1184 +5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904, # 1200 +5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920, # 1216 +5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936, # 1232 +5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952, # 1248 +5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968, # 1264 +5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,5984, # 1280 +5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,5999,6000, # 1296 +6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016, # 1312 +6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032, # 1328 +6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048, # 1344 +6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064, # 1360 +6065,6066,6067,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080, # 1376 +6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096, # 1392 +6097,6098,6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112, # 1408 +6113,6114,2044,2060,4621, 997,1235, 473,1186,4622, 920,3378,6115,6116, 379,1108, # 1424 +4313,2657,2735,3934,6117,3809, 636,3233, 573,1026,3693,3435,2974,3300,2298,4105, # 1440 + 854,2937,2463, 393,2581,2417, 539, 752,1280,2750,2480, 140,1161, 440, 708,1569, # 1456 + 665,2497,1746,1291,1523,3000, 164,1603, 847,1331, 537,1997, 486, 508,1693,2418, # 1472 +1970,2227, 878,1220, 299,1030, 969, 652,2751, 624,1137,3301,2619, 65,3302,2045, # 1488 +1761,1859,3120,1930,3694,3516, 663,1767, 852, 835,3695, 269, 767,2826,2339,1305, # 1504 + 896,1150, 770,1616,6118, 506,1502,2075,1012,2519, 775,2520,2975,2340,2938,4314, # 1520 +3028,2086,1224,1943,2286,6119,3072,4315,2240,1273,1987,3935,1557, 175, 597, 985, # 1536 +3517,2419,2521,1416,3029, 585, 938,1931,1007,1052,1932,1685,6120,3379,4316,4623, # 1552 + 804, 599,3121,1333,2128,2539,1159,1554,2032,3810, 687,2033,2904, 952, 675,1467, # 1568 +3436,6121,2241,1096,1786,2440,1543,1924, 980,1813,2228, 781,2692,1879, 728,1918, # 1584 +3696,4624, 548,1950,4625,1809,1088,1356,3303,2522,1944, 502, 972, 373, 513,2827, # 1600 + 586,2377,2391,1003,1976,1631,6122,2464,1084, 648,1776,4626,2141, 324, 962,2012, # 1616 +2177,2076,1384, 742,2178,1448,1173,1810, 222, 102, 301, 445, 125,2420, 662,2498, # 1632 + 277, 200,1476,1165,1068, 224,2562,1378,1446, 450,1880, 659, 791, 582,4627,2939, # 1648 +3936,1516,1274, 555,2099,3697,1020,1389,1526,3380,1762,1723,1787,2229, 412,2114, # 1664 +1900,2392,3518, 512,2597, 427,1925,2341,3122,1653,1686,2465,2499, 697, 330, 273, # 1680 + 380,2162, 951, 832, 780, 991,1301,3073, 965,2270,3519, 668,2523,2636,1286, 535, # 1696 +1407, 518, 671, 957,2658,2378, 267, 611,2197,3030,6123, 248,2299, 967,1799,2356, # 1712 + 850,1418,3437,1876,1256,1480,2828,1718,6124,6125,1755,1664,2405,6126,4628,2879, # 1728 +2829, 499,2179, 676,4629, 557,2329,2214,2090, 325,3234, 464, 811,3001, 992,2342, # 1744 +2481,1232,1469, 303,2242, 466,1070,2163, 603,1777,2091,4630,2752,4631,2714, 322, # 1760 +2659,1964,1768, 481,2188,1463,2330,2857,3600,2092,3031,2421,4632,2318,2070,1849, # 1776 +2598,4633,1302,2254,1668,1701,2422,3811,2905,3032,3123,2046,4106,1763,1694,4634, # 1792 +1604, 943,1724,1454, 917, 868,2215,1169,2940, 552,1145,1800,1228,1823,1955, 316, # 1808 +1080,2510, 361,1807,2830,4107,2660,3381,1346,1423,1134,4108,6127, 541,1263,1229, # 1824 +1148,2540, 545, 465,1833,2880,3438,1901,3074,2482, 816,3937, 713,1788,2500, 122, # 1840 +1575, 195,1451,2501,1111,6128, 859, 374,1225,2243,2483,4317, 390,1033,3439,3075, # 1856 +2524,1687, 266, 793,1440,2599, 946, 779, 802, 507, 897,1081, 528,2189,1292, 711, # 1872 +1866,1725,1167,1640, 753, 398,2661,1053, 246, 348,4318, 137,1024,3440,1600,2077, # 1888 +2129, 825,4319, 698, 238, 521, 187,2300,1157,2423,1641,1605,1464,1610,1097,2541, # 1904 +1260,1436, 759,2255,1814,2150, 705,3235, 409,2563,3304, 561,3033,2005,2564, 726, # 1920 +1956,2343,3698,4109, 949,3812,3813,3520,1669, 653,1379,2525, 881,2198, 632,2256, # 1936 +1027, 778,1074, 733,1957, 514,1481,2466, 554,2180, 702,3938,1606,1017,1398,6129, # 1952 +1380,3521, 921, 993,1313, 594, 449,1489,1617,1166, 768,1426,1360, 495,1794,3601, # 1968 +1177,3602,1170,4320,2344, 476, 425,3167,4635,3168,1424, 401,2662,1171,3382,1998, # 1984 +1089,4110, 477,3169, 474,6130,1909, 596,2831,1842, 494, 693,1051,1028,1207,3076, # 2000 + 606,2115, 727,2790,1473,1115, 743,3522, 630, 805,1532,4321,2021, 366,1057, 838, # 2016 + 684,1114,2142,4322,2050,1492,1892,1808,2271,3814,2424,1971,1447,1373,3305,1090, # 2032 +1536,3939,3523,3306,1455,2199, 336, 369,2331,1035, 584,2393, 902, 718,2600,6131, # 2048 +2753, 463,2151,1149,1611,2467, 715,1308,3124,1268, 343,1413,3236,1517,1347,2663, # 2064 +2093,3940,2022,1131,1553,2100,2941,1427,3441,2942,1323,2484,6132,1980, 872,2368, # 2080 +2441,2943, 320,2369,2116,1082, 679,1933,3941,2791,3815, 625,1143,2023, 422,2200, # 2096 +3816,6133, 730,1695, 356,2257,1626,2301,2858,2637,1627,1778, 937, 883,2906,2693, # 2112 +3002,1769,1086, 400,1063,1325,3307,2792,4111,3077, 456,2345,1046, 747,6134,1524, # 2128 + 884,1094,3383,1474,2164,1059, 974,1688,2181,2258,1047, 345,1665,1187, 358, 875, # 2144 +3170, 305, 660,3524,2190,1334,1135,3171,1540,1649,2542,1527, 927, 968,2793, 885, # 2160 +1972,1850, 482, 500,2638,1218,1109,1085,2543,1654,2034, 876, 78,2287,1482,1277, # 2176 + 861,1675,1083,1779, 724,2754, 454, 397,1132,1612,2332, 893, 672,1237, 257,2259, # 2192 +2370, 135,3384, 337,2244, 547, 352, 340, 709,2485,1400, 788,1138,2511, 540, 772, # 2208 +1682,2260,2272,2544,2013,1843,1902,4636,1999,1562,2288,4637,2201,1403,1533, 407, # 2224 + 576,3308,1254,2071, 978,3385, 170, 136,1201,3125,2664,3172,2394, 213, 912, 873, # 2240 +3603,1713,2202, 699,3604,3699, 813,3442, 493, 531,1054, 468,2907,1483, 304, 281, # 2256 +4112,1726,1252,2094, 339,2319,2130,2639, 756,1563,2944, 748, 571,2976,1588,2425, # 2272 +2715,1851,1460,2426,1528,1392,1973,3237, 288,3309, 685,3386, 296, 892,2716,2216, # 2288 +1570,2245, 722,1747,2217, 905,3238,1103,6135,1893,1441,1965, 251,1805,2371,3700, # 2304 +2601,1919,1078, 75,2182,1509,1592,1270,2640,4638,2152,6136,3310,3817, 524, 706, # 2320 +1075, 292,3818,1756,2602, 317, 98,3173,3605,3525,1844,2218,3819,2502, 814, 567, # 2336 + 385,2908,1534,6137, 534,1642,3239, 797,6138,1670,1529, 953,4323, 188,1071, 538, # 2352 + 178, 729,3240,2109,1226,1374,2000,2357,2977, 731,2468,1116,2014,2051,6139,1261, # 2368 +1593, 803,2859,2736,3443, 556, 682, 823,1541,6140,1369,2289,1706,2794, 845, 462, # 2384 +2603,2665,1361, 387, 162,2358,1740, 739,1770,1720,1304,1401,3241,1049, 627,1571, # 2400 +2427,3526,1877,3942,1852,1500, 431,1910,1503, 677, 297,2795, 286,1433,1038,1198, # 2416 +2290,1133,1596,4113,4639,2469,1510,1484,3943,6141,2442, 108, 712,4640,2372, 866, # 2432 +3701,2755,3242,1348, 834,1945,1408,3527,2395,3243,1811, 824, 994,1179,2110,1548, # 2448 +1453, 790,3003, 690,4324,4325,2832,2909,3820,1860,3821, 225,1748, 310, 346,1780, # 2464 +2470, 821,1993,2717,2796, 828, 877,3528,2860,2471,1702,2165,2910,2486,1789, 453, # 2480 + 359,2291,1676, 73,1164,1461,1127,3311, 421, 604, 314,1037, 589, 116,2487, 737, # 2496 + 837,1180, 111, 244, 735,6142,2261,1861,1362, 986, 523, 418, 581,2666,3822, 103, # 2512 + 855, 503,1414,1867,2488,1091, 657,1597, 979, 605,1316,4641,1021,2443,2078,2001, # 2528 +1209, 96, 587,2166,1032, 260,1072,2153, 173, 94, 226,3244, 819,2006,4642,4114, # 2544 +2203, 231,1744, 782, 97,2667, 786,3387, 887, 391, 442,2219,4326,1425,6143,2694, # 2560 + 633,1544,1202, 483,2015, 592,2052,1958,2472,1655, 419, 129,4327,3444,3312,1714, # 2576 +1257,3078,4328,1518,1098, 865,1310,1019,1885,1512,1734, 469,2444, 148, 773, 436, # 2592 +1815,1868,1128,1055,4329,1245,2756,3445,2154,1934,1039,4643, 579,1238, 932,2320, # 2608 + 353, 205, 801, 115,2428, 944,2321,1881, 399,2565,1211, 678, 766,3944, 335,2101, # 2624 +1459,1781,1402,3945,2737,2131,1010, 844, 981,1326,1013, 550,1816,1545,2620,1335, # 2640 +1008, 371,2881, 936,1419,1613,3529,1456,1395,2273,1834,2604,1317,2738,2503, 416, # 2656 +1643,4330, 806,1126, 229, 591,3946,1314,1981,1576,1837,1666, 347,1790, 977,3313, # 2672 + 764,2861,1853, 688,2429,1920,1462, 77, 595, 415,2002,3034, 798,1192,4115,6144, # 2688 +2978,4331,3035,2695,2582,2072,2566, 430,2430,1727, 842,1396,3947,3702, 613, 377, # 2704 + 278, 236,1417,3388,3314,3174, 757,1869, 107,3530,6145,1194, 623,2262, 207,1253, # 2720 +2167,3446,3948, 492,1117,1935, 536,1838,2757,1246,4332, 696,2095,2406,1393,1572, # 2736 +3175,1782, 583, 190, 253,1390,2230, 830,3126,3389, 934,3245,1703,1749,2979,1870, # 2752 +2545,1656,2204, 869,2346,4116,3176,1817, 496,1764,4644, 942,1504, 404,1903,1122, # 2768 +1580,3606,2945,1022, 515, 372,1735, 955,2431,3036,6146,2797,1110,2302,2798, 617, # 2784 +6147, 441, 762,1771,3447,3607,3608,1904, 840,3037, 86, 939,1385, 572,1370,2445, # 2800 +1336, 114,3703, 898, 294, 203,3315, 703,1583,2274, 429, 961,4333,1854,1951,3390, # 2816 +2373,3704,4334,1318,1381, 966,1911,2322,1006,1155, 309, 989, 458,2718,1795,1372, # 2832 +1203, 252,1689,1363,3177, 517,1936, 168,1490, 562, 193,3823,1042,4117,1835, 551, # 2848 + 470,4645, 395, 489,3448,1871,1465,2583,2641, 417,1493, 279,1295, 511,1236,1119, # 2864 + 72,1231,1982,1812,3004, 871,1564, 984,3449,1667,2696,2096,4646,2347,2833,1673, # 2880 +3609, 695,3246,2668, 807,1183,4647, 890, 388,2333,1801,1457,2911,1765,1477,1031, # 2896 +3316,3317,1278,3391,2799,2292,2526, 163,3450,4335,2669,1404,1802,6148,2323,2407, # 2912 +1584,1728,1494,1824,1269, 298, 909,3318,1034,1632, 375, 776,1683,2061, 291, 210, # 2928 +1123, 809,1249,1002,2642,3038, 206,1011,2132, 144, 975, 882,1565, 342, 667, 754, # 2944 +1442,2143,1299,2303,2062, 447, 626,2205,1221,2739,2912,1144,1214,2206,2584, 760, # 2960 +1715, 614, 950,1281,2670,2621, 810, 577,1287,2546,4648, 242,2168, 250,2643, 691, # 2976 + 123,2644, 647, 313,1029, 689,1357,2946,1650, 216, 771,1339,1306, 808,2063, 549, # 2992 + 913,1371,2913,2914,6149,1466,1092,1174,1196,1311,2605,2396,1783,1796,3079, 406, # 3008 +2671,2117,3949,4649, 487,1825,2220,6150,2915, 448,2348,1073,6151,2397,1707, 130, # 3024 + 900,1598, 329, 176,1959,2527,1620,6152,2275,4336,3319,1983,2191,3705,3610,2155, # 3040 +3706,1912,1513,1614,6153,1988, 646, 392,2304,1589,3320,3039,1826,1239,1352,1340, # 3056 +2916, 505,2567,1709,1437,2408,2547, 906,6154,2672, 384,1458,1594,1100,1329, 710, # 3072 + 423,3531,2064,2231,2622,1989,2673,1087,1882, 333, 841,3005,1296,2882,2379, 580, # 3088 +1937,1827,1293,2585, 601, 574, 249,1772,4118,2079,1120, 645, 901,1176,1690, 795, # 3104 +2207, 478,1434, 516,1190,1530, 761,2080, 930,1264, 355, 435,1552, 644,1791, 987, # 3120 + 220,1364,1163,1121,1538, 306,2169,1327,1222, 546,2645, 218, 241, 610,1704,3321, # 3136 +1984,1839,1966,2528, 451,6155,2586,3707,2568, 907,3178, 254,2947, 186,1845,4650, # 3152 + 745, 432,1757, 428,1633, 888,2246,2221,2489,3611,2118,1258,1265, 956,3127,1784, # 3168 +4337,2490, 319, 510, 119, 457,3612, 274,2035,2007,4651,1409,3128, 970,2758, 590, # 3184 +2800, 661,2247,4652,2008,3950,1420,1549,3080,3322,3951,1651,1375,2111, 485,2491, # 3200 +1429,1156,6156,2548,2183,1495, 831,1840,2529,2446, 501,1657, 307,1894,3247,1341, # 3216 + 666, 899,2156,1539,2549,1559, 886, 349,2208,3081,2305,1736,3824,2170,2759,1014, # 3232 +1913,1386, 542,1397,2948, 490, 368, 716, 362, 159, 282,2569,1129,1658,1288,1750, # 3248 +2674, 276, 649,2016, 751,1496, 658,1818,1284,1862,2209,2087,2512,3451, 622,2834, # 3264 + 376, 117,1060,2053,1208,1721,1101,1443, 247,1250,3179,1792,3952,2760,2398,3953, # 3280 +6157,2144,3708, 446,2432,1151,2570,3452,2447,2761,2835,1210,2448,3082, 424,2222, # 3296 +1251,2449,2119,2836, 504,1581,4338, 602, 817, 857,3825,2349,2306, 357,3826,1470, # 3312 +1883,2883, 255, 958, 929,2917,3248, 302,4653,1050,1271,1751,2307,1952,1430,2697, # 3328 +2719,2359, 354,3180, 777, 158,2036,4339,1659,4340,4654,2308,2949,2248,1146,2232, # 3344 +3532,2720,1696,2623,3827,6158,3129,1550,2698,1485,1297,1428, 637, 931,2721,2145, # 3360 + 914,2550,2587, 81,2450, 612, 827,2646,1242,4655,1118,2884, 472,1855,3181,3533, # 3376 +3534, 569,1353,2699,1244,1758,2588,4119,2009,2762,2171,3709,1312,1531,6159,1152, # 3392 +1938, 134,1830, 471,3710,2276,1112,1535,3323,3453,3535, 982,1337,2950, 488, 826, # 3408 + 674,1058,1628,4120,2017, 522,2399, 211, 568,1367,3454, 350, 293,1872,1139,3249, # 3424 +1399,1946,3006,1300,2360,3324, 588, 736,6160,2606, 744, 669,3536,3828,6161,1358, # 3440 + 199, 723, 848, 933, 851,1939,1505,1514,1338,1618,1831,4656,1634,3613, 443,2740, # 3456 +3829, 717,1947, 491,1914,6162,2551,1542,4121,1025,6163,1099,1223, 198,3040,2722, # 3472 + 370, 410,1905,2589, 998,1248,3182,2380, 519,1449,4122,1710, 947, 928,1153,4341, # 3488 +2277, 344,2624,1511, 615, 105, 161,1212,1076,1960,3130,2054,1926,1175,1906,2473, # 3504 + 414,1873,2801,6164,2309, 315,1319,3325, 318,2018,2146,2157, 963, 631, 223,4342, # 3520 +4343,2675, 479,3711,1197,2625,3712,2676,2361,6165,4344,4123,6166,2451,3183,1886, # 3536 +2184,1674,1330,1711,1635,1506, 799, 219,3250,3083,3954,1677,3713,3326,2081,3614, # 3552 +1652,2073,4657,1147,3041,1752, 643,1961, 147,1974,3955,6167,1716,2037, 918,3007, # 3568 +1994, 120,1537, 118, 609,3184,4345, 740,3455,1219, 332,1615,3830,6168,1621,2980, # 3584 +1582, 783, 212, 553,2350,3714,1349,2433,2082,4124, 889,6169,2310,1275,1410, 973, # 3600 + 166,1320,3456,1797,1215,3185,2885,1846,2590,2763,4658, 629, 822,3008, 763, 940, # 3616 +1990,2862, 439,2409,1566,1240,1622, 926,1282,1907,2764, 654,2210,1607, 327,1130, # 3632 +3956,1678,1623,6170,2434,2192, 686, 608,3831,3715, 903,3957,3042,6171,2741,1522, # 3648 +1915,1105,1555,2552,1359, 323,3251,4346,3457, 738,1354,2553,2311,2334,1828,2003, # 3664 +3832,1753,2351,1227,6172,1887,4125,1478,6173,2410,1874,1712,1847, 520,1204,2607, # 3680 + 264,4659, 836,2677,2102, 600,4660,3833,2278,3084,6174,4347,3615,1342, 640, 532, # 3696 + 543,2608,1888,2400,2591,1009,4348,1497, 341,1737,3616,2723,1394, 529,3252,1321, # 3712 + 983,4661,1515,2120, 971,2592, 924, 287,1662,3186,4349,2700,4350,1519, 908,1948, # 3728 +2452, 156, 796,1629,1486,2223,2055, 694,4126,1259,1036,3392,1213,2249,2742,1889, # 3744 +1230,3958,1015, 910, 408, 559,3617,4662, 746, 725, 935,4663,3959,3009,1289, 563, # 3760 + 867,4664,3960,1567,2981,2038,2626, 988,2263,2381,4351, 143,2374, 704,1895,6175, # 3776 +1188,3716,2088, 673,3085,2362,4352, 484,1608,1921,2765,2918, 215, 904,3618,3537, # 3792 + 894, 509, 976,3043,2701,3961,4353,2837,2982, 498,6176,6177,1102,3538,1332,3393, # 3808 +1487,1636,1637, 233, 245,3962, 383, 650, 995,3044, 460,1520,1206,2352, 749,3327, # 3824 + 530, 700, 389,1438,1560,1773,3963,2264, 719,2951,2724,3834, 870,1832,1644,1000, # 3840 + 839,2474,3717, 197,1630,3394, 365,2886,3964,1285,2133, 734, 922, 818,1106, 732, # 3856 + 480,2083,1774,3458, 923,2279,1350, 221,3086, 85,2233,2234,3835,1585,3010,2147, # 3872 +1387,1705,2382,1619,2475, 133, 239,2802,1991,1016,2084,2383, 411,2838,1113, 651, # 3888 +1985,1160,3328, 990,1863,3087,1048,1276,2647, 265,2627,1599,3253,2056, 150, 638, # 3904 +2019, 656, 853, 326,1479, 680,1439,4354,1001,1759, 413,3459,3395,2492,1431, 459, # 3920 +4355,1125,3329,2265,1953,1450,2065,2863, 849, 351,2678,3131,3254,3255,1104,1577, # 3936 + 227,1351,1645,2453,2193,1421,2887, 812,2121, 634, 95,2435, 201,2312,4665,1646, # 3952 +1671,2743,1601,2554,2702,2648,2280,1315,1366,2089,3132,1573,3718,3965,1729,1189, # 3968 + 328,2679,1077,1940,1136, 558,1283, 964,1195, 621,2074,1199,1743,3460,3619,1896, # 3984 +1916,1890,3836,2952,1154,2112,1064, 862, 378,3011,2066,2113,2803,1568,2839,6178, # 4000 +3088,2919,1941,1660,2004,1992,2194, 142, 707,1590,1708,1624,1922,1023,1836,1233, # 4016 +1004,2313, 789, 741,3620,6179,1609,2411,1200,4127,3719,3720,4666,2057,3721, 593, # 4032 +2840, 367,2920,1878,6180,3461,1521, 628,1168, 692,2211,2649, 300, 720,2067,2571, # 4048 +2953,3396, 959,2504,3966,3539,3462,1977, 701,6181, 954,1043, 800, 681, 183,3722, # 4064 +1803,1730,3540,4128,2103, 815,2314, 174, 467, 230,2454,1093,2134, 755,3541,3397, # 4080 +1141,1162,6182,1738,2039, 270,3256,2513,1005,1647,2185,3837, 858,1679,1897,1719, # 4096 +2954,2324,1806, 402, 670, 167,4129,1498,2158,2104, 750,6183, 915, 189,1680,1551, # 4112 + 455,4356,1501,2455, 405,1095,2955, 338,1586,1266,1819, 570, 641,1324, 237,1556, # 4128 +2650,1388,3723,6184,1368,2384,1343,1978,3089,2436, 879,3724, 792,1191, 758,3012, # 4144 +1411,2135,1322,4357, 240,4667,1848,3725,1574,6185, 420,3045,1546,1391, 714,4358, # 4160 +1967, 941,1864, 863, 664, 426, 560,1731,2680,1785,2864,1949,2363, 403,3330,1415, # 4176 +1279,2136,1697,2335, 204, 721,2097,3838, 90,6186,2085,2505, 191,3967, 124,2148, # 4192 +1376,1798,1178,1107,1898,1405, 860,4359,1243,1272,2375,2983,1558,2456,1638, 113, # 4208 +3621, 578,1923,2609, 880, 386,4130, 784,2186,2266,1422,2956,2172,1722, 497, 263, # 4224 +2514,1267,2412,2610, 177,2703,3542, 774,1927,1344, 616,1432,1595,1018, 172,4360, # 4240 +2325, 911,4361, 438,1468,3622, 794,3968,2024,2173,1681,1829,2957, 945, 895,3090, # 4256 + 575,2212,2476, 475,2401,2681, 785,2744,1745,2293,2555,1975,3133,2865, 394,4668, # 4272 +3839, 635,4131, 639, 202,1507,2195,2766,1345,1435,2572,3726,1908,1184,1181,2457, # 4288 +3727,3134,4362, 843,2611, 437, 916,4669, 234, 769,1884,3046,3047,3623, 833,6187, # 4304 +1639,2250,2402,1355,1185,2010,2047, 999, 525,1732,1290,1488,2612, 948,1578,3728, # 4320 +2413,2477,1216,2725,2159, 334,3840,1328,3624,2921,1525,4132, 564,1056, 891,4363, # 4336 +1444,1698,2385,2251,3729,1365,2281,2235,1717,6188, 864,3841,2515, 444, 527,2767, # 4352 +2922,3625, 544, 461,6189, 566, 209,2437,3398,2098,1065,2068,3331,3626,3257,2137, # 4368 #last 512 +#Everything below is of no interest for detection purpose +2138,2122,3730,2888,1995,1820,1044,6190,6191,6192,6193,6194,6195,6196,6197,6198, # 4384 +6199,6200,6201,6202,6203,6204,6205,4670,6206,6207,6208,6209,6210,6211,6212,6213, # 4400 +6214,6215,6216,6217,6218,6219,6220,6221,6222,6223,6224,6225,6226,6227,6228,6229, # 4416 +6230,6231,6232,6233,6234,6235,6236,6237,3187,6238,6239,3969,6240,6241,6242,6243, # 4432 +6244,4671,6245,6246,4672,6247,6248,4133,6249,6250,4364,6251,2923,2556,2613,4673, # 4448 +4365,3970,6252,6253,6254,6255,4674,6256,6257,6258,2768,2353,4366,4675,4676,3188, # 4464 +4367,3463,6259,4134,4677,4678,6260,2267,6261,3842,3332,4368,3543,6262,6263,6264, # 4480 +3013,1954,1928,4135,4679,6265,6266,2478,3091,6267,4680,4369,6268,6269,1699,6270, # 4496 +3544,4136,4681,6271,4137,6272,4370,2804,6273,6274,2593,3971,3972,4682,6275,2236, # 4512 +4683,6276,6277,4684,6278,6279,4138,3973,4685,6280,6281,3258,6282,6283,6284,6285, # 4528 +3974,4686,2841,3975,6286,6287,3545,6288,6289,4139,4687,4140,6290,4141,6291,4142, # 4544 +6292,6293,3333,6294,6295,6296,4371,6297,3399,6298,6299,4372,3976,6300,6301,6302, # 4560 +4373,6303,6304,3843,3731,6305,4688,4374,6306,6307,3259,2294,6308,3732,2530,4143, # 4576 +6309,4689,6310,6311,6312,3048,6313,6314,4690,3733,2237,6315,6316,2282,3334,6317, # 4592 +6318,3844,6319,6320,4691,6321,3400,4692,6322,4693,6323,3049,6324,4375,6325,3977, # 4608 +6326,6327,6328,3546,6329,4694,3335,6330,4695,4696,6331,6332,6333,6334,4376,3978, # 4624 +6335,4697,3979,4144,6336,3980,4698,6337,6338,6339,6340,6341,4699,4700,4701,6342, # 4640 +6343,4702,6344,6345,4703,6346,6347,4704,6348,4705,4706,3135,6349,4707,6350,4708, # 4656 +6351,4377,6352,4709,3734,4145,6353,2506,4710,3189,6354,3050,4711,3981,6355,3547, # 4672 +3014,4146,4378,3735,2651,3845,3260,3136,2224,1986,6356,3401,6357,4712,2594,3627, # 4688 +3137,2573,3736,3982,4713,3628,4714,4715,2682,3629,4716,6358,3630,4379,3631,6359, # 4704 +6360,6361,3983,6362,6363,6364,6365,4147,3846,4717,6366,6367,3737,2842,6368,4718, # 4720 +2628,6369,3261,6370,2386,6371,6372,3738,3984,4719,3464,4720,3402,6373,2924,3336, # 4736 +4148,2866,6374,2805,3262,4380,2704,2069,2531,3138,2806,2984,6375,2769,6376,4721, # 4752 +4722,3403,6377,6378,3548,6379,6380,2705,3092,1979,4149,2629,3337,2889,6381,3338, # 4768 +4150,2557,3339,4381,6382,3190,3263,3739,6383,4151,4723,4152,2558,2574,3404,3191, # 4784 +6384,6385,4153,6386,4724,4382,6387,6388,4383,6389,6390,4154,6391,4725,3985,6392, # 4800 +3847,4155,6393,6394,6395,6396,6397,3465,6398,4384,6399,6400,6401,6402,6403,6404, # 4816 +4156,6405,6406,6407,6408,2123,6409,6410,2326,3192,4726,6411,6412,6413,6414,4385, # 4832 +4157,6415,6416,4158,6417,3093,3848,6418,3986,6419,6420,3849,6421,6422,6423,4159, # 4848 +6424,6425,4160,6426,3740,6427,6428,6429,6430,3987,6431,4727,6432,2238,6433,6434, # 4864 +4386,3988,6435,6436,3632,6437,6438,2843,6439,6440,6441,6442,3633,6443,2958,6444, # 4880 +6445,3466,6446,2364,4387,3850,6447,4388,2959,3340,6448,3851,6449,4728,6450,6451, # 4896 +3264,4729,6452,3193,6453,4389,4390,2706,3341,4730,6454,3139,6455,3194,6456,3051, # 4912 +2124,3852,1602,4391,4161,3853,1158,3854,4162,3989,4392,3990,4731,4732,4393,2040, # 4928 +4163,4394,3265,6457,2807,3467,3855,6458,6459,6460,3991,3468,4733,4734,6461,3140, # 4944 +2960,6462,4735,6463,6464,6465,6466,4736,4737,4738,4739,6467,6468,4164,2403,3856, # 4960 +6469,6470,2770,2844,6471,4740,6472,6473,6474,6475,6476,6477,6478,3195,6479,4741, # 4976 +4395,6480,2867,6481,4742,2808,6482,2493,4165,6483,6484,6485,6486,2295,4743,6487, # 4992 +6488,6489,3634,6490,6491,6492,6493,6494,6495,6496,2985,4744,6497,6498,4745,6499, # 5008 +6500,2925,3141,4166,6501,6502,4746,6503,6504,4747,6505,6506,6507,2890,6508,6509, # 5024 +6510,6511,6512,6513,6514,6515,6516,6517,6518,6519,3469,4167,6520,6521,6522,4748, # 5040 +4396,3741,4397,4749,4398,3342,2125,4750,6523,4751,4752,4753,3052,6524,2961,4168, # 5056 +6525,4754,6526,4755,4399,2926,4169,6527,3857,6528,4400,4170,6529,4171,6530,6531, # 5072 +2595,6532,6533,6534,6535,3635,6536,6537,6538,6539,6540,6541,6542,4756,6543,6544, # 5088 +6545,6546,6547,6548,4401,6549,6550,6551,6552,4402,3405,4757,4403,6553,6554,6555, # 5104 +4172,3742,6556,6557,6558,3992,3636,6559,6560,3053,2726,6561,3549,4173,3054,4404, # 5120 +6562,6563,3993,4405,3266,3550,2809,4406,6564,6565,6566,4758,4759,6567,3743,6568, # 5136 +4760,3744,4761,3470,6569,6570,6571,4407,6572,3745,4174,6573,4175,2810,4176,3196, # 5152 +4762,6574,4177,6575,6576,2494,2891,3551,6577,6578,3471,6579,4408,6580,3015,3197, # 5168 +6581,3343,2532,3994,3858,6582,3094,3406,4409,6583,2892,4178,4763,4410,3016,4411, # 5184 +6584,3995,3142,3017,2683,6585,4179,6586,6587,4764,4412,6588,6589,4413,6590,2986, # 5200 +6591,2962,3552,6592,2963,3472,6593,6594,4180,4765,6595,6596,2225,3267,4414,6597, # 5216 +3407,3637,4766,6598,6599,3198,6600,4415,6601,3859,3199,6602,3473,4767,2811,4416, # 5232 +1856,3268,3200,2575,3996,3997,3201,4417,6603,3095,2927,6604,3143,6605,2268,6606, # 5248 +3998,3860,3096,2771,6607,6608,3638,2495,4768,6609,3861,6610,3269,2745,4769,4181, # 5264 +3553,6611,2845,3270,6612,6613,6614,3862,6615,6616,4770,4771,6617,3474,3999,4418, # 5280 +4419,6618,3639,3344,6619,4772,4182,6620,2126,6621,6622,6623,4420,4773,6624,3018, # 5296 +6625,4774,3554,6626,4183,2025,3746,6627,4184,2707,6628,4421,4422,3097,1775,4185, # 5312 +3555,6629,6630,2868,6631,6632,4423,6633,6634,4424,2414,2533,2928,6635,4186,2387, # 5328 +6636,4775,6637,4187,6638,1891,4425,3202,3203,6639,6640,4776,6641,3345,6642,6643, # 5344 +3640,6644,3475,3346,3641,4000,6645,3144,6646,3098,2812,4188,3642,3204,6647,3863, # 5360 +3476,6648,3864,6649,4426,4001,6650,6651,6652,2576,6653,4189,4777,6654,6655,6656, # 5376 +2846,6657,3477,3205,4002,6658,4003,6659,3347,2252,6660,6661,6662,4778,6663,6664, # 5392 +6665,6666,6667,6668,6669,4779,4780,2048,6670,3478,3099,6671,3556,3747,4004,6672, # 5408 +6673,6674,3145,4005,3748,6675,6676,6677,6678,6679,3408,6680,6681,6682,6683,3206, # 5424 +3207,6684,6685,4781,4427,6686,4782,4783,4784,6687,6688,6689,4190,6690,6691,3479, # 5440 +6692,2746,6693,4428,6694,6695,6696,6697,6698,6699,4785,6700,6701,3208,2727,6702, # 5456 +3146,6703,6704,3409,2196,6705,4429,6706,6707,6708,2534,1996,6709,6710,6711,2747, # 5472 +6712,6713,6714,4786,3643,6715,4430,4431,6716,3557,6717,4432,4433,6718,6719,6720, # 5488 +6721,3749,6722,4006,4787,6723,6724,3644,4788,4434,6725,6726,4789,2772,6727,6728, # 5504 +6729,6730,6731,2708,3865,2813,4435,6732,6733,4790,4791,3480,6734,6735,6736,6737, # 5520 +4436,3348,6738,3410,4007,6739,6740,4008,6741,6742,4792,3411,4191,6743,6744,6745, # 5536 +6746,6747,3866,6748,3750,6749,6750,6751,6752,6753,6754,6755,3867,6756,4009,6757, # 5552 +4793,4794,6758,2814,2987,6759,6760,6761,4437,6762,6763,6764,6765,3645,6766,6767, # 5568 +3481,4192,6768,3751,6769,6770,2174,6771,3868,3752,6772,6773,6774,4193,4795,4438, # 5584 +3558,4796,4439,6775,4797,6776,6777,4798,6778,4799,3559,4800,6779,6780,6781,3482, # 5600 +6782,2893,6783,6784,4194,4801,4010,6785,6786,4440,6787,4011,6788,6789,6790,6791, # 5616 +6792,6793,4802,6794,6795,6796,4012,6797,6798,6799,6800,3349,4803,3483,6801,4804, # 5632 +4195,6802,4013,6803,6804,4196,6805,4014,4015,6806,2847,3271,2848,6807,3484,6808, # 5648 +6809,6810,4441,6811,4442,4197,4443,3272,4805,6812,3412,4016,1579,6813,6814,4017, # 5664 +6815,3869,6816,2964,6817,4806,6818,6819,4018,3646,6820,6821,4807,4019,4020,6822, # 5680 +6823,3560,6824,6825,4021,4444,6826,4198,6827,6828,4445,6829,6830,4199,4808,6831, # 5696 +6832,6833,3870,3019,2458,6834,3753,3413,3350,6835,4809,3871,4810,3561,4446,6836, # 5712 +6837,4447,4811,4812,6838,2459,4448,6839,4449,6840,6841,4022,3872,6842,4813,4814, # 5728 +6843,6844,4815,4200,4201,4202,6845,4023,6846,6847,4450,3562,3873,6848,6849,4816, # 5744 +4817,6850,4451,4818,2139,6851,3563,6852,6853,3351,6854,6855,3352,4024,2709,3414, # 5760 +4203,4452,6856,4204,6857,6858,3874,3875,6859,6860,4819,6861,6862,6863,6864,4453, # 5776 +3647,6865,6866,4820,6867,6868,6869,6870,4454,6871,2869,6872,6873,4821,6874,3754, # 5792 +6875,4822,4205,6876,6877,6878,3648,4206,4455,6879,4823,6880,4824,3876,6881,3055, # 5808 +4207,6882,3415,6883,6884,6885,4208,4209,6886,4210,3353,6887,3354,3564,3209,3485, # 5824 +2652,6888,2728,6889,3210,3755,6890,4025,4456,6891,4825,6892,6893,6894,6895,4211, # 5840 +6896,6897,6898,4826,6899,6900,4212,6901,4827,6902,2773,3565,6903,4828,6904,6905, # 5856 +6906,6907,3649,3650,6908,2849,3566,6909,3567,3100,6910,6911,6912,6913,6914,6915, # 5872 +4026,6916,3355,4829,3056,4457,3756,6917,3651,6918,4213,3652,2870,6919,4458,6920, # 5888 +2438,6921,6922,3757,2774,4830,6923,3356,4831,4832,6924,4833,4459,3653,2507,6925, # 5904 +4834,2535,6926,6927,3273,4027,3147,6928,3568,6929,6930,6931,4460,6932,3877,4461, # 5920 +2729,3654,6933,6934,6935,6936,2175,4835,2630,4214,4028,4462,4836,4215,6937,3148, # 5936 +4216,4463,4837,4838,4217,6938,6939,2850,4839,6940,4464,6941,6942,6943,4840,6944, # 5952 +4218,3274,4465,6945,6946,2710,6947,4841,4466,6948,6949,2894,6950,6951,4842,6952, # 5968 +4219,3057,2871,6953,6954,6955,6956,4467,6957,2711,6958,6959,6960,3275,3101,4843, # 5984 +6961,3357,3569,6962,4844,6963,6964,4468,4845,3570,6965,3102,4846,3758,6966,4847, # 6000 +3878,4848,4849,4029,6967,2929,3879,4850,4851,6968,6969,1733,6970,4220,6971,6972, # 6016 +6973,6974,6975,6976,4852,6977,6978,6979,6980,6981,6982,3759,6983,6984,6985,3486, # 6032 +3487,6986,3488,3416,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,4853, # 6048 +6998,6999,4030,7000,7001,3211,7002,7003,4221,7004,7005,3571,4031,7006,3572,7007, # 6064 +2614,4854,2577,7008,7009,2965,3655,3656,4855,2775,3489,3880,4222,4856,3881,4032, # 6080 +3882,3657,2730,3490,4857,7010,3149,7011,4469,4858,2496,3491,4859,2283,7012,7013, # 6096 +7014,2365,4860,4470,7015,7016,3760,7017,7018,4223,1917,7019,7020,7021,4471,7022, # 6112 +2776,4472,7023,7024,7025,7026,4033,7027,3573,4224,4861,4034,4862,7028,7029,1929, # 6128 +3883,4035,7030,4473,3058,7031,2536,3761,3884,7032,4036,7033,2966,2895,1968,4474, # 6144 +3276,4225,3417,3492,4226,2105,7034,7035,1754,2596,3762,4227,4863,4475,3763,4864, # 6160 +3764,2615,2777,3103,3765,3658,3418,4865,2296,3766,2815,7036,7037,7038,3574,2872, # 6176 +3277,4476,7039,4037,4477,7040,7041,4038,7042,7043,7044,7045,7046,7047,2537,7048, # 6192 +7049,7050,7051,7052,7053,7054,4478,7055,7056,3767,3659,4228,3575,7057,7058,4229, # 6208 +7059,7060,7061,3660,7062,3212,7063,3885,4039,2460,7064,7065,7066,7067,7068,7069, # 6224 +7070,7071,7072,7073,7074,4866,3768,4867,7075,7076,7077,7078,4868,3358,3278,2653, # 6240 +7079,7080,4479,3886,7081,7082,4869,7083,7084,7085,7086,7087,7088,2538,7089,7090, # 6256 +7091,4040,3150,3769,4870,4041,2896,3359,4230,2930,7092,3279,7093,2967,4480,3213, # 6272 +4481,3661,7094,7095,7096,7097,7098,7099,7100,7101,7102,2461,3770,7103,7104,4231, # 6288 +3151,7105,7106,7107,4042,3662,7108,7109,4871,3663,4872,4043,3059,7110,7111,7112, # 6304 +3493,2988,7113,4873,7114,7115,7116,3771,4874,7117,7118,4232,4875,7119,3576,2336, # 6320 +4876,7120,4233,3419,4044,4877,4878,4482,4483,4879,4484,4234,7121,3772,4880,1045, # 6336 +3280,3664,4881,4882,7122,7123,7124,7125,4883,7126,2778,7127,4485,4486,7128,4884, # 6352 +3214,3887,7129,7130,3215,7131,4885,4045,7132,7133,4046,7134,7135,7136,7137,7138, # 6368 +7139,7140,7141,7142,7143,4235,7144,4886,7145,7146,7147,4887,7148,7149,7150,4487, # 6384 +4047,4488,7151,7152,4888,4048,2989,3888,7153,3665,7154,4049,7155,7156,7157,7158, # 6400 +7159,7160,2931,4889,4890,4489,7161,2631,3889,4236,2779,7162,7163,4891,7164,3060, # 6416 +7165,1672,4892,7166,4893,4237,3281,4894,7167,7168,3666,7169,3494,7170,7171,4050, # 6432 +7172,7173,3104,3360,3420,4490,4051,2684,4052,7174,4053,7175,7176,7177,2253,4054, # 6448 +7178,7179,4895,7180,3152,3890,3153,4491,3216,7181,7182,7183,2968,4238,4492,4055, # 6464 +7184,2990,7185,2479,7186,7187,4493,7188,7189,7190,7191,7192,4896,7193,4897,2969, # 6480 +4494,4898,7194,3495,7195,7196,4899,4495,7197,3105,2731,7198,4900,7199,7200,7201, # 6496 +4056,7202,3361,7203,7204,4496,4901,4902,7205,4497,7206,7207,2315,4903,7208,4904, # 6512 +7209,4905,2851,7210,7211,3577,7212,3578,4906,7213,4057,3667,4907,7214,4058,2354, # 6528 +3891,2376,3217,3773,7215,7216,7217,7218,7219,4498,7220,4908,3282,2685,7221,3496, # 6544 +4909,2632,3154,4910,7222,2337,7223,4911,7224,7225,7226,4912,4913,3283,4239,4499, # 6560 +7227,2816,7228,7229,7230,7231,7232,7233,7234,4914,4500,4501,7235,7236,7237,2686, # 6576 +7238,4915,7239,2897,4502,7240,4503,7241,2516,7242,4504,3362,3218,7243,7244,7245, # 6592 +4916,7246,7247,4505,3363,7248,7249,7250,7251,3774,4506,7252,7253,4917,7254,7255, # 6608 +3284,2991,4918,4919,3219,3892,4920,3106,3497,4921,7256,7257,7258,4922,7259,4923, # 6624 +3364,4507,4508,4059,7260,4240,3498,7261,7262,4924,7263,2992,3893,4060,3220,7264, # 6640 +7265,7266,7267,7268,7269,4509,3775,7270,2817,7271,4061,4925,4510,3776,7272,4241, # 6656 +4511,3285,7273,7274,3499,7275,7276,7277,4062,4512,4926,7278,3107,3894,7279,7280, # 6672 +4927,7281,4513,7282,7283,3668,7284,7285,4242,4514,4243,7286,2058,4515,4928,4929, # 6688 +4516,7287,3286,4244,7288,4517,7289,7290,7291,3669,7292,7293,4930,4931,4932,2355, # 6704 +4933,7294,2633,4518,7295,4245,7296,7297,4519,7298,7299,4520,4521,4934,7300,4246, # 6720 +4522,7301,7302,7303,3579,7304,4247,4935,7305,4936,7306,7307,7308,7309,3777,7310, # 6736 +4523,7311,7312,7313,4248,3580,7314,4524,3778,4249,7315,3581,7316,3287,7317,3221, # 6752 +7318,4937,7319,7320,7321,7322,7323,7324,4938,4939,7325,4525,7326,7327,7328,4063, # 6768 +7329,7330,4940,7331,7332,4941,7333,4526,7334,3500,2780,1741,4942,2026,1742,7335, # 6784 +7336,3582,4527,2388,7337,7338,7339,4528,7340,4250,4943,7341,7342,7343,4944,7344, # 6800 +7345,7346,3020,7347,4945,7348,7349,7350,7351,3895,7352,3896,4064,3897,7353,7354, # 6816 +7355,4251,7356,7357,3898,7358,3779,7359,3780,3288,7360,7361,4529,7362,4946,4530, # 6832 +2027,7363,3899,4531,4947,3222,3583,7364,4948,7365,7366,7367,7368,4949,3501,4950, # 6848 +3781,4951,4532,7369,2517,4952,4252,4953,3155,7370,4954,4955,4253,2518,4533,7371, # 6864 +7372,2712,4254,7373,7374,7375,3670,4956,3671,7376,2389,3502,4065,7377,2338,7378, # 6880 +7379,7380,7381,3061,7382,4957,7383,7384,7385,7386,4958,4534,7387,7388,2993,7389, # 6896 +3062,7390,4959,7391,7392,7393,4960,3108,4961,7394,4535,7395,4962,3421,4536,7396, # 6912 +4963,7397,4964,1857,7398,4965,7399,7400,2176,3584,4966,7401,7402,3422,4537,3900, # 6928 +3585,7403,3782,7404,2852,7405,7406,7407,4538,3783,2654,3423,4967,4539,7408,3784, # 6944 +3586,2853,4540,4541,7409,3901,7410,3902,7411,7412,3785,3109,2327,3903,7413,7414, # 6960 +2970,4066,2932,7415,7416,7417,3904,3672,3424,7418,4542,4543,4544,7419,4968,7420, # 6976 +7421,4255,7422,7423,7424,7425,7426,4067,7427,3673,3365,4545,7428,3110,2559,3674, # 6992 +7429,7430,3156,7431,7432,3503,7433,3425,4546,7434,3063,2873,7435,3223,4969,4547, # 7008 +4548,2898,4256,4068,7436,4069,3587,3786,2933,3787,4257,4970,4971,3788,7437,4972, # 7024 +3064,7438,4549,7439,7440,7441,7442,7443,4973,3905,7444,2874,7445,7446,7447,7448, # 7040 +3021,7449,4550,3906,3588,4974,7450,7451,3789,3675,7452,2578,7453,4070,7454,7455, # 7056 +7456,4258,3676,7457,4975,7458,4976,4259,3790,3504,2634,4977,3677,4551,4260,7459, # 7072 +7460,7461,7462,3907,4261,4978,7463,7464,7465,7466,4979,4980,7467,7468,2213,4262, # 7088 +7469,7470,7471,3678,4981,7472,2439,7473,4263,3224,3289,7474,3908,2415,4982,7475, # 7104 +4264,7476,4983,2655,7477,7478,2732,4552,2854,2875,7479,7480,4265,7481,4553,4984, # 7120 +7482,7483,4266,7484,3679,3366,3680,2818,2781,2782,3367,3589,4554,3065,7485,4071, # 7136 +2899,7486,7487,3157,2462,4072,4555,4073,4985,4986,3111,4267,2687,3368,4556,4074, # 7152 +3791,4268,7488,3909,2783,7489,2656,1962,3158,4557,4987,1963,3159,3160,7490,3112, # 7168 +4988,4989,3022,4990,4991,3792,2855,7491,7492,2971,4558,7493,7494,4992,7495,7496, # 7184 +7497,7498,4993,7499,3426,4559,4994,7500,3681,4560,4269,4270,3910,7501,4075,4995, # 7200 +4271,7502,7503,4076,7504,4996,7505,3225,4997,4272,4077,2819,3023,7506,7507,2733, # 7216 +4561,7508,4562,7509,3369,3793,7510,3590,2508,7511,7512,4273,3113,2994,2616,7513, # 7232 +7514,7515,7516,7517,7518,2820,3911,4078,2748,7519,7520,4563,4998,7521,7522,7523, # 7248 +7524,4999,4274,7525,4564,3682,2239,4079,4565,7526,7527,7528,7529,5000,7530,7531, # 7264 +5001,4275,3794,7532,7533,7534,3066,5002,4566,3161,7535,7536,4080,7537,3162,7538, # 7280 +7539,4567,7540,7541,7542,7543,7544,7545,5003,7546,4568,7547,7548,7549,7550,7551, # 7296 +7552,7553,7554,7555,7556,5004,7557,7558,7559,5005,7560,3795,7561,4569,7562,7563, # 7312 +7564,2821,3796,4276,4277,4081,7565,2876,7566,5006,7567,7568,2900,7569,3797,3912, # 7328 +7570,7571,7572,4278,7573,7574,7575,5007,7576,7577,5008,7578,7579,4279,2934,7580, # 7344 +7581,5009,7582,4570,7583,4280,7584,7585,7586,4571,4572,3913,7587,4573,3505,7588, # 7360 +5010,7589,7590,7591,7592,3798,4574,7593,7594,5011,7595,4281,7596,7597,7598,4282, # 7376 +5012,7599,7600,5013,3163,7601,5014,7602,3914,7603,7604,2734,4575,4576,4577,7605, # 7392 +7606,7607,7608,7609,3506,5015,4578,7610,4082,7611,2822,2901,2579,3683,3024,4579, # 7408 +3507,7612,4580,7613,3226,3799,5016,7614,7615,7616,7617,7618,7619,7620,2995,3290, # 7424 +7621,4083,7622,5017,7623,7624,7625,7626,7627,4581,3915,7628,3291,7629,5018,7630, # 7440 +7631,7632,7633,4084,7634,7635,3427,3800,7636,7637,4582,7638,5019,4583,5020,7639, # 7456 +3916,7640,3801,5021,4584,4283,7641,7642,3428,3591,2269,7643,2617,7644,4585,3592, # 7472 +7645,4586,2902,7646,7647,3227,5022,7648,4587,7649,4284,7650,7651,7652,4588,2284, # 7488 +7653,5023,7654,7655,7656,4589,5024,3802,7657,7658,5025,3508,4590,7659,7660,7661, # 7504 +1969,5026,7662,7663,3684,1821,2688,7664,2028,2509,4285,7665,2823,1841,7666,2689, # 7520 +3114,7667,3917,4085,2160,5027,5028,2972,7668,5029,7669,7670,7671,3593,4086,7672, # 7536 +4591,4087,5030,3803,7673,7674,7675,7676,7677,7678,7679,4286,2366,4592,4593,3067, # 7552 +2328,7680,7681,4594,3594,3918,2029,4287,7682,5031,3919,3370,4288,4595,2856,7683, # 7568 +3509,7684,7685,5032,5033,7686,7687,3804,2784,7688,7689,7690,7691,3371,7692,7693, # 7584 +2877,5034,7694,7695,3920,4289,4088,7696,7697,7698,5035,7699,5036,4290,5037,5038, # 7600 +5039,7700,7701,7702,5040,5041,3228,7703,1760,7704,5042,3229,4596,2106,4089,7705, # 7616 +4597,2824,5043,2107,3372,7706,4291,4090,5044,7707,4091,7708,5045,3025,3805,4598, # 7632 +4292,4293,4294,3373,7709,4599,7710,5046,7711,7712,5047,5048,3806,7713,7714,7715, # 7648 +5049,7716,7717,7718,7719,4600,5050,7720,7721,7722,5051,7723,4295,3429,7724,7725, # 7664 +7726,7727,3921,7728,3292,5052,4092,7729,7730,7731,7732,7733,7734,7735,5053,5054, # 7680 +7736,7737,7738,7739,3922,3685,7740,7741,7742,7743,2635,5055,7744,5056,4601,7745, # 7696 +7746,2560,7747,7748,7749,7750,3923,7751,7752,7753,7754,7755,4296,2903,7756,7757, # 7712 +7758,7759,7760,3924,7761,5057,4297,7762,7763,5058,4298,7764,4093,7765,7766,5059, # 7728 +3925,7767,7768,7769,7770,7771,7772,7773,7774,7775,7776,3595,7777,4299,5060,4094, # 7744 +7778,3293,5061,7779,7780,4300,7781,7782,4602,7783,3596,7784,7785,3430,2367,7786, # 7760 +3164,5062,5063,4301,7787,7788,4095,5064,5065,7789,3374,3115,7790,7791,7792,7793, # 7776 +7794,7795,7796,3597,4603,7797,7798,3686,3116,3807,5066,7799,7800,5067,7801,7802, # 7792 +4604,4302,5068,4303,4096,7803,7804,3294,7805,7806,5069,4605,2690,7807,3026,7808, # 7808 +7809,7810,7811,7812,7813,7814,7815,7816,7817,7818,7819,7820,7821,7822,7823,7824, # 7824 +7825,7826,7827,7828,7829,7830,7831,7832,7833,7834,7835,7836,7837,7838,7839,7840, # 7840 +7841,7842,7843,7844,7845,7846,7847,7848,7849,7850,7851,7852,7853,7854,7855,7856, # 7856 +7857,7858,7859,7860,7861,7862,7863,7864,7865,7866,7867,7868,7869,7870,7871,7872, # 7872 +7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886,7887,7888, # 7888 +7889,7890,7891,7892,7893,7894,7895,7896,7897,7898,7899,7900,7901,7902,7903,7904, # 7904 +7905,7906,7907,7908,7909,7910,7911,7912,7913,7914,7915,7916,7917,7918,7919,7920, # 7920 +7921,7922,7923,7924,3926,7925,7926,7927,7928,7929,7930,7931,7932,7933,7934,7935, # 7936 +7936,7937,7938,7939,7940,7941,7942,7943,7944,7945,7946,7947,7948,7949,7950,7951, # 7952 +7952,7953,7954,7955,7956,7957,7958,7959,7960,7961,7962,7963,7964,7965,7966,7967, # 7968 +7968,7969,7970,7971,7972,7973,7974,7975,7976,7977,7978,7979,7980,7981,7982,7983, # 7984 +7984,7985,7986,7987,7988,7989,7990,7991,7992,7993,7994,7995,7996,7997,7998,7999, # 8000 +8000,8001,8002,8003,8004,8005,8006,8007,8008,8009,8010,8011,8012,8013,8014,8015, # 8016 +8016,8017,8018,8019,8020,8021,8022,8023,8024,8025,8026,8027,8028,8029,8030,8031, # 8032 +8032,8033,8034,8035,8036,8037,8038,8039,8040,8041,8042,8043,8044,8045,8046,8047, # 8048 +8048,8049,8050,8051,8052,8053,8054,8055,8056,8057,8058,8059,8060,8061,8062,8063, # 8064 +8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079, # 8080 +8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095, # 8096 +8096,8097,8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110,8111, # 8112 +8112,8113,8114,8115,8116,8117,8118,8119,8120,8121,8122,8123,8124,8125,8126,8127, # 8128 +8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,8138,8139,8140,8141,8142,8143, # 8144 +8144,8145,8146,8147,8148,8149,8150,8151,8152,8153,8154,8155,8156,8157,8158,8159, # 8160 +8160,8161,8162,8163,8164,8165,8166,8167,8168,8169,8170,8171,8172,8173,8174,8175, # 8176 +8176,8177,8178,8179,8180,8181,8182,8183,8184,8185,8186,8187,8188,8189,8190,8191, # 8192 +8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8203,8204,8205,8206,8207, # 8208 +8208,8209,8210,8211,8212,8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223, # 8224 +8224,8225,8226,8227,8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239, # 8240 +8240,8241,8242,8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,8255, # 8256 +8256,8257,8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,8270,8271) # 8272 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/jpcntx.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/jpcntx.py new file mode 100755 index 0000000..93db4a9 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/jpcntx.py @@ -0,0 +1,210 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants + +NUM_OF_CATEGORY = 6 +DONT_KNOW = -1 +ENOUGH_REL_THRESHOLD = 100 +MAX_REL_THRESHOLD = 1000 +MINIMUM_DATA_THRESHOLD = 4 + +# This is hiragana 2-char sequence table, the number in each cell represents its frequency category +jp2CharContext = ( \ +(0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1), +(2,4,0,4,0,3,0,4,0,3,4,4,4,2,4,3,3,4,3,2,3,3,4,2,3,3,3,2,4,1,4,3,3,1,5,4,3,4,3,4,3,5,3,0,3,5,4,2,0,3,1,0,3,3,0,3,3,0,1,1,0,4,3,0,3,3,0,4,0,2,0,3,5,5,5,5,4,0,4,1,0,3,4), +(0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2), +(0,4,0,5,0,5,0,4,0,4,5,4,4,3,5,3,5,1,5,3,4,3,4,4,3,4,3,3,4,3,5,4,4,3,5,5,3,5,5,5,3,5,5,3,4,5,5,3,1,3,2,0,3,4,0,4,2,0,4,2,1,5,3,2,3,5,0,4,0,2,0,5,4,4,5,4,5,0,4,0,0,4,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,4,0,3,0,3,0,4,5,4,3,3,3,3,4,3,5,4,4,3,5,4,4,3,4,3,4,4,4,4,5,3,4,4,3,4,5,5,4,5,5,1,4,5,4,3,0,3,3,1,3,3,0,4,4,0,3,3,1,5,3,3,3,5,0,4,0,3,0,4,4,3,4,3,3,0,4,1,1,3,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,4,0,3,0,3,0,4,0,3,4,4,3,2,2,1,2,1,3,1,3,3,3,3,3,4,3,1,3,3,5,3,3,0,4,3,0,5,4,3,3,5,4,4,3,4,4,5,0,1,2,0,1,2,0,2,2,0,1,0,0,5,2,2,1,4,0,3,0,1,0,4,4,3,5,4,3,0,2,1,0,4,3), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,5,0,4,0,2,1,4,4,2,4,1,4,2,4,2,4,3,3,3,4,3,3,3,3,1,4,2,3,3,3,1,4,4,1,1,1,4,3,3,2,0,2,4,3,2,0,3,3,0,3,1,1,0,0,0,3,3,0,4,2,2,3,4,0,4,0,3,0,4,4,5,3,4,4,0,3,0,0,1,4), +(1,4,0,4,0,4,0,4,0,3,5,4,4,3,4,3,5,4,3,3,4,3,5,4,4,4,4,3,4,2,4,3,3,1,5,4,3,2,4,5,4,5,5,4,4,5,4,4,0,3,2,2,3,3,0,4,3,1,3,2,1,4,3,3,4,5,0,3,0,2,0,4,5,5,4,5,4,0,4,0,0,5,4), +(0,5,0,5,0,4,0,3,0,4,4,3,4,3,3,3,4,0,4,4,4,3,4,3,4,3,3,1,4,2,4,3,4,0,5,4,1,4,5,4,4,5,3,2,4,3,4,3,2,4,1,3,3,3,2,3,2,0,4,3,3,4,3,3,3,4,0,4,0,3,0,4,5,4,4,4,3,0,4,1,0,1,3), +(0,3,1,4,0,3,0,2,0,3,4,4,3,1,4,2,3,3,4,3,4,3,4,3,4,4,3,2,3,1,5,4,4,1,4,4,3,5,4,4,3,5,5,4,3,4,4,3,1,2,3,1,2,2,0,3,2,0,3,1,0,5,3,3,3,4,3,3,3,3,4,4,4,4,5,4,2,0,3,3,2,4,3), +(0,2,0,3,0,1,0,1,0,0,3,2,0,0,2,0,1,0,2,1,3,3,3,1,2,3,1,0,1,0,4,2,1,1,3,3,0,4,3,3,1,4,3,3,0,3,3,2,0,0,0,0,1,0,0,2,0,0,0,0,0,4,1,0,2,3,2,2,2,1,3,3,3,4,4,3,2,0,3,1,0,3,3), +(0,4,0,4,0,3,0,3,0,4,4,4,3,3,3,3,3,3,4,3,4,2,4,3,4,3,3,2,4,3,4,5,4,1,4,5,3,5,4,5,3,5,4,0,3,5,5,3,1,3,3,2,2,3,0,3,4,1,3,3,2,4,3,3,3,4,0,4,0,3,0,4,5,4,4,5,3,0,4,1,0,3,4), +(0,2,0,3,0,3,0,0,0,2,2,2,1,0,1,0,0,0,3,0,3,0,3,0,1,3,1,0,3,1,3,3,3,1,3,3,3,0,1,3,1,3,4,0,0,3,1,1,0,3,2,0,0,0,0,1,3,0,1,0,0,3,3,2,0,3,0,0,0,0,0,3,4,3,4,3,3,0,3,0,0,2,3), +(2,3,0,3,0,2,0,1,0,3,3,4,3,1,3,1,1,1,3,1,4,3,4,3,3,3,0,0,3,1,5,4,3,1,4,3,2,5,5,4,4,4,4,3,3,4,4,4,0,2,1,1,3,2,0,1,2,0,0,1,0,4,1,3,3,3,0,3,0,1,0,4,4,4,5,5,3,0,2,0,0,4,4), +(0,2,0,1,0,3,1,3,0,2,3,3,3,0,3,1,0,0,3,0,3,2,3,1,3,2,1,1,0,0,4,2,1,0,2,3,1,4,3,2,0,4,4,3,1,3,1,3,0,1,0,0,1,0,0,0,1,0,0,0,0,4,1,1,1,2,0,3,0,0,0,3,4,2,4,3,2,0,1,0,0,3,3), +(0,1,0,4,0,5,0,4,0,2,4,4,2,3,3,2,3,3,5,3,3,3,4,3,4,2,3,0,4,3,3,3,4,1,4,3,2,1,5,5,3,4,5,1,3,5,4,2,0,3,3,0,1,3,0,4,2,0,1,3,1,4,3,3,3,3,0,3,0,1,0,3,4,4,4,5,5,0,3,0,1,4,5), +(0,2,0,3,0,3,0,0,0,2,3,1,3,0,4,0,1,1,3,0,3,4,3,2,3,1,0,3,3,2,3,1,3,0,2,3,0,2,1,4,1,2,2,0,0,3,3,0,0,2,0,0,0,1,0,0,0,0,2,2,0,3,2,1,3,3,0,2,0,2,0,0,3,3,1,2,4,0,3,0,2,2,3), +(2,4,0,5,0,4,0,4,0,2,4,4,4,3,4,3,3,3,1,2,4,3,4,3,4,4,5,0,3,3,3,3,2,0,4,3,1,4,3,4,1,4,4,3,3,4,4,3,1,2,3,0,4,2,0,4,1,0,3,3,0,4,3,3,3,4,0,4,0,2,0,3,5,3,4,5,2,0,3,0,0,4,5), +(0,3,0,4,0,1,0,1,0,1,3,2,2,1,3,0,3,0,2,0,2,0,3,0,2,0,0,0,1,0,1,1,0,0,3,1,0,0,0,4,0,3,1,0,2,1,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,4,2,2,3,1,0,3,0,0,0,1,4,4,4,3,0,0,4,0,0,1,4), +(1,4,1,5,0,3,0,3,0,4,5,4,4,3,5,3,3,4,4,3,4,1,3,3,3,3,2,1,4,1,5,4,3,1,4,4,3,5,4,4,3,5,4,3,3,4,4,4,0,3,3,1,2,3,0,3,1,0,3,3,0,5,4,4,4,4,4,4,3,3,5,4,4,3,3,5,4,0,3,2,0,4,4), +(0,2,0,3,0,1,0,0,0,1,3,3,3,2,4,1,3,0,3,1,3,0,2,2,1,1,0,0,2,0,4,3,1,0,4,3,0,4,4,4,1,4,3,1,1,3,3,1,0,2,0,0,1,3,0,0,0,0,2,0,0,4,3,2,4,3,5,4,3,3,3,4,3,3,4,3,3,0,2,1,0,3,3), +(0,2,0,4,0,3,0,2,0,2,5,5,3,4,4,4,4,1,4,3,3,0,4,3,4,3,1,3,3,2,4,3,0,3,4,3,0,3,4,4,2,4,4,0,4,5,3,3,2,2,1,1,1,2,0,1,5,0,3,3,2,4,3,3,3,4,0,3,0,2,0,4,4,3,5,5,0,0,3,0,2,3,3), +(0,3,0,4,0,3,0,1,0,3,4,3,3,1,3,3,3,0,3,1,3,0,4,3,3,1,1,0,3,0,3,3,0,0,4,4,0,1,5,4,3,3,5,0,3,3,4,3,0,2,0,1,1,1,0,1,3,0,1,2,1,3,3,2,3,3,0,3,0,1,0,1,3,3,4,4,1,0,1,2,2,1,3), +(0,1,0,4,0,4,0,3,0,1,3,3,3,2,3,1,1,0,3,0,3,3,4,3,2,4,2,0,1,0,4,3,2,0,4,3,0,5,3,3,2,4,4,4,3,3,3,4,0,1,3,0,0,1,0,0,1,0,0,0,0,4,2,3,3,3,0,3,0,0,0,4,4,4,5,3,2,0,3,3,0,3,5), +(0,2,0,3,0,0,0,3,0,1,3,0,2,0,0,0,1,0,3,1,1,3,3,0,0,3,0,0,3,0,2,3,1,0,3,1,0,3,3,2,0,4,2,2,0,2,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,2,1,2,0,1,0,1,0,0,0,1,3,1,2,0,0,0,1,0,0,1,4), +(0,3,0,3,0,5,0,1,0,2,4,3,1,3,3,2,1,1,5,2,1,0,5,1,2,0,0,0,3,3,2,2,3,2,4,3,0,0,3,3,1,3,3,0,2,5,3,4,0,3,3,0,1,2,0,2,2,0,3,2,0,2,2,3,3,3,0,2,0,1,0,3,4,4,2,5,4,0,3,0,0,3,5), +(0,3,0,3,0,3,0,1,0,3,3,3,3,0,3,0,2,0,2,1,1,0,2,0,1,0,0,0,2,1,0,0,1,0,3,2,0,0,3,3,1,2,3,1,0,3,3,0,0,1,0,0,0,0,0,2,0,0,0,0,0,2,3,1,2,3,0,3,0,1,0,3,2,1,0,4,3,0,1,1,0,3,3), +(0,4,0,5,0,3,0,3,0,4,5,5,4,3,5,3,4,3,5,3,3,2,5,3,4,4,4,3,4,3,4,5,5,3,4,4,3,4,4,5,4,4,4,3,4,5,5,4,2,3,4,2,3,4,0,3,3,1,4,3,2,4,3,3,5,5,0,3,0,3,0,5,5,5,5,4,4,0,4,0,1,4,4), +(0,4,0,4,0,3,0,3,0,3,5,4,4,2,3,2,5,1,3,2,5,1,4,2,3,2,3,3,4,3,3,3,3,2,5,4,1,3,3,5,3,4,4,0,4,4,3,1,1,3,1,0,2,3,0,2,3,0,3,0,0,4,3,1,3,4,0,3,0,2,0,4,4,4,3,4,5,0,4,0,0,3,4), +(0,3,0,3,0,3,1,2,0,3,4,4,3,3,3,0,2,2,4,3,3,1,3,3,3,1,1,0,3,1,4,3,2,3,4,4,2,4,4,4,3,4,4,3,2,4,4,3,1,3,3,1,3,3,0,4,1,0,2,2,1,4,3,2,3,3,5,4,3,3,5,4,4,3,3,0,4,0,3,2,2,4,4), +(0,2,0,1,0,0,0,0,0,1,2,1,3,0,0,0,0,0,2,0,1,2,1,0,0,1,0,0,0,0,3,0,0,1,0,1,1,3,1,0,0,0,1,1,0,1,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,1,2,2,0,3,4,0,0,0,1,1,0,0,1,0,0,0,0,0,1,1), +(0,1,0,0,0,1,0,0,0,0,4,0,4,1,4,0,3,0,4,0,3,0,4,0,3,0,3,0,4,1,5,1,4,0,0,3,0,5,0,5,2,0,1,0,0,0,2,1,4,0,1,3,0,0,3,0,0,3,1,1,4,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0), +(1,4,0,5,0,3,0,2,0,3,5,4,4,3,4,3,5,3,4,3,3,0,4,3,3,3,3,3,3,2,4,4,3,1,3,4,4,5,4,4,3,4,4,1,3,5,4,3,3,3,1,2,2,3,3,1,3,1,3,3,3,5,3,3,4,5,0,3,0,3,0,3,4,3,4,4,3,0,3,0,2,4,3), +(0,1,0,4,0,0,0,0,0,1,4,0,4,1,4,2,4,0,3,0,1,0,1,0,0,0,0,0,2,0,3,1,1,1,0,3,0,0,0,1,2,1,0,0,1,1,1,1,0,1,0,0,0,1,0,0,3,0,0,0,0,3,2,0,2,2,0,1,0,0,0,2,3,2,3,3,0,0,0,0,2,1,0), +(0,5,1,5,0,3,0,3,0,5,4,4,5,1,5,3,3,0,4,3,4,3,5,3,4,3,3,2,4,3,4,3,3,0,3,3,1,4,4,3,4,4,4,3,4,5,5,3,2,3,1,1,3,3,1,3,1,1,3,3,2,4,5,3,3,5,0,4,0,3,0,4,4,3,5,3,3,0,3,4,0,4,3), +(0,5,0,5,0,3,0,2,0,4,4,3,5,2,4,3,3,3,4,4,4,3,5,3,5,3,3,1,4,0,4,3,3,0,3,3,0,4,4,4,4,5,4,3,3,5,5,3,2,3,1,2,3,2,0,1,0,0,3,2,2,4,4,3,1,5,0,4,0,3,0,4,3,1,3,2,1,0,3,3,0,3,3), +(0,4,0,5,0,5,0,4,0,4,5,5,5,3,4,3,3,2,5,4,4,3,5,3,5,3,4,0,4,3,4,4,3,2,4,4,3,4,5,4,4,5,5,0,3,5,5,4,1,3,3,2,3,3,1,3,1,0,4,3,1,4,4,3,4,5,0,4,0,2,0,4,3,4,4,3,3,0,4,0,0,5,5), +(0,4,0,4,0,5,0,1,1,3,3,4,4,3,4,1,3,0,5,1,3,0,3,1,3,1,1,0,3,0,3,3,4,0,4,3,0,4,4,4,3,4,4,0,3,5,4,1,0,3,0,0,2,3,0,3,1,0,3,1,0,3,2,1,3,5,0,3,0,1,0,3,2,3,3,4,4,0,2,2,0,4,4), +(2,4,0,5,0,4,0,3,0,4,5,5,4,3,5,3,5,3,5,3,5,2,5,3,4,3,3,4,3,4,5,3,2,1,5,4,3,2,3,4,5,3,4,1,2,5,4,3,0,3,3,0,3,2,0,2,3,0,4,1,0,3,4,3,3,5,0,3,0,1,0,4,5,5,5,4,3,0,4,2,0,3,5), +(0,5,0,4,0,4,0,2,0,5,4,3,4,3,4,3,3,3,4,3,4,2,5,3,5,3,4,1,4,3,4,4,4,0,3,5,0,4,4,4,4,5,3,1,3,4,5,3,3,3,3,3,3,3,0,2,2,0,3,3,2,4,3,3,3,5,3,4,1,3,3,5,3,2,0,0,0,0,4,3,1,3,3), +(0,1,0,3,0,3,0,1,0,1,3,3,3,2,3,3,3,0,3,0,0,0,3,1,3,0,0,0,2,2,2,3,0,0,3,2,0,1,2,4,1,3,3,0,0,3,3,3,0,1,0,0,2,1,0,0,3,0,3,1,0,3,0,0,1,3,0,2,0,1,0,3,3,1,3,3,0,0,1,1,0,3,3), +(0,2,0,3,0,2,1,4,0,2,2,3,1,1,3,1,1,0,2,0,3,1,2,3,1,3,0,0,1,0,4,3,2,3,3,3,1,4,2,3,3,3,3,1,0,3,1,4,0,1,1,0,1,2,0,1,1,0,1,1,0,3,1,3,2,2,0,1,0,0,0,2,3,3,3,1,0,0,0,0,0,2,3), +(0,5,0,4,0,5,0,2,0,4,5,5,3,3,4,3,3,1,5,4,4,2,4,4,4,3,4,2,4,3,5,5,4,3,3,4,3,3,5,5,4,5,5,1,3,4,5,3,1,4,3,1,3,3,0,3,3,1,4,3,1,4,5,3,3,5,0,4,0,3,0,5,3,3,1,4,3,0,4,0,1,5,3), +(0,5,0,5,0,4,0,2,0,4,4,3,4,3,3,3,3,3,5,4,4,4,4,4,4,5,3,3,5,2,4,4,4,3,4,4,3,3,4,4,5,5,3,3,4,3,4,3,3,4,3,3,3,3,1,2,2,1,4,3,3,5,4,4,3,4,0,4,0,3,0,4,4,4,4,4,1,0,4,2,0,2,4), +(0,4,0,4,0,3,0,1,0,3,5,2,3,0,3,0,2,1,4,2,3,3,4,1,4,3,3,2,4,1,3,3,3,0,3,3,0,0,3,3,3,5,3,3,3,3,3,2,0,2,0,0,2,0,0,2,0,0,1,0,0,3,1,2,2,3,0,3,0,2,0,4,4,3,3,4,1,0,3,0,0,2,4), +(0,0,0,4,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,1,0,2,0,1,0,0,0,0,0,3,1,3,0,3,2,0,0,0,1,0,3,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,4,0,2,0,0,0,0,0,0,2), +(0,2,1,3,0,2,0,2,0,3,3,3,3,1,3,1,3,3,3,3,3,3,4,2,2,1,2,1,4,0,4,3,1,3,3,3,2,4,3,5,4,3,3,3,3,3,3,3,0,1,3,0,2,0,0,1,0,0,1,0,0,4,2,0,2,3,0,3,3,0,3,3,4,2,3,1,4,0,1,2,0,2,3), +(0,3,0,3,0,1,0,3,0,2,3,3,3,0,3,1,2,0,3,3,2,3,3,2,3,2,3,1,3,0,4,3,2,0,3,3,1,4,3,3,2,3,4,3,1,3,3,1,1,0,1,1,0,1,0,1,0,1,0,0,0,4,1,1,0,3,0,3,1,0,2,3,3,3,3,3,1,0,0,2,0,3,3), +(0,0,0,0,0,0,0,0,0,0,3,0,2,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,3,0,3,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,2,0,2,3,0,0,0,0,0,0,0,0,3), +(0,2,0,3,1,3,0,3,0,2,3,3,3,1,3,1,3,1,3,1,3,3,3,1,3,0,2,3,1,1,4,3,3,2,3,3,1,2,2,4,1,3,3,0,1,4,2,3,0,1,3,0,3,0,0,1,3,0,2,0,0,3,3,2,1,3,0,3,0,2,0,3,4,4,4,3,1,0,3,0,0,3,3), +(0,2,0,1,0,2,0,0,0,1,3,2,2,1,3,0,1,1,3,0,3,2,3,1,2,0,2,0,1,1,3,3,3,0,3,3,1,1,2,3,2,3,3,1,2,3,2,0,0,1,0,0,0,0,0,0,3,0,1,0,0,2,1,2,1,3,0,3,0,0,0,3,4,4,4,3,2,0,2,0,0,2,4), +(0,0,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,3,1,0,0,0,0,0,0,0,3), +(0,3,0,3,0,2,0,3,0,3,3,3,2,3,2,2,2,0,3,1,3,3,3,2,3,3,0,0,3,0,3,2,2,0,2,3,1,4,3,4,3,3,2,3,1,5,4,4,0,3,1,2,1,3,0,3,1,1,2,0,2,3,1,3,1,3,0,3,0,1,0,3,3,4,4,2,1,0,2,1,0,2,4), +(0,1,0,3,0,1,0,2,0,1,4,2,5,1,4,0,2,0,2,1,3,1,4,0,2,1,0,0,2,1,4,1,1,0,3,3,0,5,1,3,2,3,3,1,0,3,2,3,0,1,0,0,0,0,0,0,1,0,0,0,0,4,0,1,0,3,0,2,0,1,0,3,3,3,4,3,3,0,0,0,0,2,3), +(0,0,0,1,0,0,0,0,0,0,2,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,0,0,1,0,0,0,0,0,3), +(0,1,0,3,0,4,0,3,0,2,4,3,1,0,3,2,2,1,3,1,2,2,3,1,1,1,2,1,3,0,1,2,0,1,3,2,1,3,0,5,5,1,0,0,1,3,2,1,0,3,0,0,1,0,0,0,0,0,3,4,0,1,1,1,3,2,0,2,0,1,0,2,3,3,1,2,3,0,1,0,1,0,4), +(0,0,0,1,0,3,0,3,0,2,2,1,0,0,4,0,3,0,3,1,3,0,3,0,3,0,1,0,3,0,3,1,3,0,3,3,0,0,1,2,1,1,1,0,1,2,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,2,2,1,2,0,0,2,0,0,0,0,2,3,3,3,3,0,0,0,0,1,4), +(0,0,0,3,0,3,0,0,0,0,3,1,1,0,3,0,1,0,2,0,1,0,0,0,0,0,0,0,1,0,3,0,2,0,2,3,0,0,2,2,3,1,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,2,3), +(2,4,0,5,0,5,0,4,0,3,4,3,3,3,4,3,3,3,4,3,4,4,5,4,5,5,5,2,3,0,5,5,4,1,5,4,3,1,5,4,3,4,4,3,3,4,3,3,0,3,2,0,2,3,0,3,0,0,3,3,0,5,3,2,3,3,0,3,0,3,0,3,4,5,4,5,3,0,4,3,0,3,4), +(0,3,0,3,0,3,0,3,0,3,3,4,3,2,3,2,3,0,4,3,3,3,3,3,3,3,3,0,3,2,4,3,3,1,3,4,3,4,4,4,3,4,4,3,2,4,4,1,0,2,0,0,1,1,0,2,0,0,3,1,0,5,3,2,1,3,0,3,0,1,2,4,3,2,4,3,3,0,3,2,0,4,4), +(0,3,0,3,0,1,0,0,0,1,4,3,3,2,3,1,3,1,4,2,3,2,4,2,3,4,3,0,2,2,3,3,3,0,3,3,3,0,3,4,1,3,3,0,3,4,3,3,0,1,1,0,1,0,0,0,4,0,3,0,0,3,1,2,1,3,0,4,0,1,0,4,3,3,4,3,3,0,2,0,0,3,3), +(0,3,0,4,0,1,0,3,0,3,4,3,3,0,3,3,3,1,3,1,3,3,4,3,3,3,0,0,3,1,5,3,3,1,3,3,2,5,4,3,3,4,5,3,2,5,3,4,0,1,0,0,0,0,0,2,0,0,1,1,0,4,2,2,1,3,0,3,0,2,0,4,4,3,5,3,2,0,1,1,0,3,4), +(0,5,0,4,0,5,0,2,0,4,4,3,3,2,3,3,3,1,4,3,4,1,5,3,4,3,4,0,4,2,4,3,4,1,5,4,0,4,4,4,4,5,4,1,3,5,4,2,1,4,1,1,3,2,0,3,1,0,3,2,1,4,3,3,3,4,0,4,0,3,0,4,4,4,3,3,3,0,4,2,0,3,4), +(1,4,0,4,0,3,0,1,0,3,3,3,1,1,3,3,2,2,3,3,1,0,3,2,2,1,2,0,3,1,2,1,2,0,3,2,0,2,2,3,3,4,3,0,3,3,1,2,0,1,1,3,1,2,0,0,3,0,1,1,0,3,2,2,3,3,0,3,0,0,0,2,3,3,4,3,3,0,1,0,0,1,4), +(0,4,0,4,0,4,0,0,0,3,4,4,3,1,4,2,3,2,3,3,3,1,4,3,4,0,3,0,4,2,3,3,2,2,5,4,2,1,3,4,3,4,3,1,3,3,4,2,0,2,1,0,3,3,0,0,2,0,3,1,0,4,4,3,4,3,0,4,0,1,0,2,4,4,4,4,4,0,3,2,0,3,3), +(0,0,0,1,0,4,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,3,2,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2), +(0,2,0,3,0,4,0,4,0,1,3,3,3,0,4,0,2,1,2,1,1,1,2,0,3,1,1,0,1,0,3,1,0,0,3,3,2,0,1,1,0,0,0,0,0,1,0,2,0,2,2,0,3,1,0,0,1,0,1,1,0,1,2,0,3,0,0,0,0,1,0,0,3,3,4,3,1,0,1,0,3,0,2), +(0,0,0,3,0,5,0,0,0,0,1,0,2,0,3,1,0,1,3,0,0,0,2,0,0,0,1,0,0,0,1,1,0,0,4,0,0,0,2,3,0,1,4,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,1,0,0,0,0,0,0,0,2,0,0,3,0,0,0,0,0,3), +(0,2,0,5,0,5,0,1,0,2,4,3,3,2,5,1,3,2,3,3,3,0,4,1,2,0,3,0,4,0,2,2,1,1,5,3,0,0,1,4,2,3,2,0,3,3,3,2,0,2,4,1,1,2,0,1,1,0,3,1,0,1,3,1,2,3,0,2,0,0,0,1,3,5,4,4,4,0,3,0,0,1,3), +(0,4,0,5,0,4,0,4,0,4,5,4,3,3,4,3,3,3,4,3,4,4,5,3,4,5,4,2,4,2,3,4,3,1,4,4,1,3,5,4,4,5,5,4,4,5,5,5,2,3,3,1,4,3,1,3,3,0,3,3,1,4,3,4,4,4,0,3,0,4,0,3,3,4,4,5,0,0,4,3,0,4,5), +(0,4,0,4,0,3,0,3,0,3,4,4,4,3,3,2,4,3,4,3,4,3,5,3,4,3,2,1,4,2,4,4,3,1,3,4,2,4,5,5,3,4,5,4,1,5,4,3,0,3,2,2,3,2,1,3,1,0,3,3,3,5,3,3,3,5,4,4,2,3,3,4,3,3,3,2,1,0,3,2,1,4,3), +(0,4,0,5,0,4,0,3,0,3,5,5,3,2,4,3,4,0,5,4,4,1,4,4,4,3,3,3,4,3,5,5,2,3,3,4,1,2,5,5,3,5,5,2,3,5,5,4,0,3,2,0,3,3,1,1,5,1,4,1,0,4,3,2,3,5,0,4,0,3,0,5,4,3,4,3,0,0,4,1,0,4,4), +(1,3,0,4,0,2,0,2,0,2,5,5,3,3,3,3,3,0,4,2,3,4,4,4,3,4,0,0,3,4,5,4,3,3,3,3,2,5,5,4,5,5,5,4,3,5,5,5,1,3,1,0,1,0,0,3,2,0,4,2,0,5,2,3,2,4,1,3,0,3,0,4,5,4,5,4,3,0,4,2,0,5,4), +(0,3,0,4,0,5,0,3,0,3,4,4,3,2,3,2,3,3,3,3,3,2,4,3,3,2,2,0,3,3,3,3,3,1,3,3,3,0,4,4,3,4,4,1,1,4,4,2,0,3,1,0,1,1,0,4,1,0,2,3,1,3,3,1,3,4,0,3,0,1,0,3,1,3,0,0,1,0,2,0,0,4,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,3,0,2,0,3,0,1,5,4,3,3,3,1,4,2,1,2,3,4,4,2,4,4,5,0,3,1,4,3,4,0,4,3,3,3,2,3,2,5,3,4,3,2,2,3,0,0,3,0,2,1,0,1,2,0,0,0,0,2,1,1,3,1,0,2,0,4,0,3,4,4,4,5,2,0,2,0,0,1,3), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,1,1,0,0,0,4,2,1,1,0,1,0,3,2,0,0,3,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,1,0,0,0,2,0,0,0,1,4,0,4,2,1,0,0,0,0,0,1), +(0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0,3,1,0,0,0,2,0,2,1,0,0,1,2,1,0,1,1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,1,3,1,0,0,0,0,0,1,0,0,2,1,0,0,0,0,0,0,0,0,2), +(0,4,0,4,0,4,0,3,0,4,4,3,4,2,4,3,2,0,4,4,4,3,5,3,5,3,3,2,4,2,4,3,4,3,1,4,0,2,3,4,4,4,3,3,3,4,4,4,3,4,1,3,4,3,2,1,2,1,3,3,3,4,4,3,3,5,0,4,0,3,0,4,3,3,3,2,1,0,3,0,0,3,3), +(0,4,0,3,0,3,0,3,0,3,5,5,3,3,3,3,4,3,4,3,3,3,4,4,4,3,3,3,3,4,3,5,3,3,1,3,2,4,5,5,5,5,4,3,4,5,5,3,2,2,3,3,3,3,2,3,3,1,2,3,2,4,3,3,3,4,0,4,0,2,0,4,3,2,2,1,2,0,3,0,0,4,1), +) + +class JapaneseContextAnalysis: + def __init__(self): + self.reset() + + def reset(self): + self._mTotalRel = 0 # total sequence received + self._mRelSample = [0] * NUM_OF_CATEGORY # category counters, each interger counts sequence in its category + self._mNeedToSkipCharNum = 0 # if last byte in current buffer is not the last byte of a character, we need to know how many bytes to skip in next buffer + self._mLastCharOrder = -1 # The order of previous char + self._mDone = constants.False # If this flag is set to constants.True, detection is done and conclusion has been made + + def feed(self, aBuf, aLen): + if self._mDone: return + + # The buffer we got is byte oriented, and a character may span in more than one + # buffers. In case the last one or two byte in last buffer is not complete, we + # record how many byte needed to complete that character and skip these bytes here. + # We can choose to record those bytes as well and analyse the character once it + # is complete, but since a character will not make much difference, by simply skipping + # this character will simply our logic and improve performance. + i = self._mNeedToSkipCharNum + while i < aLen: + order, charLen = self.get_order(aBuf[i:i+2]) + i += charLen + if i > aLen: + self._mNeedToSkipCharNum = i - aLen + self._mLastCharOrder = -1 + else: + if (order != -1) and (self._mLastCharOrder != -1): + self._mTotalRel += 1 + if self._mTotalRel > MAX_REL_THRESHOLD: + self._mDone = constants.True + break + self._mRelSample[jp2CharContext[self._mLastCharOrder][order]] += 1 + self._mLastCharOrder = order + + def got_enough_data(self): + return self._mTotalRel > ENOUGH_REL_THRESHOLD + + def get_confidence(self): + # This is just one way to calculate confidence. It works well for me. + if self._mTotalRel > MINIMUM_DATA_THRESHOLD: + return (self._mTotalRel - self._mRelSample[0]) / self._mTotalRel + else: + return DONT_KNOW + + def get_order(self, aStr): + return -1, 1 + +class SJISContextAnalysis(JapaneseContextAnalysis): + def get_order(self, aStr): + if not aStr: return -1, 1 + # find out current char's byte length + if ((aStr[0] >= '\x81') and (aStr[0] <= '\x9F')) or \ + ((aStr[0] >= '\xE0') and (aStr[0] <= '\xFC')): + charLen = 2 + else: + charLen = 1 + + # return its order if it is hiragana + if len(aStr) > 1: + if (aStr[0] == '\202') and \ + (aStr[1] >= '\x9F') and \ + (aStr[1] <= '\xF1'): + return ord(aStr[1]) - 0x9F, charLen + + return -1, charLen + +class EUCJPContextAnalysis(JapaneseContextAnalysis): + def get_order(self, aStr): + if not aStr: return -1, 1 + # find out current char's byte length + if (aStr[0] == '\x8E') or \ + ((aStr[0] >= '\xA1') and (aStr[0] <= '\xFE')): + charLen = 2 + elif aStr[0] == '\x8F': + charLen = 3 + else: + charLen = 1 + + # return its order if it is hiragana + if len(aStr) > 1: + if (aStr[0] == '\xA4') and \ + (aStr[1] >= '\xA1') and \ + (aStr[1] <= '\xF3'): + return ord(aStr[1]) - 0xA1, charLen + + return -1, charLen diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langbulgarianmodel.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langbulgarianmodel.py new file mode 100755 index 0000000..bf5641e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langbulgarianmodel.py @@ -0,0 +1,228 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +# this table is modified base on win1251BulgarianCharToOrderMap, so +# only number <64 is sure valid + +Latin5_BulgarianCharToOrderMap = ( \ +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 +110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 +253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 +116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 +194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209, # 80 +210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225, # 90 + 81,226,227,228,229,230,105,231,232,233,234,235,236, 45,237,238, # a0 + 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # b0 + 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,239, 67,240, 60, 56, # c0 + 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # d0 + 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,241, 42, 16, # e0 + 62,242,243,244, 58,245, 98,246,247,248,249,250,251, 91,252,253, # f0 +) + +win1251BulgarianCharToOrderMap = ( \ +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 +110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 +253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 +116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 +206,207,208,209,210,211,212,213,120,214,215,216,217,218,219,220, # 80 +221, 78, 64, 83,121, 98,117,105,222,223,224,225,226,227,228,229, # 90 + 88,230,231,232,233,122, 89,106,234,235,236,237,238, 45,239,240, # a0 + 73, 80,118,114,241,242,243,244,245, 62, 58,246,247,248,249,250, # b0 + 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # c0 + 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,251, 67,252, 60, 56, # d0 + 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # e0 + 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,253, 42, 16, # f0 +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 96.9392% +# first 1024 sequences:3.0618% +# rest sequences: 0.2992% +# negative sequences: 0.0020% +BulgarianLangModel = ( \ +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,2,2,1,2,2, +3,1,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,0,1, +0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,3,3,0,3,1,0, +0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,2,2,1,3,3,3,3,2,2,2,1,1,2,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,2,3,2,2,3,3,1,1,2,3,3,2,3,3,3,3,2,1,2,0,2,0,3,0,0, +0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,1,3,3,3,3,3,2,3,2,3,3,3,3,3,2,3,3,1,3,0,3,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,1,3,3,2,3,3,3,1,3,3,2,3,2,2,2,0,0,2,0,2,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,3,3,1,2,2,3,2,1,1,2,0,2,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,2,3,3,1,2,3,2,2,2,3,3,3,3,3,2,2,3,1,2,0,2,1,2,0,0, +0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,1,3,3,3,3,3,2,3,3,3,2,3,3,2,3,2,2,2,3,1,2,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,1,1,1,2,2,1,3,1,3,2,2,3,0,0,1,0,1,0,1,0,0, +0,0,0,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,2,2,3,2,2,3,1,2,1,1,1,2,3,1,3,1,2,2,0,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,1,3,2,2,3,3,1,2,3,1,1,3,3,3,3,1,2,2,1,1,1,0,2,0,2,0,1, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,2,2,3,3,3,2,2,1,1,2,0,2,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,0,1,2,1,3,3,2,3,3,3,3,3,2,3,2,1,0,3,1,2,1,2,1,2,3,2,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,2,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,1,3,3,2,3,3,2,2,2,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,0,3,3,3,3,3,2,1,1,2,1,3,3,0,3,1,1,1,1,3,2,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,1,1,3,1,3,3,2,3,2,2,2,3,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,3,2,2,3,2,1,1,1,1,1,3,1,3,1,1,0,0,0,1,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,2,0,3,2,0,3,0,2,0,0,2,1,3,1,0,0,1,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,2,1,1,1,1,2,1,1,2,1,1,1,2,2,1,2,1,1,1,0,1,1,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,2,1,3,1,1,2,1,3,2,1,1,0,1,2,3,2,1,1,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,2,2,1,0,1,0,0,1,0,0,0,2,1,0,3,0,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,2,3,2,3,3,1,3,2,1,1,1,2,1,1,2,1,3,0,1,0,0,0,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,2,2,3,3,2,3,2,2,2,3,1,2,2,1,1,2,1,1,2,2,0,1,1,0,1,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,3,1,0,2,2,1,3,2,1,0,0,2,0,2,0,1,0,0,0,0,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,1,2,0,2,3,1,2,3,2,0,1,3,1,2,1,1,1,0,0,1,0,0,2,2,2,3, +2,2,2,2,1,2,1,1,2,2,1,1,2,0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,1, +3,3,3,3,3,2,1,2,2,1,2,0,2,0,1,0,1,2,1,2,1,1,0,0,0,1,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,2,3,3,1,1,3,1,0,3,2,1,0,0,0,1,2,0,2,0,1,0,0,0,1,0,1,2,1,2,2, +1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,0,1,2,1,1,1,0,0,0,0,0,1,1,0,0, +3,1,0,1,0,2,3,2,2,2,3,2,2,2,2,2,1,0,2,1,2,1,1,1,0,1,2,1,2,2,2,1, +1,1,2,2,2,2,1,2,1,1,0,1,2,1,2,2,2,1,1,1,0,1,1,1,1,2,0,1,0,0,0,0, +2,3,2,3,3,0,0,2,1,0,2,1,0,0,0,0,2,3,0,2,0,0,0,0,0,1,0,0,2,0,1,2, +2,1,2,1,2,2,1,1,1,2,1,1,1,0,1,2,2,1,1,1,1,1,0,1,1,1,0,0,1,2,0,0, +3,3,2,2,3,0,2,3,1,1,2,0,0,0,1,0,0,2,0,2,0,0,0,1,0,1,0,1,2,0,2,2, +1,1,1,1,2,1,0,1,2,2,2,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,1,0,0, +2,3,2,3,3,0,0,3,0,1,1,0,1,0,0,0,2,2,1,2,0,0,0,0,0,0,0,0,2,0,1,2, +2,2,1,1,1,1,1,2,2,2,1,0,2,0,1,0,1,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0, +3,3,3,3,2,2,2,2,2,0,2,1,1,1,1,2,1,2,1,1,0,2,0,1,0,1,0,0,2,0,1,2, +1,1,1,1,1,1,1,2,2,1,1,0,2,0,1,0,2,0,0,1,1,1,0,0,2,0,0,0,1,1,0,0, +2,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0,0,0,0,1,2,0,1,2, +2,2,2,1,1,2,1,1,2,2,2,1,2,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,1,1,0,0, +2,3,3,3,3,0,2,2,0,2,1,0,0,0,1,1,1,2,0,2,0,0,0,3,0,0,0,0,2,0,2,2, +1,1,1,2,1,2,1,1,2,2,2,1,2,0,1,1,1,0,1,1,1,1,0,2,1,0,0,0,1,1,0,0, +2,3,3,3,3,0,2,1,0,0,2,0,0,0,0,0,1,2,0,2,0,0,0,0,0,0,0,0,2,0,1,2, +1,1,1,2,1,1,1,1,2,2,2,0,1,0,1,1,1,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0, +3,3,2,2,3,0,1,0,1,0,0,0,0,0,0,0,1,1,0,3,0,0,0,0,0,0,0,0,1,0,2,2, +1,1,1,1,1,2,1,1,2,2,1,2,2,1,0,1,1,1,1,1,0,1,0,0,1,0,0,0,1,1,0,0, +3,1,0,1,0,2,2,2,2,3,2,1,1,1,2,3,0,0,1,0,2,1,1,0,1,1,1,1,2,1,1,1, +1,2,2,1,2,1,2,2,1,1,0,1,2,1,2,2,1,1,1,0,0,1,1,1,2,1,0,1,0,0,0,0, +2,1,0,1,0,3,1,2,2,2,2,1,2,2,1,1,1,0,2,1,2,2,1,1,2,1,1,0,2,1,1,1, +1,2,2,2,2,2,2,2,1,2,0,1,1,0,2,1,1,1,1,1,0,0,1,1,1,1,0,1,0,0,0,0, +2,1,1,1,1,2,2,2,2,1,2,2,2,1,2,2,1,1,2,1,2,3,2,2,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,3,2,0,1,2,0,1,2,1,1,0,1,0,1,2,1,2,0,0,0,1,1,0,0,0,1,0,0,2, +1,1,0,0,1,1,0,1,1,1,1,0,2,0,1,1,1,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0, +2,0,0,0,0,1,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,2,1,1,1, +1,2,2,2,2,1,1,2,1,2,1,1,1,0,2,1,2,1,1,1,0,2,1,1,1,1,0,1,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0, +1,1,0,1,0,1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,3,2,0,0,0,0,1,0,0,0,0,0,0,1,1,0,2,0,0,0,0,0,0,0,0,1,0,1,2, +1,1,1,1,1,1,0,0,2,2,2,2,2,0,1,1,0,1,1,1,1,1,0,0,1,0,0,0,1,1,0,1, +2,3,1,2,1,0,1,1,0,2,2,2,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,1,2, +1,1,1,1,2,1,1,1,1,1,1,1,1,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0, +2,2,2,2,2,0,0,2,0,0,2,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,0,2,2, +1,1,1,1,1,0,0,1,2,1,1,0,1,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,2,0,1,1,0,0,0,1,0,0,2,0,2,0,0,0,0,0,0,0,0,0,0,1,1, +0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,3,2,0,0,1,0,0,1,0,0,0,0,0,0,1,0,2,0,0,0,1,0,0,0,0,0,0,0,2, +1,1,0,0,1,0,0,0,1,1,0,0,1,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,1,2,2,2,1,2,1,2,2,1,1,2,1,1,1,0,1,1,1,1,2,0,1,0,1,1,1,1,0,1,1, +1,1,2,1,1,1,1,1,1,0,0,1,2,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0, +1,0,0,1,3,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,1,0,0,1,0,2,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,2,0,0,1, +0,2,0,1,0,0,1,1,2,0,1,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,1,1,0,2,1,0,1,1,1,0,0,1,0,2,0,1,0,0,0,0,0,0,0,0,0,1, +0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,2,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, +0,1,0,1,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,0,1,2,1,1,1,1,1,1,2,2,1,0,0,1,0,1,0,0,0,0,1,1,1,1,0,0,0, +1,1,2,1,1,1,1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,1,2,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +0,1,1,0,1,1,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, +1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,2,0,0,2,0,1,0,0,1,0,0,1, +1,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0, +1,1,1,1,1,1,1,2,0,0,0,0,0,0,2,1,0,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +) + +Latin5BulgarianModel = { \ + 'charToOrderMap': Latin5_BulgarianCharToOrderMap, + 'precedenceMatrix': BulgarianLangModel, + 'mTypicalPositiveRatio': 0.969392, + 'keepEnglishLetter': constants.False, + 'charsetName': "ISO-8859-5" +} + +Win1251BulgarianModel = { \ + 'charToOrderMap': win1251BulgarianCharToOrderMap, + 'precedenceMatrix': BulgarianLangModel, + 'mTypicalPositiveRatio': 0.969392, + 'keepEnglishLetter': constants.False, + 'charsetName': "windows-1251" +} diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langcyrillicmodel.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langcyrillicmodel.py new file mode 100755 index 0000000..e604cc7 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langcyrillicmodel.py @@ -0,0 +1,329 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants + +# KOI8-R language model +# Character Mapping Table: +KOI8R_CharToOrderMap = ( \ +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, # 80 +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, # 90 +223,224,225, 68,226,227,228,229,230,231,232,233,234,235,236,237, # a0 +238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253, # b0 + 27, 3, 21, 28, 13, 2, 39, 19, 26, 4, 23, 11, 8, 12, 5, 1, # c0 + 15, 16, 9, 7, 6, 14, 24, 10, 17, 18, 20, 25, 30, 29, 22, 54, # d0 + 59, 37, 44, 58, 41, 48, 53, 46, 55, 42, 60, 36, 49, 38, 31, 34, # e0 + 35, 43, 45, 32, 40, 52, 56, 33, 61, 62, 51, 57, 47, 63, 50, 70, # f0 +) + +win1251_CharToOrderMap = ( \ +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, +239,240,241,242,243,244,245,246, 68,247,248,249,250,251,252,253, + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +) + +latin5_CharToOrderMap = ( \ +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, +) + +macCyrillic_CharToOrderMap = ( \ +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, +239,240,241,242,243,244,245,246,247,248,249,250,251,252, 68, 16, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27,255, +) + +IBM855_CharToOrderMap = ( \ +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194, 68,195,196,197,198,199,200,201,202,203,204,205, +206,207,208,209,210,211,212,213,214,215,216,217, 27, 59, 54, 70, + 3, 37, 21, 44, 28, 58, 13, 41, 2, 48, 39, 53, 19, 46,218,219, +220,221,222,223,224, 26, 55, 4, 42,225,226,227,228, 23, 60,229, +230,231,232,233,234,235, 11, 36,236,237,238,239,240,241,242,243, + 8, 49, 12, 38, 5, 31, 1, 34, 15,244,245,246,247, 35, 16,248, + 43, 9, 45, 7, 32, 6, 40, 14, 52, 24, 56, 10, 33, 17, 61,249, +250, 18, 62, 20, 51, 25, 57, 30, 47, 29, 63, 22, 50,251,252,255, +) + +IBM866_CharToOrderMap = ( \ +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 97.6601% +# first 1024 sequences: 2.3389% +# rest sequences: 0.1237% +# negative sequences: 0.0009% +RussianLangModel = ( \ +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,3,3,3,3,1,3,3,3,2,3,2,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,2,2,2,2,2,0,0,2, +3,3,3,2,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,2,3,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,2,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,2,3,3,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, +0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, +0,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,2,2,2,3,1,3,3,1,3,3,3,3,2,2,3,0,2,2,2,3,3,2,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,3,3,2,2,3,2,3,3,3,2,1,2,2,0,1,2,2,2,2,2,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,3,0,2,2,3,3,2,1,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,1,2,3,2,2,3,2,3,3,3,3,2,2,3,0,3,2,2,3,1,1,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,3,3,3,3,2,2,2,0,3,3,3,2,2,2,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,2,3,2,2,0,1,3,2,1,2,2,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,2,1,1,3,0,1,1,1,1,2,1,1,0,2,2,2,1,2,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,2,2,2,2,1,3,2,3,2,3,2,1,2,2,0,1,1,2,1,2,1,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,2,3,3,3,2,2,2,2,0,2,2,2,2,3,1,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,2,3,2,2,3,3,3,3,3,3,3,3,3,1,3,2,0,0,3,3,3,3,2,3,3,3,3,2,3,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,3,2,2,3,3,0,2,1,0,3,2,3,2,3,0,0,1,2,0,0,1,0,1,2,1,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,3,0,2,3,3,3,3,2,3,3,3,3,1,2,2,0,0,2,3,2,2,2,3,2,3,2,2,3,0,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,0,2,3,2,3,0,1,2,3,3,2,0,2,3,0,0,2,3,2,2,0,1,3,1,3,2,2,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,3,0,2,3,3,3,3,3,3,3,3,2,1,3,2,0,0,2,2,3,3,3,2,3,3,0,2,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,2,3,3,2,2,2,3,3,0,0,1,1,1,1,1,2,0,0,1,1,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,2,3,3,3,3,3,3,3,0,3,2,3,3,2,3,2,0,2,1,0,1,1,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,2,2,2,2,3,1,3,2,3,1,1,2,1,0,2,2,2,2,1,3,1,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +2,2,3,3,3,3,3,1,2,2,1,3,1,0,3,0,0,3,0,0,0,1,1,0,1,2,1,0,0,0,0,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,2,1,1,3,3,3,2,2,1,2,2,3,1,1,2,0,0,2,2,1,3,0,0,2,1,1,2,1,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,3,3,3,1,2,2,2,1,2,1,3,3,1,1,2,1,2,1,2,2,0,2,0,0,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,3,2,1,3,2,2,3,2,0,3,2,0,3,0,1,0,1,1,0,0,1,1,1,1,0,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,3,3,3,2,2,2,3,3,1,2,1,2,1,0,1,0,1,1,0,1,0,0,2,1,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,1,1,2,1,2,3,3,2,2,1,2,2,3,0,2,1,0,0,2,2,3,2,1,2,2,2,2,2,3,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,1,1,0,1,1,2,2,1,1,3,0,0,1,3,1,1,1,0,0,0,1,0,1,1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,3,3,3,2,0,0,0,2,1,0,1,0,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,0,2,3,2,2,2,1,2,2,2,1,2,1,0,0,1,1,1,0,2,0,1,1,1,0,0,1,1, +1,0,0,0,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,0,0,0,0,1,0,0,0,0,3,0,1,2,1,0,0,0,0,0,0,0,1,1,0,0,1,1, +1,0,1,0,1,2,0,0,1,1,2,1,0,1,1,1,1,0,1,1,1,1,0,1,0,0,1,0,0,1,1,0, +2,2,3,2,2,2,3,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,0,1,0,1,1,1,0,2,1, +1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,0,1,1,0, +3,3,3,2,2,2,2,3,2,2,1,1,2,2,2,2,1,1,3,1,2,1,2,0,0,1,1,0,1,0,2,1, +1,1,1,1,1,2,1,0,1,1,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,1,0, +2,0,0,1,0,3,2,2,2,2,1,2,1,2,1,2,0,0,0,2,1,2,2,1,1,2,2,0,1,1,0,2, +1,1,1,1,1,0,1,1,1,2,1,1,1,2,1,0,1,2,1,1,1,1,0,1,1,1,0,0,1,0,0,1, +1,3,2,2,2,1,1,1,2,3,0,0,0,0,2,0,2,2,1,0,0,0,0,0,0,1,0,0,0,0,1,1, +1,0,1,1,0,1,0,1,1,0,1,1,0,2,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, +2,3,2,3,2,1,2,2,2,2,1,0,0,0,2,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,2,1, +1,1,2,1,0,2,0,0,1,0,1,0,0,1,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,0, +3,0,0,1,0,2,2,2,3,2,2,2,2,2,2,2,0,0,0,2,1,2,1,1,1,2,2,0,0,0,1,2, +1,1,1,1,1,0,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,1, +2,3,2,3,3,2,0,1,1,1,0,0,1,0,2,0,1,1,3,1,0,0,0,0,0,0,0,1,0,0,2,1, +1,1,1,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,0,0,1,1,0,1,0,0,0,0,0,0,1,0, +2,3,3,3,3,1,2,2,2,2,0,1,1,0,2,1,1,1,2,1,0,1,1,0,0,1,0,1,0,0,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,2,0,0,1,1,2,2,1,0,0,2,0,1,1,3,0,0,1,0,0,0,0,0,1,0,1,2,1, +1,1,2,0,1,1,1,0,1,0,1,1,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,1,0,1,1,0, +1,3,2,3,2,1,0,0,2,2,2,0,1,0,2,0,1,1,1,0,1,0,0,0,3,0,1,1,0,0,2,1, +1,1,1,0,1,1,0,0,0,0,1,1,0,1,0,0,2,1,1,0,1,0,0,0,1,0,1,0,0,1,1,0, +3,1,2,1,1,2,2,2,2,2,2,1,2,2,1,1,0,0,0,2,2,2,0,0,0,1,2,1,0,1,0,1, +2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,1,1,1,0,1,0,1,1,0,1,1,1,0,0,1, +3,0,0,0,0,2,0,1,1,1,1,1,1,1,0,1,0,0,0,1,1,1,0,1,0,1,1,0,0,1,0,1, +1,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1, +1,3,3,2,2,0,0,0,2,2,0,0,0,1,2,0,1,1,2,0,0,0,0,0,0,0,0,1,0,0,2,1, +0,1,1,0,0,1,1,0,0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +2,3,2,3,2,0,0,0,0,1,1,0,0,0,2,0,2,0,2,0,0,0,0,0,1,0,0,1,0,0,1,1, +1,1,2,0,1,2,1,0,1,1,2,1,1,1,1,1,2,1,1,0,1,0,0,1,1,1,1,1,0,1,1,0, +1,3,2,2,2,1,0,0,2,2,1,0,1,2,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1, +0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,0,2,3,1,2,2,2,2,2,2,1,1,0,0,0,1,0,1,0,2,1,1,1,0,0,0,0,1, +1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +2,0,2,0,0,1,0,3,2,1,2,1,2,2,0,1,0,0,0,2,1,0,0,2,1,1,1,1,0,2,0,2, +2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,0,0,0,1,1,1,1,0,1,0,0,1, +1,2,2,2,2,1,0,0,1,0,0,0,0,0,2,0,1,1,1,1,0,0,0,0,1,0,1,2,0,0,2,0, +1,0,1,1,1,2,1,0,1,0,1,1,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0, +2,1,2,2,2,0,3,0,1,1,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0, +1,2,2,3,2,2,0,0,1,1,2,0,1,2,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1, +0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, +2,2,1,1,2,1,2,2,2,2,2,1,2,2,0,1,0,0,0,1,2,2,2,1,2,1,1,1,1,1,2,1, +1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,0,1, +1,2,2,2,2,0,1,0,2,2,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +0,0,1,0,0,1,0,0,0,0,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,0,2,2,2,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1, +0,1,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,0,0,1,0,0,1,1,2,0,0,0,0,1,0,1,0,0,1,0,0,2,0,0,0,1, +0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,1,1,2,0,2,1,1,1,1,0,2,2,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1, +0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,0,2,1,2,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0, +0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +1,0,0,0,0,2,0,1,2,1,0,1,1,1,0,1,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,1, +0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1, +2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,1,1,0,1,0,1,0,0,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,1,0,1,1,0,1,0,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0, +0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, +) + +Koi8rModel = { \ + 'charToOrderMap': KOI8R_CharToOrderMap, + 'precedenceMatrix': RussianLangModel, + 'mTypicalPositiveRatio': 0.976601, + 'keepEnglishLetter': constants.False, + 'charsetName': "KOI8-R" +} + +Win1251CyrillicModel = { \ + 'charToOrderMap': win1251_CharToOrderMap, + 'precedenceMatrix': RussianLangModel, + 'mTypicalPositiveRatio': 0.976601, + 'keepEnglishLetter': constants.False, + 'charsetName': "windows-1251" +} + +Latin5CyrillicModel = { \ + 'charToOrderMap': latin5_CharToOrderMap, + 'precedenceMatrix': RussianLangModel, + 'mTypicalPositiveRatio': 0.976601, + 'keepEnglishLetter': constants.False, + 'charsetName': "ISO-8859-5" +} + +MacCyrillicModel = { \ + 'charToOrderMap': macCyrillic_CharToOrderMap, + 'precedenceMatrix': RussianLangModel, + 'mTypicalPositiveRatio': 0.976601, + 'keepEnglishLetter': constants.False, + 'charsetName': "MacCyrillic" +}; + +Ibm866Model = { \ + 'charToOrderMap': IBM866_CharToOrderMap, + 'precedenceMatrix': RussianLangModel, + 'mTypicalPositiveRatio': 0.976601, + 'keepEnglishLetter': constants.False, + 'charsetName': "IBM866" +} + +Ibm855Model = { \ + 'charToOrderMap': IBM855_CharToOrderMap, + 'precedenceMatrix': RussianLangModel, + 'mTypicalPositiveRatio': 0.976601, + 'keepEnglishLetter': constants.False, + 'charsetName': "IBM855" +} diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langgreekmodel.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langgreekmodel.py new file mode 100755 index 0000000..ec6d49e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langgreekmodel.py @@ -0,0 +1,225 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin7_CharToOrderMap = ( \ +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 + 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 +253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 + 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 +253,233, 90,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 +253,253,253,253,247,248, 61, 36, 46, 71, 73,253, 54,253,108,123, # b0 +110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 + 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 +124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 + 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 +) + +win1253_CharToOrderMap = ( \ +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 + 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 +253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 + 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 +253,233, 61,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 +253,253,253,253,247,253,253, 36, 46, 71, 73,253, 54,253,108,123, # b0 +110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 + 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 +124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 + 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 98.2851% +# first 1024 sequences:1.7001% +# rest sequences: 0.0359% +# negative sequences: 0.0148% +GreekLangModel = ( \ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,2,2,3,3,3,3,3,3,3,3,1,3,3,3,0,2,2,3,3,0,3,0,3,2,0,3,3,3,0, +3,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,0,3,3,0,3,2,3,3,0,3,2,3,3,3,0,0,3,0,3,0,3,3,2,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,2,3,2,2,3,3,3,3,3,3,3,3,0,3,3,3,3,0,2,3,3,0,3,3,3,3,2,3,3,3,0, +2,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,2,1,3,3,3,3,2,3,3,2,3,3,2,0, +0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,2,3,3,0, +2,0,1,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,3,0,0,0,0,3,3,0,3,1,3,3,3,0,3,3,0,3,3,3,3,0,0,0,0, +2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,0,3,0,3,3,3,3,3,0,3,2,2,2,3,0,2,3,3,3,3,3,2,3,3,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,3,2,2,2,3,3,3,3,0,3,1,3,3,3,3,2,3,3,3,3,3,3,3,2,2,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,3,0,0,0,3,3,2,3,3,3,3,3,0,0,3,2,3,0,2,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,3,0,0,3,3,0,2,3,0,3,0,3,3,3,0,0,3,0,3,0,2,2,3,3,0,0, +0,0,1,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,3,2,3,3,3,3,0,3,3,3,3,3,0,3,3,2,3,2,3,3,2,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,2,3,2,3,3,3,3,3,3,0,2,3,2,3,2,2,2,3,2,3,3,2,3,0,2,2,2,3,0, +2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,0,3,3,3,2,3,3,0,0,3,0,3,0,0,0,3,2,0,3,0,3,0,0,2,0,2,0, +0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,0,0,0,3,3,0,3,3,3,0,0,1,2,3,0, +3,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,0,3,2,2,3,3,0,3,3,3,3,3,2,1,3,0,3,2,3,3,2,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,3,0,2,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,3,0,3,2,3,0,0,3,3,3,0, +3,0,0,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,2,0,3,2,3,0,0,3,2,3,0, +2,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,1,2,2,3,3,3,3,3,3,0,2,3,0,3,0,0,0,3,3,0,3,0,2,0,0,2,3,1,0, +2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,3,0,3,0,3,3,2,3,0,3,3,3,3,3,3,0,3,3,3,0,2,3,0,0,3,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,0,0,3,0,0,0,3,3,0,3,0,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,0,3,3,3,3,3,3,0,0,3,0,2,0,0,0,3,3,0,3,0,3,0,0,2,0,2,0, +0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,3,0,3,0,2,0,3,2,0,3,2,3,2,3,0,0,3,2,3,2,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,2,3,3,3,3,3,0,0,0,3,0,2,1,0,0,3,2,2,2,0,3,0,0,2,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,2,0,3,0,3,0,3,3,0,2,1,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,3,0,3,3,3,3,3,3,0,2,3,0,3,0,0,0,2,1,0,2,2,3,0,0,2,2,2,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,2,3,3,3,2,3,0,0,1,3,0,2,0,0,0,0,3,0,1,0,2,0,0,1,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,1,0,3,0,0,0,3,2,0,3,2,3,3,3,0,0,3,0,3,2,2,2,1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,0,0,3,0,0,0,0,2,0,2,3,3,2,2,2,2,3,0,2,0,2,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,2,0,0,0,0,0,0,2,3,0,2,0,2,3,2,0,0,3,0,3,0,3,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,3,2,3,3,2,2,3,0,2,0,3,0,0,0,2,0,0,0,0,1,2,0,2,0,2,0, +0,2,0,2,0,2,2,0,0,1,0,2,2,2,0,2,2,2,0,2,2,2,0,0,2,0,0,1,0,0,0,0, +0,2,0,3,3,2,0,0,0,0,0,0,1,3,0,2,0,2,2,2,0,0,2,0,3,0,0,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,2,3,2,0,2,2,0,2,0,2,2,0,2,0,2,2,2,0,0,0,0,0,0,2,3,0,0,0,2, +0,1,2,0,0,0,0,2,2,0,0,0,2,1,0,2,2,0,0,0,0,0,0,1,0,2,0,0,0,0,0,0, +0,0,2,1,0,2,3,2,2,3,2,3,2,0,0,3,3,3,0,0,3,2,0,0,0,1,1,0,2,0,2,2, +0,2,0,2,0,2,2,0,0,2,0,2,2,2,0,2,2,2,2,0,0,2,0,0,0,2,0,1,0,0,0,0, +0,3,0,3,3,2,2,0,3,0,0,0,2,2,0,2,2,2,1,2,0,0,1,2,2,0,0,3,0,0,0,2, +0,1,2,0,0,0,1,2,0,0,0,0,0,0,0,2,2,0,1,0,0,2,0,0,0,2,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,2,2,0,0,0,2,0,2,3,3,0,2,0,0,0,0,0,0,2,2,2,0,2,2,0,2,0,2, +0,2,2,0,0,2,2,2,2,1,0,0,2,2,0,2,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0, +0,2,0,3,2,3,0,0,0,3,0,0,2,2,0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,0,2, +0,0,2,2,0,0,2,2,2,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,3,2,0,2,2,2,2,2,0,0,0,2,0,0,0,0,2,0,1,0,0,2,0,1,0,0,0, +0,2,2,2,0,2,2,0,1,2,0,2,2,2,0,2,2,2,2,1,2,2,0,0,2,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,2,0,2,0,2,2,0,0,0,0,1,2,1,0,0,2,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,3,2,3,0,0,2,0,0,0,2,2,0,2,0,0,0,1,0,0,2,0,2,0,2,2,0,0,0,0, +0,0,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0, +0,2,2,3,2,2,0,0,0,0,0,0,1,3,0,2,0,2,2,0,0,0,1,0,2,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,0,2,0,3,2,0,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,2,0,0,0,0,1,1,0,0,2,1,2,0,2,2,0,1,0,0,1,0,0,0,2,0,0,0,0,0,0, +0,3,0,2,2,2,0,0,2,0,0,0,2,0,0,0,2,3,0,2,0,0,0,0,0,0,2,2,0,0,0,2, +0,1,2,0,0,0,1,2,2,1,0,0,0,2,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,1,2,0,2,2,0,2,0,0,2,0,0,0,0,1,2,1,0,2,1,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,0,3,1,2,2,0,2,0,0,0,0,2,0,0,0,2,0,0,3,0,0,0,0,2,2,2,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,1,0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,2, +0,2,2,0,0,2,2,2,2,2,0,1,2,0,0,0,2,2,0,1,0,2,0,0,2,2,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,0,0,0,0,2,0,2,0,0,0,0,2, +0,1,2,0,0,0,0,2,2,1,0,1,0,1,0,2,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,2,0,0,2,2,0,0,0,0,1,0,0,0,0,0,0,2, +0,2,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0, +0,2,2,2,2,0,0,0,3,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,1, +0,0,2,0,0,0,0,1,2,0,0,0,0,0,0,2,2,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,2,2,2,0,0,0,2,0,0,0,0,0,0,0,0,2, +0,0,1,0,0,0,0,2,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,3,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,2, +0,0,2,0,0,0,0,2,2,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,0,2,2,1,0,0,0,0,0,0,2,0,0,2,0,2,2,2,0,0,0,0,0,0,2,0,0,0,0,2, +0,0,2,0,0,2,0,2,2,0,0,0,0,2,0,2,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0, +0,0,3,0,0,0,2,2,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0, +0,2,2,2,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1, +0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,2,0,0,0,2,0,0,0,0,0,1,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,2,0,0,0, +0,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,2,0,2,0,0,0, +0,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +) + +Latin7GreekModel = { \ + 'charToOrderMap': Latin7_CharToOrderMap, + 'precedenceMatrix': GreekLangModel, + 'mTypicalPositiveRatio': 0.982851, + 'keepEnglishLetter': constants.False, + 'charsetName': "ISO-8859-7" +} + +Win1253GreekModel = { \ + 'charToOrderMap': win1253_CharToOrderMap, + 'precedenceMatrix': GreekLangModel, + 'mTypicalPositiveRatio': 0.982851, + 'keepEnglishLetter': constants.False, + 'charsetName': "windows-1253" +} diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langhebrewmodel.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langhebrewmodel.py new file mode 100755 index 0000000..a8bcc65 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langhebrewmodel.py @@ -0,0 +1,201 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Simon Montagu +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Shoshannah Forbes - original C code (?) +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Windows-1255 language model +# Character Mapping Table: +win1255_CharToOrderMap = ( \ +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 69, 91, 79, 80, 92, 89, 97, 90, 68,111,112, 82, 73, 95, 85, # 40 + 78,121, 86, 71, 67,102,107, 84,114,103,115,253,253,253,253,253, # 50 +253, 50, 74, 60, 61, 42, 76, 70, 64, 53,105, 93, 56, 65, 54, 49, # 60 + 66,110, 51, 43, 44, 63, 81, 77, 98, 75,108,253,253,253,253,253, # 70 +124,202,203,204,205, 40, 58,206,207,208,209,210,211,212,213,214, +215, 83, 52, 47, 46, 72, 32, 94,216,113,217,109,218,219,220,221, + 34,116,222,118,100,223,224,117,119,104,125,225,226, 87, 99,227, +106,122,123,228, 55,229,230,101,231,232,120,233, 48, 39, 57,234, + 30, 59, 41, 88, 33, 37, 36, 31, 29, 35,235, 62, 28,236,126,237, +238, 38, 45,239,240,241,242,243,127,244,245,246,247,248,249,250, + 9, 8, 20, 16, 3, 2, 24, 14, 22, 1, 25, 15, 4, 11, 6, 23, + 12, 19, 13, 26, 18, 27, 21, 17, 7, 10, 5,251,252,128, 96,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 98.4004% +# first 1024 sequences: 1.5981% +# rest sequences: 0.087% +# negative sequences: 0.0015% +HebrewLangModel = ( \ +0,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,3,2,1,2,0,1,0,0, +3,0,3,1,0,0,1,3,2,0,1,1,2,0,2,2,2,1,1,1,1,2,1,1,1,2,0,0,2,2,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2, +1,2,1,2,1,2,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2, +1,2,1,3,1,1,0,0,2,0,0,0,1,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,1,2,2,1,3, +1,2,1,1,2,2,0,0,2,2,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,1,0,1,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,2,2,2,3,2, +1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,3,2,2,3,2,2,2,1,2,2,2,2, +1,2,1,1,2,2,0,1,2,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,0,2,2,2,2,2, +0,2,0,2,2,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,0,2,2,2, +0,2,1,2,2,2,0,0,2,1,0,0,0,0,1,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,2,1,2,3,2,2,2, +1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,2,0,2, +0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,2,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,2,2,3,2,1,2,1,1,1, +0,1,1,1,1,1,3,0,1,0,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,0,1,0,0,1,0,0,0,0, +0,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,2,1,2,3,3,2,3,3,3,3,2,3,2,1,2,0,2,1,2, +0,2,0,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,1,2,2,3,3,2,3,2,3,2,2,3,1,2,2,0,2,2,2, +0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,2,2,3,3,3,3,1,3,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,2,3,2,2,2,1,2,2,0,2,2,2,2, +0,2,0,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,1,3,2,3,3,2,3,3,2,2,1,2,2,2,2,2,2, +0,2,1,2,1,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,2,3,3,2,3,3,3,3,2,3,2,3,3,3,3,3,2,2,2,2,2,2,2,1, +0,2,0,1,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,1,2,3,3,3,3,3,3,3,2,3,2,3,2,1,2,3,0,2,1,2,2, +0,2,1,1,2,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,2,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,3,2,1,3,1,2,2,2,1,2,3,3,1,2,1,2,2,2,2, +0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,0,2,3,3,3,1,3,3,3,1,2,2,2,2,1,1,2,2,2,2,2,2, +0,2,0,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,2,2,3,3,3,2,1,2,3,2,3,2,2,2,2,1,2,1,1,1,2,2, +0,2,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,1,0,0,0,0,0, +1,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,3,2,3,1,2,2,2,2,3,2,3,1,1,2,2,1,2,2,1,1,0,2,2,2,2, +0,1,0,1,2,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,0,0,1,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,0,1,0,1,1,0,1,1,0,0,0,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +3,2,2,1,2,2,2,2,2,2,2,1,2,2,1,2,2,1,1,1,1,1,1,1,1,2,1,1,0,3,3,3, +0,3,0,2,2,2,2,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,1,2,2,2,1,1,1,2,0,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,0,0,0,0, +0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,0,2,1,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +0,3,1,1,2,2,2,2,2,1,2,2,2,1,1,2,2,2,2,2,2,2,1,2,2,1,0,1,1,1,1,0, +0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,1,1,1,1,2,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, +0,0,2,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,0,0, +2,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,2,1,2,1,1,1,1,0,0,0,0, +0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,1,2,2,2,2,2,2,2,2,2,2,1,2,1,2,1,1,2,1,1,1,2,1,2,1,2,0,1,0,1, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,1,2,2,2,1,2,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,2,1,2,1,1,0,1,0,1, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,1,1,1,1,1,1,0,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,1,1,1,0,1,0,0,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0, +0,1,1,1,2,1,2,2,2,0,2,0,2,0,1,1,2,1,1,1,1,2,1,0,1,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,1,0,0,0,0,0,1,0,1,2,2,0,1,0,0,1,1,2,2,1,2,0,2,0,0,0,1,2,0,1, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,2,1,2,0,2,0,0,1,1,1,1,1,1,0,1,0,0,0,1,0,0,1, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,1,2,2,0,0,1,0,0,0,1,0,0,1, +1,1,2,1,0,1,1,1,0,1,0,1,1,1,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,2,1, +0,2,0,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,0,0,1,0,1,1,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,1,0,0,0,1,1,0,1, +2,0,1,0,1,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,0,1,1,2,1,1,2,0,1,0,0,0,1,1,0,1, +1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,0,0,2,1,1,2,0,2,0,0,0,1,1,0,1, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,2,2,1,2,1,1,0,1,0,0,0,1,1,0,1, +2,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,1,0,1, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,2,1,1,1,0,2,1,1,0,0,0,2,1,0,1, +1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,0,2,1,1,0,1,0,0,0,1,1,0,1, +2,2,1,1,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,0,1,2,1,0,2,0,0,0,1,1,0,1, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0, +0,1,0,0,2,0,2,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,1,0,1,0,0,1,0,0,0,1,0,0,1, +1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,0,2,1,1,1,1,1,0,1,0,0,0,0,1,0,1, +0,1,1,1,2,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,2,1,0,0,0,0,0,1,1,1,1,1,0,1,0,0,0,1,1,0,0, +) + +Win1255HebrewModel = { \ + 'charToOrderMap': win1255_CharToOrderMap, + 'precedenceMatrix': HebrewLangModel, + 'mTypicalPositiveRatio': 0.984004, + 'keepEnglishLetter': constants.False, + 'charsetName': "windows-1255" +} diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langhungarianmodel.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langhungarianmodel.py new file mode 100755 index 0000000..d635f03 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langhungarianmodel.py @@ -0,0 +1,225 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin2_HungarianCharToOrderMap = ( \ +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, + 46, 71, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, +253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, + 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, +159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174, +175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190, +191,192,193,194,195,196,197, 75,198,199,200,201,202,203,204,205, + 79,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, +221, 51, 81,222, 78,223,224,225,226, 44,227,228,229, 61,230,231, +232,233,234, 58,235, 66, 59,236,237,238, 60, 69, 63,239,240,241, + 82, 14, 74,242, 70, 80,243, 72,244, 15, 83, 77, 84, 30, 76, 85, +245,246,247, 25, 73, 42, 24,248,249,250, 31, 56, 29,251,252,253, +) + +win1250HungarianCharToOrderMap = ( \ +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, + 46, 72, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, +253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, + 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, +161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176, +177,178,179,180, 78,181, 69,182,183,184,185,186,187,188,189,190, +191,192,193,194,195,196,197, 76,198,199,200,201,202,203,204,205, + 81,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, +221, 51, 83,222, 80,223,224,225,226, 44,227,228,229, 61,230,231, +232,233,234, 58,235, 66, 59,236,237,238, 60, 70, 63,239,240,241, + 84, 14, 75,242, 71, 82,243, 73,244, 15, 85, 79, 86, 30, 77, 87, +245,246,247, 25, 74, 42, 24,248,249,250, 31, 56, 29,251,252,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 94.7368% +# first 1024 sequences:5.2623% +# rest sequences: 0.8894% +# negative sequences: 0.0009% +HungarianLangModel = ( \ +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,2,3,3,1,1,2,2,2,2,2,1,2, +3,2,2,3,3,3,3,3,2,3,3,3,3,3,3,1,2,3,3,3,3,2,3,3,1,1,3,3,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +3,2,1,3,3,3,3,3,2,3,3,3,3,3,1,1,2,3,3,3,3,3,3,3,1,1,3,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,1,1,2,3,3,3,1,3,3,3,3,3,1,3,3,2,2,0,3,2,3, +0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,3,3,2,3,3,2,2,3,2,3,2,0,3,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,1,2,3,2,2,3,1,2,3,3,2,2,0,3,3,3, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,3,2,3,3,3,3,2,3,3,3,3,0,2,3,2, +0,0,0,1,1,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,1,1,1,3,3,2,1,3,2,2,3,2,1,3,2,2,1,0,3,3,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,2,2,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,3,2,2,3,1,1,3,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,1,3,3,3,3,3,2,2,1,3,3,3,0,1,1,2, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,2,0,3,2,3, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,1,3,2,2,2,3,1,1,3,3,1,1,0,3,3,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,2,3,3,3,3,3,1,2,3,2,2,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,2,2,3,1,3,3,2,2,1,3,3,3,1,1,3,1,2,3,2,3,2,2,2,1,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,2,2,3,2,1,0,3,2,0,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,1,0,3,3,3,3,0,2,3,0,0,2,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,2,3,3,2,2,2,2,3,3,0,1,2,3,2,3,2,2,3,2,1,2,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,3,3,3,3,3,1,2,3,3,3,2,1,2,3,3,2,2,2,3,2,3,3,1,3,3,1,1,0,2,3,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,1,2,2,2,2,3,3,3,1,1,1,3,3,1,1,3,1,1,3,2,1,2,3,1,1,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,1,2,1,1,3,3,1,1,1,1,3,3,1,1,2,2,1,2,1,1,2,2,1,1,0,2,2,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,1,1,2,1,1,3,3,1,0,1,1,3,3,2,0,1,1,2,3,1,0,2,2,1,0,0,1,3,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,2,1,3,3,3,3,3,1,2,3,2,3,3,2,1,1,3,2,3,2,1,2,2,0,1,2,1,0,0,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,2,2,2,2,3,1,2,2,1,1,3,3,0,3,2,1,2,3,2,1,3,3,1,1,0,2,1,3, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,2,2,3,2,3,3,3,2,1,1,3,3,1,1,1,2,2,3,2,3,2,2,2,1,0,2,2,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +1,0,0,3,3,3,3,3,0,0,3,3,2,3,0,0,0,2,3,3,1,0,1,2,0,0,1,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,2,3,3,3,3,3,1,2,3,3,2,2,1,1,0,3,3,2,2,1,2,2,1,0,2,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,2,1,3,1,2,3,3,2,2,1,1,2,2,1,1,1,1,3,2,1,1,1,1,2,1,0,1,2,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +2,3,3,1,1,1,1,1,3,3,3,0,1,1,3,3,1,1,1,1,1,2,2,0,3,1,1,2,0,2,1,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,1,0,1,2,1,2,2,0,1,2,3,1,2,0,0,0,2,1,1,1,1,1,2,0,0,1,1,0,0,0,0, +1,2,1,2,2,2,1,2,1,2,0,2,0,2,2,1,1,2,1,1,2,1,1,1,0,1,0,0,0,1,1,0, +1,1,1,2,3,2,3,3,0,1,2,2,3,1,0,1,0,2,1,2,2,0,1,1,0,0,1,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,3,3,2,2,1,0,0,3,2,3,2,0,0,0,1,1,3,0,0,1,1,0,0,2,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,2,2,3,3,1,0,1,3,2,3,1,1,1,0,1,1,1,1,1,3,1,0,0,2,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,1,2,2,2,1,0,1,2,3,3,2,0,0,0,2,1,1,1,2,1,1,1,0,1,1,1,0,0,0, +1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,2,1,1,1,1,1,1,0,1,1,1,0,0,1,1, +3,2,2,1,0,0,1,1,2,2,0,3,0,1,2,1,1,0,0,1,1,1,0,1,1,1,1,0,2,1,1,1, +2,2,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,2,3,1,1,1,1,1,1,1,1,1,0,1, +2,3,3,0,1,0,0,0,3,3,1,0,0,1,2,2,1,0,0,0,0,2,0,0,1,1,1,0,2,1,1,1, +2,1,1,1,1,1,1,2,1,1,0,1,1,0,1,1,1,0,1,2,1,1,0,1,1,1,1,1,1,1,0,1, +2,3,3,0,1,0,0,0,2,2,0,0,0,0,1,2,2,0,0,0,0,1,0,0,1,1,0,0,2,0,1,0, +2,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, +3,2,2,0,1,0,1,0,2,3,2,0,0,1,2,2,1,0,0,1,1,1,0,0,2,1,0,1,2,2,1,1, +2,1,1,1,1,1,1,2,1,1,1,1,1,1,0,2,1,0,1,1,0,1,1,1,0,1,1,2,1,1,0,1, +2,2,2,0,0,1,0,0,2,2,1,1,0,0,2,1,1,0,0,0,1,2,0,0,2,1,0,0,2,1,1,1, +2,1,1,1,1,2,1,2,1,1,1,2,2,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1, +1,2,3,0,0,0,1,0,3,2,1,0,0,1,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,2,1, +1,1,0,0,0,1,0,1,1,1,1,1,2,0,0,1,0,0,0,2,0,0,1,1,1,1,1,1,1,1,0,1, +3,0,0,2,1,2,2,1,0,0,2,1,2,2,0,0,0,2,1,1,1,0,1,1,0,0,1,1,2,0,0,0, +1,2,1,2,2,1,1,2,1,2,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,0,0,1, +1,3,2,0,0,0,1,0,2,2,2,0,0,0,2,2,1,0,0,0,0,3,1,1,1,1,0,0,2,1,1,1, +2,1,0,1,1,1,0,1,1,1,1,1,1,1,0,2,1,0,0,1,0,1,1,0,1,1,1,1,1,1,0,1, +2,3,2,0,0,0,1,0,2,2,0,0,0,0,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,1,0, +2,1,1,1,1,2,1,2,1,2,0,1,1,1,0,2,1,1,1,2,1,1,1,1,0,1,1,1,1,1,0,1, +3,1,1,2,2,2,3,2,1,1,2,2,1,1,0,1,0,2,2,1,1,1,1,1,0,0,1,1,0,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,0,0,0,0,0,2,2,0,0,0,0,2,2,1,0,0,0,1,1,0,0,1,2,0,0,2,1,1,1, +2,2,1,1,1,2,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,1,1,0,1,2,1,1,1,0,1, +1,0,0,1,2,3,2,1,0,0,2,0,1,1,0,0,0,1,1,1,1,0,1,1,0,0,1,0,0,0,0,0, +1,2,1,2,1,2,1,1,1,2,0,2,1,1,1,0,1,2,0,0,1,1,1,0,0,0,0,0,0,0,0,0, +2,3,2,0,0,0,0,0,1,1,2,1,0,0,1,1,1,0,0,0,0,2,0,0,1,1,0,0,2,1,1,1, +2,1,1,1,1,1,1,2,1,0,1,1,1,1,0,2,1,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1, +1,2,2,0,1,1,1,0,2,2,2,0,0,0,3,2,1,0,0,0,1,1,0,0,1,1,0,1,1,1,0,0, +1,1,0,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,0,0,1,1,1,0,1,0,1, +2,1,0,2,1,1,2,2,1,1,2,1,1,1,0,0,0,1,1,0,1,1,1,1,0,0,1,1,1,0,0,0, +1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,1,0, +1,2,3,0,0,0,1,0,2,2,0,0,0,0,2,2,0,0,0,0,0,1,0,0,1,0,0,0,2,0,1,0, +2,1,1,1,1,1,0,2,0,0,0,1,2,1,1,1,1,0,1,2,0,1,0,1,0,1,1,1,0,1,0,1, +2,2,2,0,0,0,1,0,2,1,2,0,0,0,1,1,2,0,0,0,0,1,0,0,1,1,0,0,2,1,0,1, +2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, +1,2,2,0,0,0,1,0,2,2,2,0,0,0,1,1,0,0,0,0,0,1,1,0,2,0,0,1,1,1,0,1, +1,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,0,0,1,1,0,1,0,1,1,1,1,1,0,0,0,1, +1,0,0,1,0,1,2,1,0,0,1,1,1,2,0,0,0,1,1,0,1,0,1,1,0,0,1,0,0,0,0,0, +0,2,1,2,1,1,1,1,1,2,0,2,0,1,1,0,1,2,1,0,1,1,1,0,0,0,0,0,0,1,0,0, +2,1,1,0,1,2,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,2,1,0,1, +2,2,1,1,1,1,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,0,1,0,1,1,1,1,1,0,1, +1,2,2,0,0,0,0,0,1,1,0,0,0,0,2,1,0,0,0,0,0,2,0,0,2,2,0,0,2,0,0,1, +2,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,1, +1,1,2,0,0,3,1,0,2,1,1,1,0,0,1,1,1,0,0,0,1,1,0,0,0,1,0,0,1,0,1,0, +1,2,1,0,1,1,1,2,1,1,0,1,1,1,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,1,0,0, +2,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,2,0,0,0, +2,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,1,0,1, +2,1,1,1,2,1,1,1,0,1,1,2,1,0,0,0,0,1,1,1,1,0,1,0,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,0,1,1,1,1,1,0,0,1,1,2,1,0,0,0,1,1,0,0,0,1,1,0,0,1,0,1,0,0,0, +1,2,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0, +2,0,0,0,1,1,1,1,0,0,1,1,0,0,0,0,0,1,1,1,2,0,0,1,0,0,1,0,1,0,0,0, +0,1,1,1,1,1,1,1,1,2,0,1,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,1,0,0,2,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0, +0,1,1,1,1,1,1,0,1,1,0,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +0,1,1,1,1,1,0,0,1,1,0,1,0,1,0,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +0,0,0,1,0,0,0,0,0,0,1,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,1,1,0,1,0,0,1,1,0,1,0,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +2,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,0,1,0,0,1,0,1,0,1,1,1,0,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,1,1,1,1,1,0,1,1,0,1,0,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0, +) + +Latin2HungarianModel = { \ + 'charToOrderMap': Latin2_HungarianCharToOrderMap, + 'precedenceMatrix': HungarianLangModel, + 'mTypicalPositiveRatio': 0.947368, + 'keepEnglishLetter': constants.True, + 'charsetName': "ISO-8859-2" +} + +Win1250HungarianModel = { \ + 'charToOrderMap': win1250HungarianCharToOrderMap, + 'precedenceMatrix': HungarianLangModel, + 'mTypicalPositiveRatio': 0.947368, + 'keepEnglishLetter': constants.True, + 'charsetName': "windows-1250" +} diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langthaimodel.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langthaimodel.py new file mode 100755 index 0000000..96ec054 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/langthaimodel.py @@ -0,0 +1,200 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# The following result for thai was collected from a limited sample (1M). + +# Character Mapping Table: +TIS620CharToOrderMap = ( \ +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,182,106,107,100,183,184,185,101, 94,186,187,108,109,110,111, # 40 +188,189,190, 89, 95,112,113,191,192,193,194,253,253,253,253,253, # 50 +253, 64, 72, 73,114, 74,115,116,102, 81,201,117, 90,103, 78, 82, # 60 + 96,202, 91, 79, 84,104,105, 97, 98, 92,203,253,253,253,253,253, # 70 +209,210,211,212,213, 88,214,215,216,217,218,219,220,118,221,222, +223,224, 99, 85, 83,225,226,227,228,229,230,231,232,233,234,235, +236, 5, 30,237, 24,238, 75, 8, 26, 52, 34, 51,119, 47, 58, 57, + 49, 53, 55, 43, 20, 19, 44, 14, 48, 3, 17, 25, 39, 62, 31, 54, + 45, 9, 16, 2, 61, 15,239, 12, 42, 46, 18, 21, 76, 4, 66, 63, + 22, 10, 1, 36, 23, 13, 40, 27, 32, 35, 86,240,241,242,243,244, + 11, 28, 41, 29, 33,245, 50, 37, 6, 7, 67, 77, 38, 93,246,247, + 68, 56, 59, 65, 69, 60, 70, 80, 71, 87,248,249,250,251,252,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 92.6386% +# first 1024 sequences:7.3177% +# rest sequences: 1.0230% +# negative sequences: 0.0436% +ThaiLangModel = ( \ +0,1,3,3,3,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,0,0,3,3,3,0,3,3,3,3, +0,3,3,0,0,0,1,3,0,3,3,2,3,3,0,1,2,3,3,3,3,0,2,0,2,0,0,3,2,1,2,2, +3,0,3,3,2,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,0,3,2,3,0,2,2,2,3, +0,2,3,0,0,0,0,1,0,1,2,3,1,1,3,2,2,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1, +3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,3,3,2,3,2,3,3,2,2,2, +3,1,2,3,0,3,3,2,2,1,2,3,3,1,2,0,1,3,0,1,0,0,1,0,0,0,0,0,0,0,1,1, +3,3,2,2,3,3,3,3,1,2,3,3,3,3,3,2,2,2,2,3,3,2,2,3,3,2,2,3,2,3,2,2, +3,3,1,2,3,1,2,2,3,3,1,0,2,1,0,0,3,1,2,1,0,0,1,0,0,0,0,0,0,1,0,1, +3,3,3,3,3,3,2,2,3,3,3,3,2,3,2,2,3,3,2,2,3,2,2,2,2,1,1,3,1,2,1,1, +3,2,1,0,2,1,0,1,0,1,1,0,1,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,3,2,3,2,3,3,2,2,3,2,3,3,2,3,1,1,2,3,2,2,2,3,2,2,2,2,2,1,2,1, +2,2,1,1,3,3,2,1,0,1,2,2,0,1,3,0,0,0,1,1,0,0,0,0,0,2,3,0,0,2,1,1, +3,3,2,3,3,2,0,0,3,3,0,3,3,0,2,2,3,1,2,2,1,1,1,0,2,2,2,0,2,2,1,1, +0,2,1,0,2,0,0,2,0,1,0,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,2,3,3,2,0,0,3,3,0,2,3,0,2,1,2,2,2,2,1,2,0,0,2,2,2,0,2,2,1,1, +0,2,1,0,2,0,0,2,0,1,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,2,3,2,3,2,0,2,2,1,3,2,1,3,2,1,2,3,2,2,3,0,2,3,2,2,1,2,2,2,2, +1,2,2,0,0,0,0,2,0,1,2,0,1,1,1,0,1,0,3,1,1,0,0,0,0,0,0,0,0,0,1,0, +3,3,2,3,3,2,3,2,2,2,3,2,2,3,2,2,1,2,3,2,2,3,1,3,2,2,2,3,2,2,2,3, +3,2,1,3,0,1,1,1,0,2,1,1,1,1,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,2,0,0, +1,0,0,3,0,3,3,3,3,3,0,0,3,0,2,2,3,3,3,3,3,0,0,0,1,1,3,0,0,0,0,2, +0,0,1,0,0,0,0,0,0,0,2,3,0,0,0,3,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +2,0,3,3,3,3,0,0,2,3,0,0,3,0,3,3,2,3,3,3,3,3,0,0,3,3,3,0,0,0,3,3, +0,0,3,0,0,0,0,2,0,0,2,1,1,3,0,0,1,0,0,2,3,0,1,0,0,0,0,0,0,0,1,0, +3,3,3,3,2,3,3,3,3,3,3,3,1,2,1,3,3,2,2,1,2,2,2,3,1,1,2,0,2,1,2,1, +2,2,1,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0, +3,0,2,1,2,3,3,3,0,2,0,2,2,0,2,1,3,2,2,1,2,1,0,0,2,2,1,0,2,1,2,2, +0,1,1,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,3,3,1,1,3,0,2,3,1,1,3,2,1,1,2,0,2,2,3,2,1,1,1,1,1,2, +3,0,0,1,3,1,2,1,2,0,3,0,0,0,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, +3,3,1,1,3,2,3,3,3,1,3,2,1,3,2,1,3,2,2,2,2,1,3,3,1,2,1,3,1,2,3,0, +2,1,1,3,2,2,2,1,2,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, +3,3,2,3,2,3,3,2,3,2,3,2,3,3,2,1,0,3,2,2,2,1,2,2,2,1,2,2,1,2,1,1, +2,2,2,3,0,1,3,1,1,1,1,0,1,1,0,2,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,3,2,2,1,1,3,2,3,2,3,2,0,3,2,2,1,2,0,2,2,2,1,2,2,2,2,1, +3,2,1,2,2,1,0,2,0,1,0,0,1,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,2,3,1,2,3,3,2,2,3,0,1,1,2,0,3,3,2,2,3,0,1,1,3,0,0,0,0, +3,1,0,3,3,0,2,0,2,1,0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,3,2,3,3,0,1,3,1,1,2,1,2,1,1,3,1,1,0,2,3,1,1,1,1,1,1,1,1, +3,1,1,2,2,2,2,1,1,1,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,2,2,1,1,2,1,3,3,2,3,2,2,3,2,2,3,1,2,2,1,2,0,3,2,1,2,2,2,2,2,1, +3,2,1,2,2,2,1,1,1,1,0,0,1,1,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,1,3,3,0,2,1,0,3,2,0,0,3,1,0,1,1,0,1,0,0,0,0,0,1, +1,0,0,1,0,3,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,2,2,2,3,0,0,1,3,0,3,2,0,3,2,2,3,3,3,3,3,1,0,2,2,2,0,2,2,1,2, +0,2,3,0,0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,0,2,3,1,3,3,2,3,3,0,3,3,0,3,2,2,3,2,3,3,3,0,0,2,2,3,0,1,1,1,3, +0,0,3,0,0,0,2,2,0,1,3,0,1,2,2,2,3,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1, +3,2,3,3,2,0,3,3,2,2,3,1,3,2,1,3,2,0,1,2,2,0,2,3,2,1,0,3,0,0,0,0, +3,0,0,2,3,1,3,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,3,2,2,2,1,2,0,1,3,1,1,3,1,3,0,0,2,1,1,1,1,2,1,1,1,0,2,1,0,1, +1,2,0,0,0,3,1,1,0,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,3,1,0,0,0,1,0, +3,3,3,3,2,2,2,2,2,1,3,1,1,1,2,0,1,1,2,1,2,1,3,2,0,0,3,1,1,1,1,1, +3,1,0,2,3,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,2,3,0,3,3,0,2,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,3,1,3,0,0,1,2,0,0,2,0,3,3,2,3,3,3,2,3,0,0,2,2,2,0,0,0,2,2, +0,0,1,0,0,0,0,3,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +0,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,1,2,3,1,3,3,0,0,1,0,3,0,0,0,0,0, +0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,1,2,3,1,2,3,1,0,3,0,2,2,1,0,2,1,1,2,0,1,0,0,1,1,1,1,0,1,0,0, +1,0,0,0,0,1,1,0,3,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,0,1,1,1,3,1,2,2,2,2,2,2,1,1,1,1,0,3,1,0,1,3,1,1,1,1, +1,1,0,2,0,1,3,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1, +3,0,2,2,1,3,3,2,3,3,0,1,1,0,2,2,1,2,1,3,3,1,0,0,3,2,0,0,0,0,2,1, +0,1,0,0,0,0,1,2,0,1,1,3,1,1,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,3,0,0,1,0,0,0,3,0,0,3,0,3,1,0,1,1,1,3,2,0,0,0,3,0,0,0,0,2,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,1,3,2,1,3,3,1,2,2,0,1,2,1,0,1,2,0,0,0,0,0,3,0,0,0,3,0,0,0,0, +3,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,2,0,3,3,3,2,2,0,1,1,0,1,3,0,0,0,2,2,0,0,0,0,3,1,0,1,0,0,0, +0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,2,3,1,2,0,0,2,1,0,3,1,0,1,2,0,1,1,1,1,3,0,0,3,1,1,0,2,2,1,1, +0,2,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,3,1,2,0,0,2,2,0,1,2,0,1,0,1,3,1,2,1,0,0,0,2,0,3,0,0,0,1,0, +0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,1,2,2,0,0,0,2,0,2,1,0,1,1,0,1,1,1,2,1,0,0,1,1,1,0,2,1,1,1, +0,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1, +0,0,0,2,0,1,3,1,1,1,1,0,0,0,0,3,2,0,1,0,0,0,1,2,0,0,0,1,0,0,0,0, +0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,2,3,2,2,0,0,0,1,0,0,0,0,2,3,2,1,2,2,3,0,0,0,2,3,1,0,0,0,1,1, +0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0, +3,3,2,2,0,1,0,0,0,0,2,0,2,0,1,0,0,0,1,1,0,0,0,2,1,0,1,0,1,1,0,0, +0,1,0,2,0,0,1,0,3,0,1,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,1,0,0,1,0,0,0,0,0,1,1,2,0,0,0,0,1,0,0,1,3,1,0,0,0,0,1,1,0,0, +0,1,0,0,0,0,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0, +3,3,1,1,1,1,2,3,0,0,2,1,1,1,1,1,0,2,1,1,0,0,0,2,1,0,1,2,1,1,0,1, +2,1,0,3,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,3,1,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1, +0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,0,0,0,0,0,0,1,2,1,0,1,1,0,2,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,2,0,0,0,1,3,0,1,0,0,0,2,0,0,0,0,0,0,0,1,2,0,0,0,0,0, +3,3,0,0,1,1,2,0,0,1,2,1,0,1,1,1,0,1,1,0,0,2,1,1,0,1,0,0,1,1,1,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,1,0,0,0,0,1,0,0,0,0,3,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,0,0,1,1,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,0,1,2,0,1,2,0,0,1,1,0,2,0,1,0,0,1,0,0,0,0,1,0,0,0,2,0,0,0,0, +1,0,0,1,0,1,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,0,0,0,0,0,0,0,1,1,0,1,1,0,2,1,3,0,0,0,0,1,1,0,0,0,0,0,0,0,3, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,1,0,0,2,0,0,2,0,0,1,1,2,0,0,1,1,0,0,0,1,0,0,0,1,1,0,0,0, +1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,3,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0, +1,0,0,0,0,0,0,0,0,1,0,0,0,0,2,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,1,0,0,2,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +) + +TIS620ThaiModel = { \ + 'charToOrderMap': TIS620CharToOrderMap, + 'precedenceMatrix': ThaiLangModel, + 'mTypicalPositiveRatio': 0.926386, + 'keepEnglishLetter': constants.False, + 'charsetName': "TIS-620" +} diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/latin1prober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/latin1prober.py new file mode 100755 index 0000000..b46129b --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/latin1prober.py @@ -0,0 +1,136 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from charsetprober import CharSetProber +import constants +import operator + +FREQ_CAT_NUM = 4 + +UDF = 0 # undefined +OTH = 1 # other +ASC = 2 # ascii capital letter +ASS = 3 # ascii small letter +ACV = 4 # accent capital vowel +ACO = 5 # accent capital other +ASV = 6 # accent small vowel +ASO = 7 # accent small other +CLASS_NUM = 8 # total classes + +Latin1_CharToClass = ( \ + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 00 - 07 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 08 - 0F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 10 - 17 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 18 - 1F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 20 - 27 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 28 - 2F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 30 - 37 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 38 - 3F + OTH, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 40 - 47 + ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 48 - 4F + ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 50 - 57 + ASC, ASC, ASC, OTH, OTH, OTH, OTH, OTH, # 58 - 5F + OTH, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 60 - 67 + ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 68 - 6F + ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 70 - 77 + ASS, ASS, ASS, OTH, OTH, OTH, OTH, OTH, # 78 - 7F + OTH, UDF, OTH, ASO, OTH, OTH, OTH, OTH, # 80 - 87 + OTH, OTH, ACO, OTH, ACO, UDF, ACO, UDF, # 88 - 8F + UDF, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 90 - 97 + OTH, OTH, ASO, OTH, ASO, UDF, ASO, ACO, # 98 - 9F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A0 - A7 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A8 - AF + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B0 - B7 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B8 - BF + ACV, ACV, ACV, ACV, ACV, ACV, ACO, ACO, # C0 - C7 + ACV, ACV, ACV, ACV, ACV, ACV, ACV, ACV, # C8 - CF + ACO, ACO, ACV, ACV, ACV, ACV, ACV, OTH, # D0 - D7 + ACV, ACV, ACV, ACV, ACV, ACO, ACO, ACO, # D8 - DF + ASV, ASV, ASV, ASV, ASV, ASV, ASO, ASO, # E0 - E7 + ASV, ASV, ASV, ASV, ASV, ASV, ASV, ASV, # E8 - EF + ASO, ASO, ASV, ASV, ASV, ASV, ASV, OTH, # F0 - F7 + ASV, ASV, ASV, ASV, ASV, ASO, ASO, ASO, # F8 - FF +) + +# 0 : illegal +# 1 : very unlikely +# 2 : normal +# 3 : very likely +Latin1ClassModel = ( \ +# UDF OTH ASC ASS ACV ACO ASV ASO + 0, 0, 0, 0, 0, 0, 0, 0, # UDF + 0, 3, 3, 3, 3, 3, 3, 3, # OTH + 0, 3, 3, 3, 3, 3, 3, 3, # ASC + 0, 3, 3, 3, 1, 1, 3, 3, # ASS + 0, 3, 3, 3, 1, 2, 1, 2, # ACV + 0, 3, 3, 3, 3, 3, 3, 3, # ACO + 0, 3, 1, 3, 1, 1, 1, 3, # ASV + 0, 3, 1, 3, 1, 1, 3, 3, # ASO +) + +class Latin1Prober(CharSetProber): + def __init__(self): + CharSetProber.__init__(self) + self.reset() + + def reset(self): + self._mLastCharClass = OTH + self._mFreqCounter = [0] * FREQ_CAT_NUM + CharSetProber.reset(self) + + def get_charset_name(self): + return "windows-1252" + + def feed(self, aBuf): + aBuf = self.filter_with_english_letters(aBuf) + for c in aBuf: + charClass = Latin1_CharToClass[ord(c)] + freq = Latin1ClassModel[(self._mLastCharClass * CLASS_NUM) + charClass] + if freq == 0: + self._mState = constants.eNotMe + break + self._mFreqCounter[freq] += 1 + self._mLastCharClass = charClass + + return self.get_state() + + def get_confidence(self): + if self.get_state() == constants.eNotMe: + return 0.01 + + total = reduce(operator.add, self._mFreqCounter) + if total < 0.01: + confidence = 0.0 + else: + confidence = (self._mFreqCounter[3] / total) - (self._mFreqCounter[1] * 20.0 / total) + if confidence < 0.0: + confidence = 0.0 + # lower the confidence of latin1 so that other more accurate detector + # can take priority. + confidence = confidence * 0.5 + return confidence diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/mbcharsetprober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/mbcharsetprober.py new file mode 100755 index 0000000..a813144 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/mbcharsetprober.py @@ -0,0 +1,82 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Proofpoint, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants, sys +from constants import eStart, eError, eItsMe +from charsetprober import CharSetProber + +class MultiByteCharSetProber(CharSetProber): + def __init__(self): + CharSetProber.__init__(self) + self._mDistributionAnalyzer = None + self._mCodingSM = None + self._mLastChar = ['\x00', '\x00'] + + def reset(self): + CharSetProber.reset(self) + if self._mCodingSM: + self._mCodingSM.reset() + if self._mDistributionAnalyzer: + self._mDistributionAnalyzer.reset() + self._mLastChar = ['\x00', '\x00'] + + def get_charset_name(self): + pass + + def feed(self, aBuf): + aLen = len(aBuf) + for i in range(0, aLen): + codingState = self._mCodingSM.next_state(aBuf[i]) + if codingState == eError: + if constants._debug: + sys.stderr.write(self.get_charset_name() + ' prober hit error at byte ' + str(i) + '\n') + self._mState = constants.eNotMe + break + elif codingState == eItsMe: + self._mState = constants.eFoundIt + break + elif codingState == eStart: + charLen = self._mCodingSM.get_current_charlen() + if i == 0: + self._mLastChar[1] = aBuf[0] + self._mDistributionAnalyzer.feed(self._mLastChar, charLen) + else: + self._mDistributionAnalyzer.feed(aBuf[i-1:i+1], charLen) + + self._mLastChar[0] = aBuf[aLen - 1] + + if self.get_state() == constants.eDetecting: + if self._mDistributionAnalyzer.got_enough_data() and \ + (self.get_confidence() > constants.SHORTCUT_THRESHOLD): + self._mState = constants.eFoundIt + + return self.get_state() + + def get_confidence(self): + return self._mDistributionAnalyzer.get_confidence() diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/mbcsgroupprober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/mbcsgroupprober.py new file mode 100755 index 0000000..941cc3e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/mbcsgroupprober.py @@ -0,0 +1,50 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Proofpoint, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from charsetgroupprober import CharSetGroupProber +from utf8prober import UTF8Prober +from sjisprober import SJISProber +from eucjpprober import EUCJPProber +from gb2312prober import GB2312Prober +from euckrprober import EUCKRProber +from big5prober import Big5Prober +from euctwprober import EUCTWProber + +class MBCSGroupProber(CharSetGroupProber): + def __init__(self): + CharSetGroupProber.__init__(self) + self._mProbers = [ \ + UTF8Prober(), + SJISProber(), + EUCJPProber(), + GB2312Prober(), + EUCKRProber(), + Big5Prober(), + EUCTWProber()] + self.reset() diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/mbcssm.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/mbcssm.py new file mode 100755 index 0000000..e46c1ff --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/mbcssm.py @@ -0,0 +1,514 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from constants import eStart, eError, eItsMe + +# BIG5 + +BIG5_cls = ( \ + 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as legal value + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,1, # 78 - 7f + 4,4,4,4,4,4,4,4, # 80 - 87 + 4,4,4,4,4,4,4,4, # 88 - 8f + 4,4,4,4,4,4,4,4, # 90 - 97 + 4,4,4,4,4,4,4,4, # 98 - 9f + 4,3,3,3,3,3,3,3, # a0 - a7 + 3,3,3,3,3,3,3,3, # a8 - af + 3,3,3,3,3,3,3,3, # b0 - b7 + 3,3,3,3,3,3,3,3, # b8 - bf + 3,3,3,3,3,3,3,3, # c0 - c7 + 3,3,3,3,3,3,3,3, # c8 - cf + 3,3,3,3,3,3,3,3, # d0 - d7 + 3,3,3,3,3,3,3,3, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,3,3,3, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,3,3,0) # f8 - ff + +BIG5_st = ( \ + eError,eStart,eStart, 3,eError,eError,eError,eError,#00-07 + eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eError,#08-0f + eError,eStart,eStart,eStart,eStart,eStart,eStart,eStart)#10-17 + +Big5CharLenTable = (0, 1, 1, 2, 0) + +Big5SMModel = {'classTable': BIG5_cls, + 'classFactor': 5, + 'stateTable': BIG5_st, + 'charLenTable': Big5CharLenTable, + 'name': 'Big5'} + +# EUC-JP + +EUCJP_cls = ( \ + 4,4,4,4,4,4,4,4, # 00 - 07 + 4,4,4,4,4,4,5,5, # 08 - 0f + 4,4,4,4,4,4,4,4, # 10 - 17 + 4,4,4,5,4,4,4,4, # 18 - 1f + 4,4,4,4,4,4,4,4, # 20 - 27 + 4,4,4,4,4,4,4,4, # 28 - 2f + 4,4,4,4,4,4,4,4, # 30 - 37 + 4,4,4,4,4,4,4,4, # 38 - 3f + 4,4,4,4,4,4,4,4, # 40 - 47 + 4,4,4,4,4,4,4,4, # 48 - 4f + 4,4,4,4,4,4,4,4, # 50 - 57 + 4,4,4,4,4,4,4,4, # 58 - 5f + 4,4,4,4,4,4,4,4, # 60 - 67 + 4,4,4,4,4,4,4,4, # 68 - 6f + 4,4,4,4,4,4,4,4, # 70 - 77 + 4,4,4,4,4,4,4,4, # 78 - 7f + 5,5,5,5,5,5,5,5, # 80 - 87 + 5,5,5,5,5,5,1,3, # 88 - 8f + 5,5,5,5,5,5,5,5, # 90 - 97 + 5,5,5,5,5,5,5,5, # 98 - 9f + 5,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,2,2,2, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,2,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,0,5) # f8 - ff + +EUCJP_st = ( \ + 3, 4, 3, 5,eStart,eError,eError,eError,#00-07 + eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,#08-0f + eItsMe,eItsMe,eStart,eError,eStart,eError,eError,eError,#10-17 + eError,eError,eStart,eError,eError,eError, 3,eError,#18-1f + 3,eError,eError,eError,eStart,eStart,eStart,eStart)#20-27 + +EUCJPCharLenTable = (2, 2, 2, 3, 1, 0) + +EUCJPSMModel = {'classTable': EUCJP_cls, + 'classFactor': 6, + 'stateTable': EUCJP_st, + 'charLenTable': EUCJPCharLenTable, + 'name': 'EUC-JP'} + +# EUC-KR + +EUCKR_cls = ( \ + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 1,1,1,1,1,1,1,1, # 40 - 47 + 1,1,1,1,1,1,1,1, # 48 - 4f + 1,1,1,1,1,1,1,1, # 50 - 57 + 1,1,1,1,1,1,1,1, # 58 - 5f + 1,1,1,1,1,1,1,1, # 60 - 67 + 1,1,1,1,1,1,1,1, # 68 - 6f + 1,1,1,1,1,1,1,1, # 70 - 77 + 1,1,1,1,1,1,1,1, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,3,3,3, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,3,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 2,2,2,2,2,2,2,2, # e0 - e7 + 2,2,2,2,2,2,2,2, # e8 - ef + 2,2,2,2,2,2,2,2, # f0 - f7 + 2,2,2,2,2,2,2,0) # f8 - ff + +EUCKR_st = ( + eError,eStart, 3,eError,eError,eError,eError,eError,#00-07 + eItsMe,eItsMe,eItsMe,eItsMe,eError,eError,eStart,eStart)#08-0f + +EUCKRCharLenTable = (0, 1, 2, 0) + +EUCKRSMModel = {'classTable': EUCKR_cls, + 'classFactor': 4, + 'stateTable': EUCKR_st, + 'charLenTable': EUCKRCharLenTable, + 'name': 'EUC-KR'} + +# EUC-TW + +EUCTW_cls = ( \ + 2,2,2,2,2,2,2,2, # 00 - 07 + 2,2,2,2,2,2,0,0, # 08 - 0f + 2,2,2,2,2,2,2,2, # 10 - 17 + 2,2,2,0,2,2,2,2, # 18 - 1f + 2,2,2,2,2,2,2,2, # 20 - 27 + 2,2,2,2,2,2,2,2, # 28 - 2f + 2,2,2,2,2,2,2,2, # 30 - 37 + 2,2,2,2,2,2,2,2, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,2, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,6,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,3,4,4,4,4,4,4, # a0 - a7 + 5,5,1,1,1,1,1,1, # a8 - af + 1,1,1,1,1,1,1,1, # b0 - b7 + 1,1,1,1,1,1,1,1, # b8 - bf + 1,1,3,1,3,3,3,3, # c0 - c7 + 3,3,3,3,3,3,3,3, # c8 - cf + 3,3,3,3,3,3,3,3, # d0 - d7 + 3,3,3,3,3,3,3,3, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,3,3,3, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,3,3,0) # f8 - ff + +EUCTW_st = ( \ + eError,eError,eStart, 3, 3, 3, 4,eError,#00-07 + eError,eError,eError,eError,eError,eError,eItsMe,eItsMe,#08-0f + eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eError,eStart,eError,#10-17 + eStart,eStart,eStart,eError,eError,eError,eError,eError,#18-1f + 5,eError,eError,eError,eStart,eError,eStart,eStart,#20-27 + eStart,eError,eStart,eStart,eStart,eStart,eStart,eStart)#28-2f + +EUCTWCharLenTable = (0, 0, 1, 2, 2, 2, 3) + +EUCTWSMModel = {'classTable': EUCTW_cls, + 'classFactor': 7, + 'stateTable': EUCTW_st, + 'charLenTable': EUCTWCharLenTable, + 'name': 'x-euc-tw'} + +# GB2312 + +GB2312_cls = ( \ + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 3,3,3,3,3,3,3,3, # 30 - 37 + 3,3,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,4, # 78 - 7f + 5,6,6,6,6,6,6,6, # 80 - 87 + 6,6,6,6,6,6,6,6, # 88 - 8f + 6,6,6,6,6,6,6,6, # 90 - 97 + 6,6,6,6,6,6,6,6, # 98 - 9f + 6,6,6,6,6,6,6,6, # a0 - a7 + 6,6,6,6,6,6,6,6, # a8 - af + 6,6,6,6,6,6,6,6, # b0 - b7 + 6,6,6,6,6,6,6,6, # b8 - bf + 6,6,6,6,6,6,6,6, # c0 - c7 + 6,6,6,6,6,6,6,6, # c8 - cf + 6,6,6,6,6,6,6,6, # d0 - d7 + 6,6,6,6,6,6,6,6, # d8 - df + 6,6,6,6,6,6,6,6, # e0 - e7 + 6,6,6,6,6,6,6,6, # e8 - ef + 6,6,6,6,6,6,6,6, # f0 - f7 + 6,6,6,6,6,6,6,0) # f8 - ff + +GB2312_st = ( \ + eError,eStart,eStart,eStart,eStart,eStart, 3,eError,#00-07 + eError,eError,eError,eError,eError,eError,eItsMe,eItsMe,#08-0f + eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eError,eError,eStart,#10-17 + 4,eError,eStart,eStart,eError,eError,eError,eError,#18-1f + eError,eError, 5,eError,eError,eError,eItsMe,eError,#20-27 + eError,eError,eStart,eStart,eStart,eStart,eStart,eStart)#28-2f + +# To be accurate, the length of class 6 can be either 2 or 4. +# But it is not necessary to discriminate between the two since +# it is used for frequency analysis only, and we are validing +# each code range there as well. So it is safe to set it to be +# 2 here. +GB2312CharLenTable = (0, 1, 1, 1, 1, 1, 2) + +GB2312SMModel = {'classTable': GB2312_cls, + 'classFactor': 7, + 'stateTable': GB2312_st, + 'charLenTable': GB2312CharLenTable, + 'name': 'GB2312'} + +# Shift_JIS + +SJIS_cls = ( \ + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,1, # 78 - 7f + 3,3,3,3,3,3,3,3, # 80 - 87 + 3,3,3,3,3,3,3,3, # 88 - 8f + 3,3,3,3,3,3,3,3, # 90 - 97 + 3,3,3,3,3,3,3,3, # 98 - 9f + #0xa0 is illegal in sjis encoding, but some pages does + #contain such byte. We need to be more error forgiven. + 2,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,2,2,2, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,2,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,4,4,4, # e8 - ef + 4,4,4,4,4,4,4,4, # f0 - f7 + 4,4,4,4,4,0,0,0) # f8 - ff + +SJIS_st = ( \ + eError,eStart,eStart, 3,eError,eError,eError,eError,#00-07 + eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,#08-0f + eItsMe,eItsMe,eError,eError,eStart,eStart,eStart,eStart)#10-17 + +SJISCharLenTable = (0, 1, 1, 2, 0, 0) + +SJISSMModel = {'classTable': SJIS_cls, + 'classFactor': 6, + 'stateTable': SJIS_st, + 'charLenTable': SJISCharLenTable, + 'name': 'Shift_JIS'} + +# UCS2-BE + +UCS2BE_cls = ( \ + 0,0,0,0,0,0,0,0, # 00 - 07 + 0,0,1,0,0,2,0,0, # 08 - 0f + 0,0,0,0,0,0,0,0, # 10 - 17 + 0,0,0,3,0,0,0,0, # 18 - 1f + 0,0,0,0,0,0,0,0, # 20 - 27 + 0,3,3,3,3,3,0,0, # 28 - 2f + 0,0,0,0,0,0,0,0, # 30 - 37 + 0,0,0,0,0,0,0,0, # 38 - 3f + 0,0,0,0,0,0,0,0, # 40 - 47 + 0,0,0,0,0,0,0,0, # 48 - 4f + 0,0,0,0,0,0,0,0, # 50 - 57 + 0,0,0,0,0,0,0,0, # 58 - 5f + 0,0,0,0,0,0,0,0, # 60 - 67 + 0,0,0,0,0,0,0,0, # 68 - 6f + 0,0,0,0,0,0,0,0, # 70 - 77 + 0,0,0,0,0,0,0,0, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,0,0,0,0,0,0,0, # a0 - a7 + 0,0,0,0,0,0,0,0, # a8 - af + 0,0,0,0,0,0,0,0, # b0 - b7 + 0,0,0,0,0,0,0,0, # b8 - bf + 0,0,0,0,0,0,0,0, # c0 - c7 + 0,0,0,0,0,0,0,0, # c8 - cf + 0,0,0,0,0,0,0,0, # d0 - d7 + 0,0,0,0,0,0,0,0, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,4,5) # f8 - ff + +UCS2BE_st = ( \ + 5, 7, 7,eError, 4, 3,eError,eError,#00-07 + eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,#08-0f + eItsMe,eItsMe, 6, 6, 6, 6,eError,eError,#10-17 + 6, 6, 6, 6, 6,eItsMe, 6, 6,#18-1f + 6, 6, 6, 6, 5, 7, 7,eError,#20-27 + 5, 8, 6, 6,eError, 6, 6, 6,#28-2f + 6, 6, 6, 6,eError,eError,eStart,eStart)#30-37 + +UCS2BECharLenTable = (2, 2, 2, 0, 2, 2) + +UCS2BESMModel = {'classTable': UCS2BE_cls, + 'classFactor': 6, + 'stateTable': UCS2BE_st, + 'charLenTable': UCS2BECharLenTable, + 'name': 'UTF-16BE'} + +# UCS2-LE + +UCS2LE_cls = ( \ + 0,0,0,0,0,0,0,0, # 00 - 07 + 0,0,1,0,0,2,0,0, # 08 - 0f + 0,0,0,0,0,0,0,0, # 10 - 17 + 0,0,0,3,0,0,0,0, # 18 - 1f + 0,0,0,0,0,0,0,0, # 20 - 27 + 0,3,3,3,3,3,0,0, # 28 - 2f + 0,0,0,0,0,0,0,0, # 30 - 37 + 0,0,0,0,0,0,0,0, # 38 - 3f + 0,0,0,0,0,0,0,0, # 40 - 47 + 0,0,0,0,0,0,0,0, # 48 - 4f + 0,0,0,0,0,0,0,0, # 50 - 57 + 0,0,0,0,0,0,0,0, # 58 - 5f + 0,0,0,0,0,0,0,0, # 60 - 67 + 0,0,0,0,0,0,0,0, # 68 - 6f + 0,0,0,0,0,0,0,0, # 70 - 77 + 0,0,0,0,0,0,0,0, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,0,0,0,0,0,0,0, # a0 - a7 + 0,0,0,0,0,0,0,0, # a8 - af + 0,0,0,0,0,0,0,0, # b0 - b7 + 0,0,0,0,0,0,0,0, # b8 - bf + 0,0,0,0,0,0,0,0, # c0 - c7 + 0,0,0,0,0,0,0,0, # c8 - cf + 0,0,0,0,0,0,0,0, # d0 - d7 + 0,0,0,0,0,0,0,0, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,4,5) # f8 - ff + +UCS2LE_st = ( \ + 6, 6, 7, 6, 4, 3,eError,eError,#00-07 + eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,#08-0f + eItsMe,eItsMe, 5, 5, 5,eError,eItsMe,eError,#10-17 + 5, 5, 5,eError, 5,eError, 6, 6,#18-1f + 7, 6, 8, 8, 5, 5, 5,eError,#20-27 + 5, 5, 5,eError,eError,eError, 5, 5,#28-2f + 5, 5, 5,eError, 5,eError,eStart,eStart)#30-37 + +UCS2LECharLenTable = (2, 2, 2, 2, 2, 2) + +UCS2LESMModel = {'classTable': UCS2LE_cls, + 'classFactor': 6, + 'stateTable': UCS2LE_st, + 'charLenTable': UCS2LECharLenTable, + 'name': 'UTF-16LE'} + +# UTF-8 + +UTF8_cls = ( \ + 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as a legal value + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 1,1,1,1,1,1,1,1, # 40 - 47 + 1,1,1,1,1,1,1,1, # 48 - 4f + 1,1,1,1,1,1,1,1, # 50 - 57 + 1,1,1,1,1,1,1,1, # 58 - 5f + 1,1,1,1,1,1,1,1, # 60 - 67 + 1,1,1,1,1,1,1,1, # 68 - 6f + 1,1,1,1,1,1,1,1, # 70 - 77 + 1,1,1,1,1,1,1,1, # 78 - 7f + 2,2,2,2,3,3,3,3, # 80 - 87 + 4,4,4,4,4,4,4,4, # 88 - 8f + 4,4,4,4,4,4,4,4, # 90 - 97 + 4,4,4,4,4,4,4,4, # 98 - 9f + 5,5,5,5,5,5,5,5, # a0 - a7 + 5,5,5,5,5,5,5,5, # a8 - af + 5,5,5,5,5,5,5,5, # b0 - b7 + 5,5,5,5,5,5,5,5, # b8 - bf + 0,0,6,6,6,6,6,6, # c0 - c7 + 6,6,6,6,6,6,6,6, # c8 - cf + 6,6,6,6,6,6,6,6, # d0 - d7 + 6,6,6,6,6,6,6,6, # d8 - df + 7,8,8,8,8,8,8,8, # e0 - e7 + 8,8,8,8,8,9,8,8, # e8 - ef + 10,11,11,11,11,11,11,11, # f0 - f7 + 12,13,13,13,14,15,0,0) # f8 - ff + +UTF8_st = ( \ + eError,eStart,eError,eError,eError,eError, 12, 10,#00-07 + 9, 11, 8, 7, 6, 5, 4, 3,#08-0f + eError,eError,eError,eError,eError,eError,eError,eError,#10-17 + eError,eError,eError,eError,eError,eError,eError,eError,#18-1f + eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,#20-27 + eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,#28-2f + eError,eError, 5, 5, 5, 5,eError,eError,#30-37 + eError,eError,eError,eError,eError,eError,eError,eError,#38-3f + eError,eError,eError, 5, 5, 5,eError,eError,#40-47 + eError,eError,eError,eError,eError,eError,eError,eError,#48-4f + eError,eError, 7, 7, 7, 7,eError,eError,#50-57 + eError,eError,eError,eError,eError,eError,eError,eError,#58-5f + eError,eError,eError,eError, 7, 7,eError,eError,#60-67 + eError,eError,eError,eError,eError,eError,eError,eError,#68-6f + eError,eError, 9, 9, 9, 9,eError,eError,#70-77 + eError,eError,eError,eError,eError,eError,eError,eError,#78-7f + eError,eError,eError,eError,eError, 9,eError,eError,#80-87 + eError,eError,eError,eError,eError,eError,eError,eError,#88-8f + eError,eError, 12, 12, 12, 12,eError,eError,#90-97 + eError,eError,eError,eError,eError,eError,eError,eError,#98-9f + eError,eError,eError,eError,eError, 12,eError,eError,#a0-a7 + eError,eError,eError,eError,eError,eError,eError,eError,#a8-af + eError,eError, 12, 12, 12,eError,eError,eError,#b0-b7 + eError,eError,eError,eError,eError,eError,eError,eError,#b8-bf + eError,eError,eStart,eStart,eStart,eStart,eError,eError,#c0-c7 + eError,eError,eError,eError,eError,eError,eError,eError)#c8-cf + +UTF8CharLenTable = (0, 1, 0, 0, 0, 0, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6) + +UTF8SMModel = {'classTable': UTF8_cls, + 'classFactor': 16, + 'stateTable': UTF8_st, + 'charLenTable': UTF8CharLenTable, + 'name': 'UTF-8'} diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/sbcharsetprober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/sbcharsetprober.py new file mode 100755 index 0000000..da07116 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/sbcharsetprober.py @@ -0,0 +1,106 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants, sys +from charsetprober import CharSetProber + +SAMPLE_SIZE = 64 +SB_ENOUGH_REL_THRESHOLD = 1024 +POSITIVE_SHORTCUT_THRESHOLD = 0.95 +NEGATIVE_SHORTCUT_THRESHOLD = 0.05 +SYMBOL_CAT_ORDER = 250 +NUMBER_OF_SEQ_CAT = 4 +POSITIVE_CAT = NUMBER_OF_SEQ_CAT - 1 +#NEGATIVE_CAT = 0 + +class SingleByteCharSetProber(CharSetProber): + def __init__(self, model, reversed=constants.False, nameProber=None): + CharSetProber.__init__(self) + self._mModel = model + self._mReversed = reversed # TRUE if we need to reverse every pair in the model lookup + self._mNameProber = nameProber # Optional auxiliary prober for name decision + self.reset() + + def reset(self): + CharSetProber.reset(self) + self._mLastOrder = 255 # char order of last character + self._mSeqCounters = [0] * NUMBER_OF_SEQ_CAT + self._mTotalSeqs = 0 + self._mTotalChar = 0 + self._mFreqChar = 0 # characters that fall in our sampling range + + def get_charset_name(self): + if self._mNameProber: + return self._mNameProber.get_charset_name() + else: + return self._mModel['charsetName'] + + def feed(self, aBuf): + if not self._mModel['keepEnglishLetter']: + aBuf = self.filter_without_english_letters(aBuf) + aLen = len(aBuf) + if not aLen: + return self.get_state() + for c in aBuf: + order = self._mModel['charToOrderMap'][ord(c)] + if order < SYMBOL_CAT_ORDER: + self._mTotalChar += 1 + if order < SAMPLE_SIZE: + self._mFreqChar += 1 + if self._mLastOrder < SAMPLE_SIZE: + self._mTotalSeqs += 1 + if not self._mReversed: + self._mSeqCounters[self._mModel['precedenceMatrix'][(self._mLastOrder * SAMPLE_SIZE) + order]] += 1 + else: # reverse the order of the letters in the lookup + self._mSeqCounters[self._mModel['precedenceMatrix'][(order * SAMPLE_SIZE) + self._mLastOrder]] += 1 + self._mLastOrder = order + + if self.get_state() == constants.eDetecting: + if self._mTotalSeqs > SB_ENOUGH_REL_THRESHOLD: + cf = self.get_confidence() + if cf > POSITIVE_SHORTCUT_THRESHOLD: + if constants._debug: + sys.stderr.write('%s confidence = %s, we have a winner\n' % (self._mModel['charsetName'], cf)) + self._mState = constants.eFoundIt + elif cf < NEGATIVE_SHORTCUT_THRESHOLD: + if constants._debug: + sys.stderr.write('%s confidence = %s, below negative shortcut threshhold %s\n' % (self._mModel['charsetName'], cf, NEGATIVE_SHORTCUT_THRESHOLD)) + self._mState = constants.eNotMe + + return self.get_state() + + def get_confidence(self): + r = 0.01 + if self._mTotalSeqs > 0: +# print self._mSeqCounters[POSITIVE_CAT], self._mTotalSeqs, self._mModel['mTypicalPositiveRatio'] + r = (1.0 * self._mSeqCounters[POSITIVE_CAT]) / self._mTotalSeqs / self._mModel['mTypicalPositiveRatio'] +# print r, self._mFreqChar, self._mTotalChar + r = r * self._mFreqChar / self._mTotalChar + if r >= 1.0: + r = 0.99 + return r diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/sbcsgroupprober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/sbcsgroupprober.py new file mode 100755 index 0000000..d19160c --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/sbcsgroupprober.py @@ -0,0 +1,64 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants, sys +from charsetgroupprober import CharSetGroupProber +from sbcharsetprober import SingleByteCharSetProber +from langcyrillicmodel import Win1251CyrillicModel, Koi8rModel, Latin5CyrillicModel, MacCyrillicModel, Ibm866Model, Ibm855Model +from langgreekmodel import Latin7GreekModel, Win1253GreekModel +from langbulgarianmodel import Latin5BulgarianModel, Win1251BulgarianModel +from langhungarianmodel import Latin2HungarianModel, Win1250HungarianModel +from langthaimodel import TIS620ThaiModel +from langhebrewmodel import Win1255HebrewModel +from hebrewprober import HebrewProber + +class SBCSGroupProber(CharSetGroupProber): + def __init__(self): + CharSetGroupProber.__init__(self) + self._mProbers = [ \ + SingleByteCharSetProber(Win1251CyrillicModel), + SingleByteCharSetProber(Koi8rModel), + SingleByteCharSetProber(Latin5CyrillicModel), + SingleByteCharSetProber(MacCyrillicModel), + SingleByteCharSetProber(Ibm866Model), + SingleByteCharSetProber(Ibm855Model), + SingleByteCharSetProber(Latin7GreekModel), + SingleByteCharSetProber(Win1253GreekModel), + SingleByteCharSetProber(Latin5BulgarianModel), + SingleByteCharSetProber(Win1251BulgarianModel), + SingleByteCharSetProber(Latin2HungarianModel), + SingleByteCharSetProber(Win1250HungarianModel), + SingleByteCharSetProber(TIS620ThaiModel), + ] + hebrewProber = HebrewProber() + logicalHebrewProber = SingleByteCharSetProber(Win1255HebrewModel, constants.False, hebrewProber) + visualHebrewProber = SingleByteCharSetProber(Win1255HebrewModel, constants.True, hebrewProber) + hebrewProber.set_model_probers(logicalHebrewProber, visualHebrewProber) + self._mProbers.extend([hebrewProber, logicalHebrewProber, visualHebrewProber]) + + self.reset() diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/sjisprober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/sjisprober.py new file mode 100755 index 0000000..fea2690 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/sjisprober.py @@ -0,0 +1,85 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from mbcharsetprober import MultiByteCharSetProber +from codingstatemachine import CodingStateMachine +from chardistribution import SJISDistributionAnalysis +from jpcntx import SJISContextAnalysis +from mbcssm import SJISSMModel +import constants, sys +from constants import eStart, eError, eItsMe + +class SJISProber(MultiByteCharSetProber): + def __init__(self): + MultiByteCharSetProber.__init__(self) + self._mCodingSM = CodingStateMachine(SJISSMModel) + self._mDistributionAnalyzer = SJISDistributionAnalysis() + self._mContextAnalyzer = SJISContextAnalysis() + self.reset() + + def reset(self): + MultiByteCharSetProber.reset(self) + self._mContextAnalyzer.reset() + + def get_charset_name(self): + return "SHIFT_JIS" + + def feed(self, aBuf): + aLen = len(aBuf) + for i in range(0, aLen): + codingState = self._mCodingSM.next_state(aBuf[i]) + if codingState == eError: + if constants._debug: + sys.stderr.write(self.get_charset_name() + ' prober hit error at byte ' + str(i) + '\n') + self._mState = constants.eNotMe + break + elif codingState == eItsMe: + self._mState = constants.eFoundIt + break + elif codingState == eStart: + charLen = self._mCodingSM.get_current_charlen() + if i == 0: + self._mLastChar[1] = aBuf[0] + self._mContextAnalyzer.feed(self._mLastChar[2 - charLen :], charLen) + self._mDistributionAnalyzer.feed(self._mLastChar, charLen) + else: + self._mContextAnalyzer.feed(aBuf[i + 1 - charLen : i + 3 - charLen], charLen) + self._mDistributionAnalyzer.feed(aBuf[i - 1 : i + 1], charLen) + + self._mLastChar[0] = aBuf[aLen - 1] + + if self.get_state() == constants.eDetecting: + if self._mContextAnalyzer.got_enough_data() and \ + (self.get_confidence() > constants.SHORTCUT_THRESHOLD): + self._mState = constants.eFoundIt + + return self.get_state() + + def get_confidence(self): + contxtCf = self._mContextAnalyzer.get_confidence() + distribCf = self._mDistributionAnalyzer.get_confidence() + return max(contxtCf, distribCf) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/test.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/test.py new file mode 100755 index 0000000..12305fd --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/test.py @@ -0,0 +1,21 @@ +import sys, glob +sys.path.insert(0, '..') +from chardet.universaldetector import UniversalDetector + +count = 0 +u = UniversalDetector() +for f in glob.glob(src.argv[1]): + for f in g: + print f.ljust(60), + u.reset() + for line in file(f, 'rb'): + u.feed(line) + if u.done: break + u.close() + result = u.result + if result['encoding']: + print result['encoding'], 'with confidence', result['confidence'] + else: + print '******** no result' + count += 1 +print count, 'tests' diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/universaldetector.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/universaldetector.py new file mode 100755 index 0000000..809df22 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/universaldetector.py @@ -0,0 +1,154 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants, sys +from latin1prober import Latin1Prober # windows-1252 +from mbcsgroupprober import MBCSGroupProber # multi-byte character sets +from sbcsgroupprober import SBCSGroupProber # single-byte character sets +from escprober import EscCharSetProber # ISO-2122, etc. +import re + +MINIMUM_THRESHOLD = 0.20 +ePureAscii = 0 +eEscAscii = 1 +eHighbyte = 2 + +class UniversalDetector: + def __init__(self): + self._highBitDetector = re.compile(r'[\x80-\xFF]') + self._escDetector = re.compile(r'(\033|~{)') + self._mEscCharSetProber = None + self._mCharSetProbers = [] + self.reset() + + def reset(self): + self.result = {'encoding': None, 'confidence': 0.0} + self.done = constants.False + self._mStart = constants.True + self._mGotData = constants.False + self._mInputState = ePureAscii + self._mLastChar = '' + if self._mEscCharSetProber: + self._mEscCharSetProber.reset() + for prober in self._mCharSetProbers: + prober.reset() + + def feed(self, aBuf): + if self.done: return + + aLen = len(aBuf) + if not aLen: return + + if not self._mGotData: + # If the data starts with BOM, we know it is UTF + if aBuf[:3] == '\xEF\xBB\xBF': + # EF BB BF UTF-8 with BOM + self.result = {'encoding': "UTF-8", 'confidence': 1.0} + elif aBuf[:4] == '\xFF\xFE\x00\x00': + # FF FE 00 00 UTF-32, little-endian BOM + self.result = {'encoding': "UTF-32LE", 'confidence': 1.0} + elif aBuf[:4] == '\x00\x00\xFE\xFF': + # 00 00 FE FF UTF-32, big-endian BOM + self.result = {'encoding': "UTF-32BE", 'confidence': 1.0} + elif aBuf[:4] == '\xFE\xFF\x00\x00': + # FE FF 00 00 UCS-4, unusual octet order BOM (3412) + self.result = {'encoding': "X-ISO-10646-UCS-4-3412", 'confidence': 1.0} + elif aBuf[:4] == '\x00\x00\xFF\xFE': + # 00 00 FF FE UCS-4, unusual octet order BOM (2143) + self.result = {'encoding': "X-ISO-10646-UCS-4-2143", 'confidence': 1.0} + elif aBuf[:2] == '\xFF\xFE': + # FF FE UTF-16, little endian BOM + self.result = {'encoding': "UTF-16LE", 'confidence': 1.0} + elif aBuf[:2] == '\xFE\xFF': + # FE FF UTF-16, big endian BOM + self.result = {'encoding': "UTF-16BE", 'confidence': 1.0} + + self._mGotData = constants.True + if self.result['encoding'] and (self.result['confidence'] > 0.0): + self.done = constants.True + return + + if self._mInputState == ePureAscii: + if self._highBitDetector.search(aBuf): + self._mInputState = eHighbyte + elif (self._mInputState == ePureAscii) and self._escDetector.search(self._mLastChar + aBuf): + self._mInputState = eEscAscii + + self._mLastChar = aBuf[-1] + + if self._mInputState == eEscAscii: + if not self._mEscCharSetProber: + self._mEscCharSetProber = EscCharSetProber() + if self._mEscCharSetProber.feed(aBuf) == constants.eFoundIt: + self.result = {'encoding': self._mEscCharSetProber.get_charset_name(), + 'confidence': self._mEscCharSetProber.get_confidence()} + self.done = constants.True + elif self._mInputState == eHighbyte: + if not self._mCharSetProbers: + self._mCharSetProbers = [MBCSGroupProber(), SBCSGroupProber(), Latin1Prober()] + for prober in self._mCharSetProbers: + if prober.feed(aBuf) == constants.eFoundIt: + self.result = {'encoding': prober.get_charset_name(), + 'confidence': prober.get_confidence()} + self.done = constants.True + break + + def close(self): + if self.done: return + if not self._mGotData: + if constants._debug: + sys.stderr.write('no data received!\n') + return + self.done = constants.True + + if self._mInputState == ePureAscii: + self.result = {'encoding': 'ascii', 'confidence': 1.0} + return self.result + + if self._mInputState == eHighbyte: + proberConfidence = None + maxProberConfidence = 0.0 + maxProber = None + for prober in self._mCharSetProbers: + if not prober: continue + proberConfidence = prober.get_confidence() + if proberConfidence > maxProberConfidence: + maxProberConfidence = proberConfidence + maxProber = prober + if maxProber and (maxProberConfidence > MINIMUM_THRESHOLD): + self.result = {'encoding': maxProber.get_charset_name(), + 'confidence': maxProber.get_confidence()} + return self.result + + if constants._debug: + sys.stderr.write('no probers hit minimum threshhold\n') + for prober in self._mCharSetProbers[0].mProbers: + if not prober: continue + sys.stderr.write('%s confidence = %s\n' % \ + (prober.get_charset_name(), \ + prober.get_confidence())) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/chardet/utf8prober.py b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/utf8prober.py new file mode 100755 index 0000000..c1792bb --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/chardet/utf8prober.py @@ -0,0 +1,76 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import constants, sys +from constants import eStart, eError, eItsMe +from charsetprober import CharSetProber +from codingstatemachine import CodingStateMachine +from mbcssm import UTF8SMModel + +ONE_CHAR_PROB = 0.5 + +class UTF8Prober(CharSetProber): + def __init__(self): + CharSetProber.__init__(self) + self._mCodingSM = CodingStateMachine(UTF8SMModel) + self.reset() + + def reset(self): + CharSetProber.reset(self) + self._mCodingSM.reset() + self._mNumOfMBChar = 0 + + def get_charset_name(self): + return "utf-8" + + def feed(self, aBuf): + for c in aBuf: + codingState = self._mCodingSM.next_state(c) + if codingState == eError: + self._mState = constants.eNotMe + break + elif codingState == eItsMe: + self._mState = constants.eFoundIt + break + elif codingState == eStart: + if self._mCodingSM.get_current_charlen() >= 2: + self._mNumOfMBChar += 1 + + if self.get_state() == constants.eDetecting: + if self.get_confidence() > constants.SHORTCUT_THRESHOLD: + self._mState = constants.eFoundIt + + return self.get_state() + + def get_confidence(self): + unlike = 0.99 + if self._mNumOfMBChar < 6: + for i in range(0, self._mNumOfMBChar): + unlike = unlike * ONE_CHAR_PROB + return 1.0 - unlike + else: + return unlike diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/collections26.py b/interactive-mining-3rdparty-madis/madis/src/lib/collections26.py new file mode 100644 index 0000000..958e523 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/collections26.py @@ -0,0 +1,668 @@ +__all__ = ['Counter', 'deque', 'defaultdict', 'namedtuple', 'OrderedDict'] +# For bootstrapping reasons, the collection ABCs are defined in _abcoll.py. +# They should however be considered an integral part of collections.py. +from _abcoll import * +import _abcoll +__all__ += _abcoll.__all__ + +from _collections import deque, defaultdict +from operator import itemgetter as _itemgetter +from keyword import iskeyword as _iskeyword +import sys as _sys +import heapq as _heapq +from itertools import repeat as _repeat, chain as _chain, starmap as _starmap + +try: + from thread import get_ident as _get_ident +except ImportError: + from dummy_thread import get_ident as _get_ident + + +################################################################################ +### OrderedDict +################################################################################ + +class OrderedDict(dict): + 'Dictionary that remembers insertion order' + # An inherited dict maps keys to values. + # The inherited dict provides __getitem__, __len__, __contains__, and get. + # The remaining methods are order-aware. + # Big-O running times for all methods are the same as regular dictionaries. + + # The internal self.__map dict maps keys to links in a doubly linked list. + # The circular doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted (this simplifies the algorithm). + # Each link is stored as a list of length three: [PREV, NEXT, KEY]. + + def __init__(self, *args, **kwds): + '''Initialize an ordered dictionary. The signature is the same as + regular dictionaries, but keyword arguments are not recommended because + their insertion order is arbitrary. + + ''' + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__root + except AttributeError: + self.__root = root = [] # sentinel node + root[:] = [root, root, None] + self.__map = {} + self.__update(*args, **kwds) + + def __setitem__(self, key, value, PREV=0, NEXT=1, dict_setitem=dict.__setitem__): + 'od.__setitem__(i, y) <==> od[i]=y' + # Setting a new item creates a new link at the end of the linked list, + # and the inherited dictionary is updated with the new key/value pair. + if key not in self: + root = self.__root + last = root[PREV] + last[NEXT] = root[PREV] = self.__map[key] = [last, root, key] + dict_setitem(self, key, value) + + def __delitem__(self, key, PREV=0, NEXT=1, dict_delitem=dict.__delitem__): + 'od.__delitem__(y) <==> del od[y]' + # Deleting an existing item uses self.__map to find the link which gets + # removed by updating the links in the predecessor and successor nodes. + dict_delitem(self, key) + link_prev, link_next, key = self.__map.pop(key) + link_prev[NEXT] = link_next + link_next[PREV] = link_prev + + def __iter__(self): + 'od.__iter__() <==> iter(od)' + # Traverse the linked list in order. + NEXT, KEY = 1, 2 + root = self.__root + curr = root[NEXT] + while curr is not root: + yield curr[KEY] + curr = curr[NEXT] + + def __reversed__(self): + 'od.__reversed__() <==> reversed(od)' + # Traverse the linked list in reverse order. + PREV, KEY = 0, 2 + root = self.__root + curr = root[PREV] + while curr is not root: + yield curr[KEY] + curr = curr[PREV] + + def clear(self): + 'od.clear() -> None. Remove all items from od.' + for node in self.__map.itervalues(): + del node[:] + root = self.__root + root[:] = [root, root, None] + self.__map.clear() + dict.clear(self) + + # -- the following methods do not depend on the internal structure -- + + def keys(self): + 'od.keys() -> list of keys in od' + return list(self) + + def values(self): + 'od.values() -> list of values in od' + return [self[key] for key in self] + + def items(self): + 'od.items() -> list of (key, value) pairs in od' + return [(key, self[key]) for key in self] + + def iterkeys(self): + 'od.iterkeys() -> an iterator over the keys in od' + return iter(self) + + def itervalues(self): + 'od.itervalues -> an iterator over the values in od' + for k in self: + yield self[k] + + def iteritems(self): + 'od.iteritems -> an iterator over the (key, value) pairs in od' + for k in self: + yield (k, self[k]) + + update = MutableMapping.update + + __update = update # let subclasses override update without breaking __init__ + + __marker = object() + + def pop(self, key, default=__marker): + '''od.pop(k[,d]) -> v, remove specified key and return the corresponding + value. If key is not found, d is returned if given, otherwise KeyError + is raised. + + ''' + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + if key in self: + return self[key] + self[key] = default + return default + + def popitem(self, last=True): + '''od.popitem() -> (k, v), return and remove a (key, value) pair. + Pairs are returned in LIFO order if last is true or FIFO order if false. + + ''' + if not self: + raise KeyError('dictionary is empty') + key = next(reversed(self) if last else iter(self)) + value = self.pop(key) + return key, value + + def __repr__(self, _repr_running={}): + 'od.__repr__() <==> repr(od)' + call_key = id(self), _get_ident() + if call_key in _repr_running: + return '...' + _repr_running[call_key] = 1 + try: + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + finally: + del _repr_running[call_key] + + def __reduce__(self): + 'Return state information for pickling' + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + for k in vars(OrderedDict()): + inst_dict.pop(k, None) + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def copy(self): + 'od.copy() -> a shallow copy of od' + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S. + If not specified, the value defaults to None. + + ''' + self = cls() + for key in iterable: + self[key] = value + return self + + def __eq__(self, other): + '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + while comparison to a regular mapping is order-insensitive. + + ''' + if isinstance(other, OrderedDict): + return len(self)==len(other) and self.items() == other.items() + return dict.__eq__(self, other) + + def __ne__(self, other): + 'od.__ne__(y) <==> od!=y' + return not self == other + + # -- the following methods support python 3.x style dictionary views -- + + def viewkeys(self): + "od.viewkeys() -> a set-like object providing a view on od's keys" + return KeysView(self) + + def viewvalues(self): + "od.viewvalues() -> an object providing a view on od's values" + return ValuesView(self) + + def viewitems(self): + "od.viewitems() -> a set-like object providing a view on od's items" + return ItemsView(self) + + +################################################################################ +### namedtuple +################################################################################ + +def namedtuple(typename, field_names, verbose=False, rename=False): + """Returns a new subclass of tuple with named fields. + + >>> Point = namedtuple('Point', 'x y') + >>> Point.__doc__ # docstring for the new class + 'Point(x, y)' + >>> p = Point(11, y=22) # instantiate with positional args or keywords + >>> p[0] + p[1] # indexable like a plain tuple + 33 + >>> x, y = p # unpack like a regular tuple + >>> x, y + (11, 22) + >>> p.x + p.y # fields also accessable by name + 33 + >>> d = p._asdict() # convert to a dictionary + >>> d['x'] + 11 + >>> Point(**d) # convert from a dictionary + Point(x=11, y=22) + >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields + Point(x=100, y=22) + + """ + + # Parse and validate the field names. Validation serves two purposes, + # generating informative error messages and preventing template injection attacks. + if isinstance(field_names, basestring): + field_names = field_names.replace(',', ' ').split() # names separated by whitespace and/or commas + field_names = tuple(map(str, field_names)) + if rename: + names = list(field_names) + seen = set() + for i, name in enumerate(names): + if (not all(c.isalnum() or c=='_' for c in name) or _iskeyword(name) + or not name or name[0].isdigit() or name.startswith('_') + or name in seen): + names[i] = '_%d' % i + seen.add(name) + field_names = tuple(names) + for name in (typename,) + field_names: + if not all(c.isalnum() or c=='_' for c in name): + raise ValueError('Type names and field names can only contain alphanumeric characters and underscores: %r' % name) + if _iskeyword(name): + raise ValueError('Type names and field names cannot be a keyword: %r' % name) + if name[0].isdigit(): + raise ValueError('Type names and field names cannot start with a number: %r' % name) + seen_names = set() + for name in field_names: + if name.startswith('_') and not rename: + raise ValueError('Field names cannot start with an underscore: %r' % name) + if name in seen_names: + raise ValueError('Encountered duplicate field name: %r' % name) + seen_names.add(name) + + # Create and fill-in the class template + numfields = len(field_names) + argtxt = repr(field_names).replace("'", "")[1:-1] # tuple repr without parens or quotes + reprtxt = ', '.join('%s=%%r' % name for name in field_names) + template = '''class %(typename)s(tuple): + '%(typename)s(%(argtxt)s)' \n + __slots__ = () \n + _fields = %(field_names)r \n + def __new__(_cls, %(argtxt)s): + 'Create new instance of %(typename)s(%(argtxt)s)' + return _tuple.__new__(_cls, (%(argtxt)s)) \n + @classmethod + def _make(cls, iterable, new=tuple.__new__, len=len): + 'Make a new %(typename)s object from a sequence or iterable' + result = new(cls, iterable) + if len(result) != %(numfields)d: + raise TypeError('Expected %(numfields)d arguments, got %%d' %% len(result)) + return result \n + def __repr__(self): + 'Return a nicely formatted representation string' + return '%(typename)s(%(reprtxt)s)' %% self \n + def _asdict(self): + 'Return a new OrderedDict which maps field names to their values' + return OrderedDict(zip(self._fields, self)) \n + __dict__ = property(_asdict) \n + def _replace(_self, **kwds): + 'Return a new %(typename)s object replacing specified fields with new values' + result = _self._make(map(kwds.pop, %(field_names)r, _self)) + if kwds: + raise ValueError('Got unexpected field names: %%r' %% kwds.keys()) + return result \n + def __getnewargs__(self): + 'Return self as a plain tuple. Used by copy and pickle.' + return tuple(self) \n\n''' % locals() + for i, name in enumerate(field_names): + template += " %s = _property(_itemgetter(%d), doc='Alias for field number %d')\n" % (name, i, i) + if verbose: + print template + + # Execute the template string in a temporary namespace and + # support tracing utilities by setting a value for frame.f_globals['__name__'] + namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename, + OrderedDict=OrderedDict, _property=property, _tuple=tuple) + try: + exec template in namespace + except SyntaxError, e: + raise SyntaxError(e.message + ':\n' + template) + result = namespace[typename] + + # For pickling to work, the __module__ variable needs to be set to the frame + # where the named tuple is created. Bypass this step in enviroments where + # sys._getframe is not defined (Jython for example) or sys._getframe is not + # defined for arguments greater than 0 (IronPython). + try: + result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__') + except (AttributeError, ValueError): + pass + + return result + + +######################################################################## +### Counter +######################################################################## + +class Counter(dict): + '''Dict subclass for counting hashable items. Sometimes called a bag + or multiset. Elements are stored as dictionary keys and their counts + are stored as dictionary values. + + >>> c = Counter('abcdeabcdabcaba') # count elements from a string + + >>> c.most_common(3) # three most common elements + [('a', 5), ('b', 4), ('c', 3)] + >>> sorted(c) # list all unique elements + ['a', 'b', 'c', 'd', 'e'] + >>> ''.join(sorted(c.elements())) # list elements with repetitions + 'aaaaabbbbcccdde' + >>> sum(c.values()) # total of all counts + 15 + + >>> c['a'] # count of letter 'a' + 5 + >>> for elem in 'shazam': # update counts from an iterable + ... c[elem] += 1 # by adding 1 to each element's count + >>> c['a'] # now there are seven 'a' + 7 + >>> del c['b'] # remove all 'b' + >>> c['b'] # now there are zero 'b' + 0 + + >>> d = Counter('simsalabim') # make another counter + >>> c.update(d) # add in the second counter + >>> c['a'] # now there are nine 'a' + 9 + + >>> c.clear() # empty the counter + >>> c + Counter() + + Note: If a count is set to zero or reduced to zero, it will remain + in the counter until the entry is deleted or the counter is cleared: + + >>> c = Counter('aaabbc') + >>> c['b'] -= 2 # reduce the count of 'b' by two + >>> c.most_common() # 'b' is still in, but its count is zero + [('a', 3), ('c', 1), ('b', 0)] + + ''' + # References: + # http://en.wikipedia.org/wiki/Multiset + # http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html + # http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm + # http://code.activestate.com/recipes/259174/ + # Knuth, TAOCP Vol. II section 4.6.3 + + def __init__(self, iterable=None, **kwds): + '''Create a new, empty Counter object. And if given, count elements + from an input iterable. Or, initialize the count from another mapping + of elements to their counts. + + >>> c = Counter() # a new, empty counter + >>> c = Counter('gallahad') # a new counter from an iterable + >>> c = Counter({'a': 4, 'b': 2}) # a new counter from a mapping + >>> c = Counter(a=4, b=2) # a new counter from keyword args + + ''' + super(Counter, self).__init__() + self.update(iterable, **kwds) + + def __missing__(self, key): + 'The count of elements not in the Counter is zero.' + # Needed so that self[missing_item] does not raise KeyError + return 0 + + def most_common(self, n=None): + '''List the n most common elements and their counts from the most + common to the least. If n is None, then list all element counts. + + >>> Counter('abcdeabcdabcaba').most_common(3) + [('a', 5), ('b', 4), ('c', 3)] + + ''' + # Emulate Bag.sortedByCount from Smalltalk + if n is None: + return sorted(self.iteritems(), key=_itemgetter(1), reverse=True) + return _heapq.nlargest(n, self.iteritems(), key=_itemgetter(1)) + + def elements(self): + '''Iterator over elements repeating each as many times as its count. + + >>> c = Counter('ABCABC') + >>> sorted(c.elements()) + ['A', 'A', 'B', 'B', 'C', 'C'] + + # Knuth's example for prime factors of 1836: 2**2 * 3**3 * 17**1 + >>> prime_factors = Counter({2: 2, 3: 3, 17: 1}) + >>> product = 1 + >>> for factor in prime_factors.elements(): # loop over factors + ... product *= factor # and multiply them + >>> product + 1836 + + Note, if an element's count has been set to zero or is a negative + number, elements() will ignore it. + + ''' + # Emulate Bag.do from Smalltalk and Multiset.begin from C++. + return _chain.from_iterable(_starmap(_repeat, self.iteritems())) + + # Override dict methods where necessary + + @classmethod + def fromkeys(cls, iterable, v=None): + # There is no equivalent method for counters because setting v=1 + # means that no element can have a count greater than one. + raise NotImplementedError( + 'Counter.fromkeys() is undefined. Use Counter(iterable) instead.') + + def update(self, iterable=None, **kwds): + '''Like dict.update() but add counts instead of replacing them. + + Source can be an iterable, a dictionary, or another Counter instance. + + >>> c = Counter('which') + >>> c.update('witch') # add elements from another iterable + >>> d = Counter('watch') + >>> c.update(d) # add elements from another counter + >>> c['h'] # four 'h' in which, witch, and watch + 4 + + ''' + # The regular dict.update() operation makes no sense here because the + # replace behavior results in the some of original untouched counts + # being mixed-in with all of the other counts for a mismash that + # doesn't have a straight-forward interpretation in most counting + # contexts. Instead, we implement straight-addition. Both the inputs + # and outputs are allowed to contain zero and negative counts. + + if iterable is not None: + if isinstance(iterable, Mapping): + if self: + self_get = self.get + for elem, count in iterable.iteritems(): + self[elem] = self_get(elem, 0) + count + else: + super(Counter, self).update(iterable) # fast path when counter is empty + else: + self_get = self.get + for elem in iterable: + self[elem] = self_get(elem, 0) + 1 + if kwds: + self.update(kwds) + + def subtract(self, iterable=None, **kwds): + '''Like dict.update() but subtracts counts instead of replacing them. + Counts can be reduced below zero. Both the inputs and outputs are + allowed to contain zero and negative counts. + + Source can be an iterable, a dictionary, or another Counter instance. + + >>> c = Counter('which') + >>> c.subtract('witch') # subtract elements from another iterable + >>> c.subtract(Counter('watch')) # subtract elements from another counter + >>> c['h'] # 2 in which, minus 1 in witch, minus 1 in watch + 0 + >>> c['w'] # 1 in which, minus 1 in witch, minus 1 in watch + -1 + + ''' + if iterable is not None: + self_get = self.get + if isinstance(iterable, Mapping): + for elem, count in iterable.items(): + self[elem] = self_get(elem, 0) - count + else: + for elem in iterable: + self[elem] = self_get(elem, 0) - 1 + if kwds: + self.subtract(kwds) + + def copy(self): + 'Return a shallow copy.' + return self.__class__(self) + + def __reduce__(self): + return self.__class__, (dict(self),) + + def __delitem__(self, elem): + 'Like dict.__delitem__() but does not raise KeyError for missing values.' + if elem in self: + super(Counter, self).__delitem__(elem) + + def __repr__(self): + if not self: + return '%s()' % self.__class__.__name__ + items = ', '.join(map('%r: %r'.__mod__, self.most_common())) + return '%s({%s})' % (self.__class__.__name__, items) + + # Multiset-style mathematical operations discussed in: + # Knuth TAOCP Volume II section 4.6.3 exercise 19 + # and at http://en.wikipedia.org/wiki/Multiset + # + # Outputs guaranteed to only include positive counts. + # + # To strip negative and zero counts, add-in an empty counter: + # c += Counter() + + def __add__(self, other): + '''Add counts from two counters. + + >>> Counter('abbb') + Counter('bcc') + Counter({'b': 4, 'c': 2, 'a': 1}) + + ''' + if not isinstance(other, Counter): + return NotImplemented + result = Counter() + for elem, count in self.items(): + newcount = count + other[elem] + if newcount > 0: + result[elem] = newcount + for elem, count in other.items(): + if elem not in self and count > 0: + result[elem] = count + return result + + def __sub__(self, other): + ''' Subtract count, but keep only results with positive counts. + + >>> Counter('abbbc') - Counter('bccd') + Counter({'b': 2, 'a': 1}) + + ''' + if not isinstance(other, Counter): + return NotImplemented + result = Counter() + for elem, count in self.items(): + newcount = count - other[elem] + if newcount > 0: + result[elem] = newcount + for elem, count in other.items(): + if elem not in self and count < 0: + result[elem] = 0 - count + return result + + def __or__(self, other): + '''Union is the maximum of value in either of the input counters. + + >>> Counter('abbb') | Counter('bcc') + Counter({'b': 3, 'c': 2, 'a': 1}) + + ''' + if not isinstance(other, Counter): + return NotImplemented + result = Counter() + for elem, count in self.items(): + other_count = other[elem] + newcount = other_count if count < other_count else count + if newcount > 0: + result[elem] = newcount + for elem, count in other.items(): + if elem not in self and count > 0: + result[elem] = count + return result + + def __and__(self, other): + ''' Intersection is the minimum of corresponding counts. + + >>> Counter('abbb') & Counter('bcc') + Counter({'b': 1}) + + ''' + if not isinstance(other, Counter): + return NotImplemented + result = Counter() + for elem, count in self.items(): + other_count = other[elem] + newcount = count if count < other_count else other_count + if newcount > 0: + result[elem] = newcount + return result + + +if __name__ == '__main__': + # verify that instances can be pickled + from cPickle import loads, dumps + Point = namedtuple('Point', 'x, y', True) + p = Point(x=10, y=20) + assert p == loads(dumps(p)) + + # test and demonstrate ability to override methods + class Point(namedtuple('Point', 'x y')): + __slots__ = () + @property + def hypot(self): + return (self.x ** 2 + self.y ** 2) ** 0.5 + def __str__(self): + return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot) + + for p in Point(3, 4), Point(14, 5/7.): + print p + + class Point(namedtuple('Point', 'x y')): + 'Point class with optimized _make() and _replace() without error-checking' + __slots__ = () + _make = classmethod(tuple.__new__) + def _replace(self, _map=map, **kwds): + return self._make(_map(kwds.get, ('x', 'y'), self)) + + print Point(11, 22)._replace(x=100) + + Point3D = namedtuple('Point3D', Point._fields + ('z',)) + print Point3D.__doc__ + + import doctest + TestResults = namedtuple('TestResults', 'failed attempted') + print TestResults(*doctest.testmod()) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/colorama/LICENSE.txt b/interactive-mining-3rdparty-madis/madis/src/lib/colorama/LICENSE.txt new file mode 100644 index 0000000..b746447 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/colorama/LICENSE.txt @@ -0,0 +1,33 @@ +Copyright (c) 2010 Jonathan Hartley + +Released under the New BSD license (reproduced below), or alternatively you may +use this software under any OSI approved open source license such as those at +http://opensource.org/licenses/alphabetical + +All rights reserved. + +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(s) of the copyright holders, nor those 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 HOLDER 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. + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/colorama/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/colorama/__init__.py new file mode 100644 index 0000000..c5d780a --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/colorama/__init__.py @@ -0,0 +1,6 @@ +from .initialise import init, deinit, reinit +from .ansi import Fore, Back, Style +from .ansitowin32 import AnsiToWin32 + +VERSION = '0.2.4' + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/colorama/ansi.py b/interactive-mining-3rdparty-madis/madis/src/lib/colorama/ansi.py new file mode 100644 index 0000000..7b818e1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/colorama/ansi.py @@ -0,0 +1,49 @@ +''' +This module generates ANSI character codes to printing colors to terminals. +See: http://en.wikipedia.org/wiki/ANSI_escape_code +''' + +CSI = '\033[' + +def code_to_chars(code): + return CSI + str(code) + 'm' + +class AnsiCodes(object): + def __init__(self, codes): + for name in dir(codes): + if not name.startswith('_'): + value = getattr(codes, name) + setattr(self, name, code_to_chars(value)) + +class AnsiFore: + BLACK = 30 + RED = 31 + GREEN = 32 + YELLOW = 33 + BLUE = 34 + MAGENTA = 35 + CYAN = 36 + WHITE = 37 + RESET = 39 + +class AnsiBack: + BLACK = 40 + RED = 41 + GREEN = 42 + YELLOW = 43 + BLUE = 44 + MAGENTA = 45 + CYAN = 46 + WHITE = 47 + RESET = 49 + +class AnsiStyle: + BRIGHT = 1 + DIM = 2 + NORMAL = 22 + RESET_ALL = 0 + +Fore = AnsiCodes( AnsiFore ) +Back = AnsiCodes( AnsiBack ) +Style = AnsiCodes( AnsiStyle ) + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/colorama/ansitowin32.py b/interactive-mining-3rdparty-madis/madis/src/lib/colorama/ansitowin32.py new file mode 100644 index 0000000..a85ce49 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/colorama/ansitowin32.py @@ -0,0 +1,182 @@ + +import re +import sys + +from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style +from .winterm import WinTerm, WinColor, WinStyle +from .win32 import windll + + +if windll is not None: + winterm = WinTerm() + + +def is_a_tty(stream): + return hasattr(stream, 'isatty') and stream.isatty() + + +class StreamWrapper(object): + ''' + Wraps a stream (such as stdout), acting as a transparent proxy for all + attribute access apart from method 'write()', which is delegated to our + Converter instance. + ''' + def __init__(self, wrapped, converter): + # double-underscore everything to prevent clashes with names of + # attributes on the wrapped stream object. + self.__wrapped = wrapped + self.__convertor = converter + + def __getattr__(self, name): + return getattr(self.__wrapped, name) + + def write(self, text): + self.__convertor.write(text) + + +class AnsiToWin32(object): + ''' + Implements a 'write()' method which, on Windows, will strip ANSI character + sequences from the text, and if outputting to a tty, will convert them into + win32 function calls. + ''' + ANSI_RE = re.compile('\033\[((?:\d|;)*)([a-zA-Z])') + + def __init__(self, wrapped, convert=None, strip=None, autoreset=False): + # The wrapped stream (normally sys.stdout or sys.stderr) + self.wrapped = wrapped + + # should we reset colors to defaults after every .write() + self.autoreset = autoreset + + # create the proxy wrapping our output stream + self.stream = StreamWrapper(wrapped, self) + + on_windows = sys.platform.startswith('win') + + # should we strip ANSI sequences from our output? + if strip is None: + strip = on_windows + self.strip = strip + + # should we should convert ANSI sequences into win32 calls? + if convert is None: + convert = on_windows and is_a_tty(wrapped) + self.convert = convert + + # dict of ansi codes to win32 functions and parameters + self.win32_calls = self.get_win32_calls() + + # are we wrapping stderr? + self.on_stderr = self.wrapped is sys.stderr + + + def should_wrap(self): + ''' + True if this class is actually needed. If false, then the output + stream will not be affected, nor will win32 calls be issued, so + wrapping stdout is not actually required. This will generally be + False on non-Windows platforms, unless optional functionality like + autoreset has been requested using kwargs to init() + ''' + return self.convert or self.strip or self.autoreset + + + def get_win32_calls(self): + if self.convert and winterm: + return { + AnsiStyle.RESET_ALL: (winterm.reset_all, ), + AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), + AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), + AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), + AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), + AnsiFore.RED: (winterm.fore, WinColor.RED), + AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), + AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), + AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), + AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), + AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), + AnsiFore.WHITE: (winterm.fore, WinColor.GREY), + AnsiFore.RESET: (winterm.fore, ), + AnsiBack.BLACK: (winterm.back, WinColor.BLACK), + AnsiBack.RED: (winterm.back, WinColor.RED), + AnsiBack.GREEN: (winterm.back, WinColor.GREEN), + AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), + AnsiBack.BLUE: (winterm.back, WinColor.BLUE), + AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), + AnsiBack.CYAN: (winterm.back, WinColor.CYAN), + AnsiBack.WHITE: (winterm.back, WinColor.GREY), + AnsiBack.RESET: (winterm.back, ), + } + + + def write(self, text): + if self.strip or self.convert: + self.write_and_convert(text) + else: + self.wrapped.write(text) + self.wrapped.flush() + if self.autoreset: + self.reset_all() + + + def reset_all(self): + if self.convert: + self.call_win32('m', (0,)) + elif is_a_tty(self.wrapped): + self.wrapped.write(Style.RESET_ALL) + + + def write_and_convert(self, text): + ''' + Write the given text to our wrapped stream, stripping any ANSI + sequences from the text, and optionally converting them into win32 + calls. + ''' + cursor = 0 + for match in self.ANSI_RE.finditer(text): + start, end = match.span() + self.write_plain_text(text, cursor, start) + self.convert_ansi(*match.groups()) + cursor = end + self.write_plain_text(text, cursor, len(text)) + + + def write_plain_text(self, text, start, end): + if start < end: + self.wrapped.write(text[start:end]) + self.wrapped.flush() + + + def convert_ansi(self, paramstring, command): + if self.convert: + params = self.extract_params(paramstring) + self.call_win32(command, params) + + + def extract_params(self, paramstring): + def split(paramstring): + for p in paramstring.split(';'): + if p != '': + yield int(p) + return tuple(split(paramstring)) + + + def call_win32(self, command, params): + if params == []: + params = [0] + if command == 'm': + for param in params: + if param in self.win32_calls: + func_args = self.win32_calls[param] + func = func_args[0] + args = func_args[1:] + kwargs = dict(on_stderr=self.on_stderr) + func(*args, **kwargs) + elif command in ('H', 'f'): # set cursor position + func = winterm.set_cursor_position + func(params, on_stderr=self.on_stderr) + elif command in ('J'): + func = winterm.erase_data + func(params, on_stderr=self.on_stderr) + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/colorama/initialise.py b/interactive-mining-3rdparty-madis/madis/src/lib/colorama/initialise.py new file mode 100644 index 0000000..e54f8a8 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/colorama/initialise.py @@ -0,0 +1,55 @@ +import atexit +import sys + +from .ansitowin32 import AnsiToWin32 + + +orig_stdout = sys.stdout +orig_stderr = sys.stderr + +wrapped_stdout = sys.stdout +wrapped_stderr = sys.stderr + +atexit_done = False + + +def reset_all(): + AnsiToWin32(orig_stdout).reset_all() + + +def init(autoreset=False, convert=None, strip=None, wrap=True): + + if not wrap and any([autoreset, convert, strip]): + raise ValueError('wrap=False conflicts with any other arg=True') + + global wrapped_stdout, wrapped_stderr + sys.stdout = wrapped_stdout = \ + wrap_stream(orig_stdout, convert, strip, autoreset, wrap) + sys.stderr = wrapped_stderr = \ + wrap_stream(orig_stderr, convert, strip, autoreset, wrap) + + global atexit_done + if not atexit_done: + atexit.register(reset_all) + atexit_done = True + + +def deinit(): + sys.stdout = orig_stdout + sys.stderr = orig_stderr + + +def reinit(): + sys.stdout = wrapped_stdout + sys.stderr = wrapped_stdout + + +def wrap_stream(stream, convert, strip, autoreset, wrap): + if wrap: + wrapper = AnsiToWin32(stream, + convert=convert, strip=strip, autoreset=autoreset) + if wrapper.should_wrap(): + stream = wrapper.stream + return stream + + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/colorama/win32.py b/interactive-mining-3rdparty-madis/madis/src/lib/colorama/win32.py new file mode 100644 index 0000000..5911761 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/colorama/win32.py @@ -0,0 +1,109 @@ + +# from winbase.h +STDOUT = -11 +STDERR = -12 + +try: + from ctypes import windll +except ImportError: + windll = None + SetConsoleTextAttribute = lambda *_: None +else: + from ctypes import ( + byref, Structure, c_char, c_short, c_uint32, c_ushort + ) + + handles = { + STDOUT: windll.kernel32.GetStdHandle(STDOUT), + STDERR: windll.kernel32.GetStdHandle(STDERR), + } + + SHORT = c_short + WORD = c_ushort + DWORD = c_uint32 + TCHAR = c_char + + class COORD(Structure): + """struct in wincon.h""" + _fields_ = [ + ('X', SHORT), + ('Y', SHORT), + ] + + class SMALL_RECT(Structure): + """struct in wincon.h.""" + _fields_ = [ + ("Left", SHORT), + ("Top", SHORT), + ("Right", SHORT), + ("Bottom", SHORT), + ] + + class CONSOLE_SCREEN_BUFFER_INFO(Structure): + """struct in wincon.h.""" + _fields_ = [ + ("dwSize", COORD), + ("dwCursorPosition", COORD), + ("wAttributes", WORD), + ("srWindow", SMALL_RECT), + ("dwMaximumWindowSize", COORD), + ] + def __str__(self): + return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( + self.dwSize.Y, self.dwSize.X + , self.dwCursorPosition.Y, self.dwCursorPosition.X + , self.wAttributes + , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right + , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X + ) + + def GetConsoleScreenBufferInfo(stream_id=STDOUT): + handle = handles[stream_id] + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = windll.kernel32.GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return csbi + + + def SetConsoleTextAttribute(stream_id, attrs): + handle = handles[stream_id] + return windll.kernel32.SetConsoleTextAttribute(handle, attrs) + + + def SetConsoleCursorPosition(stream_id, position): + position = COORD(*position) + # If the position is out of range, do nothing. + if position.Y <= 0 or position.X <= 0: + return + # Adjust for Windows' SetConsoleCursorPosition: + # 1. being 0-based, while ANSI is 1-based. + # 2. expecting (x,y), while ANSI uses (y,x). + adjusted_position = COORD(position.Y - 1, position.X - 1) + # Adjust for viewport's scroll position + sr = GetConsoleScreenBufferInfo(STDOUT).srWindow + adjusted_position.Y += sr.Top + adjusted_position.X += sr.Left + # Resume normal processing + handle = handles[stream_id] + return windll.kernel32.SetConsoleCursorPosition(handle, adjusted_position) + + def FillConsoleOutputCharacter(stream_id, char, length, start): + handle = handles[stream_id] + char = TCHAR(char) + length = DWORD(length) + num_written = DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + success = windll.kernel32.FillConsoleOutputCharacterA( + handle, char, length, start, byref(num_written)) + return num_written.value + + def FillConsoleOutputAttribute(stream_id, attr, length, start): + ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' + handle = handles[stream_id] + attribute = WORD(attr) + length = DWORD(length) + num_written = DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + return windll.kernel32.FillConsoleOutputAttribute( + handle, attribute, length, start, byref(num_written)) + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/colorama/winterm.py b/interactive-mining-3rdparty-madis/madis/src/lib/colorama/winterm.py new file mode 100644 index 0000000..362f932 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/colorama/winterm.py @@ -0,0 +1,102 @@ + +from . import win32 + + +# from wincon.h +class WinColor(object): + BLACK = 0 + BLUE = 1 + GREEN = 2 + CYAN = 3 + RED = 4 + MAGENTA = 5 + YELLOW = 6 + GREY = 7 + +# from wincon.h +class WinStyle(object): + NORMAL = 0x00 # dim text, dim background + BRIGHT = 0x08 # bright text, dim background + + +class WinTerm(object): + + def __init__(self): + self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes + self.set_attrs(self._default) + self._default_fore = self._fore + self._default_back = self._back + self._default_style = self._style + + def get_attrs(self): + return self._fore + self._back * 16 + self._style + + def set_attrs(self, value): + self._fore = value & 7 + self._back = (value >> 4) & 7 + self._style = value & WinStyle.BRIGHT + + def reset_all(self, on_stderr=None): + self.set_attrs(self._default) + self.set_console(attrs=self._default) + + def fore(self, fore=None, on_stderr=False): + if fore is None: + fore = self._default_fore + self._fore = fore + self.set_console(on_stderr=on_stderr) + + def back(self, back=None, on_stderr=False): + if back is None: + back = self._default_back + self._back = back + self.set_console(on_stderr=on_stderr) + + def style(self, style=None, on_stderr=False): + if style is None: + style = self._default_style + self._style = style + self.set_console(on_stderr=on_stderr) + + def set_console(self, attrs=None, on_stderr=False): + if attrs is None: + attrs = self.get_attrs() + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleTextAttribute(handle, attrs) + + def set_cursor_position(self, position=None, on_stderr=False): + if position is None: + #I'm not currently tracking the position, so there is no default. + #position = self.get_position() + return + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleCursorPosition(handle, position) + + def erase_data(self, mode=0, on_stderr=False): + # 0 (or None) should clear from the cursor to the end of the screen. + # 1 should clear from the cursor to the beginning of the screen. + # 2 should clear the entire screen. (And maybe move cursor to (1,1)?) + # + # At the moment, I only support mode 2. From looking at the API, it + # should be possible to calculate a different number of bytes to clear, + # and to do so relative to the cursor position. + if mode[0] not in (2,): + return + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + # here's where we'll home the cursor + coord_screen = win32.COORD(0,0) + csbi = win32.GetConsoleScreenBufferInfo(handle) + # get the number of character cells in the current buffer + dw_con_size = csbi.dwSize.X * csbi.dwSize.Y + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ord(' '), dw_con_size, coord_screen) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), dw_con_size, coord_screen ); + # put the cursor at (0, 0) + win32.SetConsoleCursorPosition(handle, (coord_screen.X, coord_screen.Y)) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/conutils.py b/interactive-mining-3rdparty-madis/madis/src/lib/conutils.py new file mode 100644 index 0000000..c55eb0e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/conutils.py @@ -0,0 +1,9 @@ +def optimized_cursor(connection,type='sqlite'): + if type=='sqlite': + cursor=connection.cursor() + cursor.execute('PRAGMA count_changes=OFF') + cursor.execute('PRAGMA page_cache=100000') + cursor.execute('PRAGMA page_size=32768') + cursor.execute('PRAGMA synchronous=1') + cursor.execute('PRAGMA journal_mode=PERSIST') + return cursor diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/LICENSE b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/LICENSE new file mode 100644 index 0000000..c5b5923 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/LICENSE @@ -0,0 +1,259 @@ +A. HISTORY OF THE SOFTWARE +========================== + +Python was created in the early 1990s by Guido van Rossum at Stichting +Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands +as a successor of a language called ABC. Guido remains Python's +principal author, although it includes many contributions from others. + +In 1995, Guido continued his work on Python at the Corporation for +National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) +in Reston, Virginia where he released several versions of the +software. + +In May 2000, Guido and the Python core development team moved to +BeOpen.com to form the BeOpen PythonLabs team. In October of the same +year, the PythonLabs team moved to Digital Creations (now Zope +Corporation, see http://www.zope.com). In 2001, the Python Software +Foundation (PSF, see http://www.python.org/psf/) was formed, a +non-profit organization created specifically to own Python-related +Intellectual Property. Zope Corporation is a sponsoring member of +the PSF. + +All Python releases are Open Source (see http://www.opensource.org for +the Open Source Definition). Historically, most, but not all, Python +releases have also been GPL-compatible; the table below summarizes +the various releases. + + Release Derived Year Owner GPL- + from compatible? (1) + + 0.9.0 thru 1.2 1991-1995 CWI yes + 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes + 1.6 1.5.2 2000 CNRI no + 2.0 1.6 2000 BeOpen.com no + 1.6.1 1.6 2001 CNRI yes (2) + 2.1 2.0+1.6.1 2001 PSF no + 2.0.1 2.0+1.6.1 2001 PSF yes + 2.1.1 2.1+2.0.1 2001 PSF yes + 2.2 2.1.1 2001 PSF yes + 2.1.2 2.1.1 2002 PSF yes + 2.1.3 2.1.2 2002 PSF yes + 2.2.1 2.2 2002 PSF yes + 2.2.2 2.2.1 2002 PSF yes + 2.2.3 2.2.2 2003 PSF yes + 2.3 2.2.2 2002-2003 PSF yes + +Footnotes: + +(1) GPL-compatible doesn't mean that we're distributing Python under + the GPL. All Python licenses, unlike the GPL, let you distribute + a modified version without making your changes open source. The + GPL-compatible licenses make it possible to combine Python with + other software that is released under the GPL; the others don't. + +(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, + because its license has a choice of law clause. According to + CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 + is "not incompatible" with the GPL. + +Thanks to the many outside volunteers who have worked under Guido's +direction to make these releases possible. + + +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON +=============================================================== + +PSF LICENSE AGREEMENT FOR PYTHON 2.3 +------------------------------------ + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using Python 2.3 software in source or binary form and its +associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 2.3 +alone or in any derivative version, provided, however, that PSF's +License Agreement and PSF's notice of copyright, i.e., "Copyright (c) +2001, 2002, 2003 Python Software Foundation; All Rights Reserved" are +retained in Python 2.3 alone or in any derivative version prepared by +Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 2.3 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 2.3. + +4. PSF is making Python 2.3 available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.3 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +2.3 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.3, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python 2.3, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 +------------------------------------------- + +BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 + +1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an +office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the +Individual or Organization ("Licensee") accessing and otherwise using +this software in source or binary form and its associated +documentation ("the Software"). + +2. Subject to the terms and conditions of this BeOpen Python License +Agreement, BeOpen hereby grants Licensee a non-exclusive, +royalty-free, world-wide license to reproduce, analyze, test, perform +and/or display publicly, prepare derivative works, distribute, and +otherwise use the Software alone or in any derivative version, +provided, however, that the BeOpen Python License is retained in the +Software, alone or in any derivative version prepared by Licensee. + +3. BeOpen is making the Software available to Licensee on an "AS IS" +basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE +SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS +AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY +DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +5. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +6. This License Agreement shall be governed by and interpreted in all +respects by the law of the State of California, excluding conflict of +law provisions. Nothing in this License Agreement shall be deemed to +create any relationship of agency, partnership, or joint venture +between BeOpen and Licensee. This License Agreement does not grant +permission to use BeOpen trademarks or trade names in a trademark +sense to endorse or promote products or services of Licensee, or any +third party. As an exception, the "BeOpen Python" logos available at +http://www.pythonlabs.com/logos.html may be used according to the +permissions granted on that web page. + +7. By copying, installing or otherwise using the software, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 +--------------------------------------- + +1. This LICENSE AGREEMENT is between the Corporation for National +Research Initiatives, having an office at 1895 Preston White Drive, +Reston, VA 20191 ("CNRI"), and the Individual or Organization +("Licensee") accessing and otherwise using Python 1.6.1 software in +source or binary form and its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, CNRI +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 1.6.1 +alone or in any derivative version, provided, however, that CNRI's +License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) +1995-2001 Corporation for National Research Initiatives; All Rights +Reserved" are retained in Python 1.6.1 alone or in any derivative +version prepared by Licensee. Alternately, in lieu of CNRI's License +Agreement, Licensee may substitute the following text (omitting the +quotes): "Python 1.6.1 is made available subject to the terms and +conditions in CNRI's License Agreement. This Agreement together with +Python 1.6.1 may be located on the Internet using the following +unique, persistent identifier (known as a handle): 1895.22/1013. This +Agreement may also be obtained from a proxy server on the Internet +using the following URL: http://hdl.handle.net/1895.22/1013". + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 1.6.1 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 1.6.1. + +4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" +basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. This License Agreement shall be governed by the federal +intellectual property law of the United States, including without +limitation the federal copyright law, and, to the extent such +U.S. federal law does not apply, by the law of the Commonwealth of +Virginia, excluding Virginia's conflict of law provisions. +Notwithstanding the foregoing, with regard to derivative works based +on Python 1.6.1 that incorporate non-separable material that was +previously distributed under the GNU General Public License (GPL), the +law of the Commonwealth of Virginia shall govern this License +Agreement only as to issues arising under or with respect to +Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this +License Agreement shall be deemed to create any relationship of +agency, partnership, or joint venture between CNRI and Licensee. This +License Agreement does not grant permission to use CNRI trademarks or +trade name in a trademark sense to endorse or promote products or +services of Licensee, or any third party. + +8. By clicking on the "ACCEPT" button where indicated, or by copying, +installing or otherwise using Python 1.6.1, Licensee agrees to be +bound by the terms and conditions of this License Agreement. + + ACCEPT + + +CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 +-------------------------------------------------- + +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, +The Netherlands. All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/__init__.py new file mode 100644 index 0000000..290814c --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/__init__.py @@ -0,0 +1,9 @@ +""" +Copyright (c) 2003-2010 Gustavo Niemeyer + +This module offers extensions to the standard python 2.3+ +datetime module. +""" +__author__ = "Gustavo Niemeyer " +__license__ = "PSF License" +__version__ = "1.5" diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/easter.py b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/easter.py new file mode 100644 index 0000000..d794410 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/easter.py @@ -0,0 +1,92 @@ +""" +Copyright (c) 2003-2007 Gustavo Niemeyer + +This module offers extensions to the standard python 2.3+ +datetime module. +""" +__author__ = "Gustavo Niemeyer " +__license__ = "PSF License" + +import datetime + +__all__ = ["easter", "EASTER_JULIAN", "EASTER_ORTHODOX", "EASTER_WESTERN"] + +EASTER_JULIAN = 1 +EASTER_ORTHODOX = 2 +EASTER_WESTERN = 3 + +def easter(year, method=EASTER_WESTERN): + """ + This method was ported from the work done by GM Arts, + on top of the algorithm by Claus Tondering, which was + based in part on the algorithm of Ouding (1940), as + quoted in "Explanatory Supplement to the Astronomical + Almanac", P. Kenneth Seidelmann, editor. + + This algorithm implements three different easter + calculation methods: + + 1 - Original calculation in Julian calendar, valid in + dates after 326 AD + 2 - Original method, with date converted to Gregorian + calendar, valid in years 1583 to 4099 + 3 - Revised method, in Gregorian calendar, valid in + years 1583 to 4099 as well + + These methods are represented by the constants: + + EASTER_JULIAN = 1 + EASTER_ORTHODOX = 2 + EASTER_WESTERN = 3 + + The default method is method 3. + + More about the algorithm may be found at: + + http://users.chariot.net.au/~gmarts/eastalg.htm + + and + + http://www.tondering.dk/claus/calendar.html + + """ + + if not (1 <= method <= 3): + raise ValueError, "invalid method" + + # g - Golden year - 1 + # c - Century + # h - (23 - Epact) mod 30 + # i - Number of days from March 21 to Paschal Full Moon + # j - Weekday for PFM (0=Sunday, etc) + # p - Number of days from March 21 to Sunday on or before PFM + # (-6 to 28 methods 1 & 3, to 56 for method 2) + # e - Extra days to add for method 2 (converting Julian + # date to Gregorian date) + + y = year + g = y % 19 + e = 0 + if method < 3: + # Old method + i = (19*g+15)%30 + j = (y+y//4+i)%7 + if method == 2: + # Extra dates to convert Julian to Gregorian date + e = 10 + if y > 1600: + e = e+y//100-16-(y//100-16)//4 + else: + # New method + c = y//100 + h = (c-c//4-(8*c+13)//25+19*g+15)%30 + i = h-(h//28)*(1-(h//28)*(29//(h+1))*((21-g)//11)) + j = (y+y//4+i+2-c+c//4)%7 + + # p can be from -6 to 56 corresponding to dates 22 March to 23 May + # (later dates apply to method 2, although 23 May never actually occurs) + p = i-j+e + d = 1+(p+27+(p+6)//40)%31 + m = 3+(p+26)//30 + return datetime.date(int(y),int(m),int(d)) + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/parser.py b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/parser.py new file mode 100644 index 0000000..5d824e4 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/parser.py @@ -0,0 +1,886 @@ +# -*- coding:iso-8859-1 -*- +""" +Copyright (c) 2003-2007 Gustavo Niemeyer + +This module offers extensions to the standard python 2.3+ +datetime module. +""" +__author__ = "Gustavo Niemeyer " +__license__ = "PSF License" + +import datetime +import string +import time +import sys +import os + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + +import relativedelta +import tz + + +__all__ = ["parse", "parserinfo"] + + +# Some pointers: +# +# http://www.cl.cam.ac.uk/~mgk25/iso-time.html +# http://www.iso.ch/iso/en/prods-services/popstds/datesandtime.html +# http://www.w3.org/TR/NOTE-datetime +# http://ringmaster.arc.nasa.gov/tools/time_formats.html +# http://search.cpan.org/author/MUIR/Time-modules-2003.0211/lib/Time/ParseDate.pm +# http://stein.cshl.org/jade/distrib/docs/java.text.SimpleDateFormat.html + + +class _timelex(object): + + def __init__(self, instream): + if isinstance(instream, basestring): + instream = StringIO(instream) + self.instream = instream + self.wordchars = ('abcdfeghijklmnopqrstuvwxyz' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_' + 'ßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ' + 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ') + self.numchars = '0123456789' + self.whitespace = ' \t\r\n' + self.charstack = [] + self.tokenstack = [] + self.eof = False + + def get_token(self): + if self.tokenstack: + return self.tokenstack.pop(0) + seenletters = False + token = None + state = None + wordchars = self.wordchars + numchars = self.numchars + whitespace = self.whitespace + while not self.eof: + if self.charstack: + nextchar = self.charstack.pop(0) + else: + nextchar = self.instream.read(1) + while nextchar == '\x00': + nextchar = self.instream.read(1) + if not nextchar: + self.eof = True + break + elif not state: + token = nextchar + if nextchar in wordchars: + state = 'a' + elif nextchar in numchars: + state = '0' + elif nextchar in whitespace: + token = ' ' + break # emit token + else: + break # emit token + elif state == 'a': + seenletters = True + if nextchar in wordchars: + token += nextchar + elif nextchar == '.': + token += nextchar + state = 'a.' + else: + self.charstack.append(nextchar) + break # emit token + elif state == '0': + if nextchar in numchars: + token += nextchar + elif nextchar == '.': + token += nextchar + state = '0.' + else: + self.charstack.append(nextchar) + break # emit token + elif state == 'a.': + seenletters = True + if nextchar == '.' or nextchar in wordchars: + token += nextchar + elif nextchar in numchars and token[-1] == '.': + token += nextchar + state = '0.' + else: + self.charstack.append(nextchar) + break # emit token + elif state == '0.': + if nextchar == '.' or nextchar in numchars: + token += nextchar + elif nextchar in wordchars and token[-1] == '.': + token += nextchar + state = 'a.' + else: + self.charstack.append(nextchar) + break # emit token + if (state in ('a.', '0.') and + (seenletters or token.count('.') > 1 or token[-1] == '.')): + l = token.split('.') + token = l[0] + for tok in l[1:]: + self.tokenstack.append('.') + if tok: + self.tokenstack.append(tok) + return token + + def __iter__(self): + return self + + def next(self): + token = self.get_token() + if token is None: + raise StopIteration + return token + + def split(cls, s): + return list(cls(s)) + split = classmethod(split) + + +class _resultbase(object): + + def __init__(self): + for attr in self.__slots__: + setattr(self, attr, None) + + def _repr(self, classname): + l = [] + for attr in self.__slots__: + value = getattr(self, attr) + if value is not None: + l.append("%s=%s" % (attr, `value`)) + return "%s(%s)" % (classname, ", ".join(l)) + + def __repr__(self): + return self._repr(self.__class__.__name__) + + +class parserinfo(object): + + # m from a.m/p.m, t from ISO T separator + JUMP = [" ", ".", ",", ";", "-", "/", "'", + "at", "on", "and", "ad", "m", "t", "of", + "st", "nd", "rd", "th"] + + WEEKDAYS = [("Mon", "Monday"), + ("Tue", "Tuesday"), + ("Wed", "Wednesday"), + ("Thu", "Thursday"), + ("Fri", "Friday"), + ("Sat", "Saturday"), + ("Sun", "Sunday")] + MONTHS = [("Jan", "January"), + ("Feb", "February"), + ("Mar", "March"), + ("Apr", "April"), + ("May", "May"), + ("Jun", "June"), + ("Jul", "July"), + ("Aug", "August"), + ("Sep", "September"), + ("Oct", "October"), + ("Nov", "November"), + ("Dec", "December")] + HMS = [("h", "hour", "hours"), + ("m", "minute", "minutes"), + ("s", "second", "seconds")] + AMPM = [("am", "a"), + ("pm", "p")] + UTCZONE = ["UTC", "GMT", "Z"] + PERTAIN = ["of"] + TZOFFSET = {} + + def __init__(self, dayfirst=False, yearfirst=False): + self._jump = self._convert(self.JUMP) + self._weekdays = self._convert(self.WEEKDAYS) + self._months = self._convert(self.MONTHS) + self._hms = self._convert(self.HMS) + self._ampm = self._convert(self.AMPM) + self._utczone = self._convert(self.UTCZONE) + self._pertain = self._convert(self.PERTAIN) + + self.dayfirst = dayfirst + self.yearfirst = yearfirst + + self._year = time.localtime().tm_year + self._century = self._year//100*100 + + def _convert(self, lst): + dct = {} + for i in range(len(lst)): + v = lst[i] + if isinstance(v, tuple): + for v in v: + dct[v.lower()] = i + else: + dct[v.lower()] = i + return dct + + def jump(self, name): + return name.lower() in self._jump + + def weekday(self, name): + if len(name) >= 3: + try: + return self._weekdays[name.lower()] + except KeyError: + pass + return None + + def month(self, name): + if len(name) >= 3: + try: + return self._months[name.lower()]+1 + except KeyError: + pass + return None + + def hms(self, name): + try: + return self._hms[name.lower()] + except KeyError: + return None + + def ampm(self, name): + try: + return self._ampm[name.lower()] + except KeyError: + return None + + def pertain(self, name): + return name.lower() in self._pertain + + def utczone(self, name): + return name.lower() in self._utczone + + def tzoffset(self, name): + if name in self._utczone: + return 0 + return self.TZOFFSET.get(name) + + def convertyear(self, year): + if year < 100: + year += self._century + if abs(year-self._year) >= 50: + if year < self._year: + year += 100 + else: + year -= 100 + return year + + def validate(self, res): + # move to info + if res.year is not None: + res.year = self.convertyear(res.year) + if res.tzoffset == 0 and not res.tzname or res.tzname == 'Z': + res.tzname = "UTC" + res.tzoffset = 0 + elif res.tzoffset != 0 and res.tzname and self.utczone(res.tzname): + res.tzoffset = 0 + return True + + +class parser(object): + + def __init__(self, info=None): + self.info = info or parserinfo() + + def parse(self, timestr, default=None, + ignoretz=False, tzinfos=None, + **kwargs): + if not default: + default = datetime.datetime.now().replace(hour=0, minute=0, + second=0, microsecond=0) + res = self._parse(timestr, **kwargs) + if res is None: + raise ValueError, "unknown string format" + repl = {} + for attr in ["year", "month", "day", "hour", + "minute", "second", "microsecond"]: + value = getattr(res, attr) + if value is not None: + repl[attr] = value + ret = default.replace(**repl) + if res.weekday is not None and not res.day: + ret = ret+relativedelta.relativedelta(weekday=res.weekday) + if not ignoretz: + if callable(tzinfos) or tzinfos and res.tzname in tzinfos: + if callable(tzinfos): + tzdata = tzinfos(res.tzname, res.tzoffset) + else: + tzdata = tzinfos.get(res.tzname) + if isinstance(tzdata, datetime.tzinfo): + tzinfo = tzdata + elif isinstance(tzdata, basestring): + tzinfo = tz.tzstr(tzdata) + elif isinstance(tzdata, int): + tzinfo = tz.tzoffset(res.tzname, tzdata) + else: + raise ValueError, "offset must be tzinfo subclass, " \ + "tz string, or int offset" + ret = ret.replace(tzinfo=tzinfo) + elif res.tzname and res.tzname in time.tzname: + ret = ret.replace(tzinfo=tz.tzlocal()) + elif res.tzoffset == 0: + ret = ret.replace(tzinfo=tz.tzutc()) + elif res.tzoffset: + ret = ret.replace(tzinfo=tz.tzoffset(res.tzname, res.tzoffset)) + return ret + + class _result(_resultbase): + __slots__ = ["year", "month", "day", "weekday", + "hour", "minute", "second", "microsecond", + "tzname", "tzoffset"] + + def _parse(self, timestr, dayfirst=None, yearfirst=None, fuzzy=False): + info = self.info + if dayfirst is None: + dayfirst = info.dayfirst + if yearfirst is None: + yearfirst = info.yearfirst + res = self._result() + l = _timelex.split(timestr) + try: + + # year/month/day list + ymd = [] + + # Index of the month string in ymd + mstridx = -1 + + len_l = len(l) + i = 0 + while i < len_l: + + # Check if it's a number + try: + value_repr = l[i] + value = float(value_repr) + except ValueError: + value = None + + if value is not None: + # Token is a number + len_li = len(l[i]) + i += 1 + if (len(ymd) == 3 and len_li in (2, 4) + and (i >= len_l or (l[i] != ':' and + info.hms(l[i]) is None))): + # 19990101T23[59] + s = l[i-1] + res.hour = int(s[:2]) + if len_li == 4: + res.minute = int(s[2:]) + elif len_li == 6 or (len_li > 6 and l[i-1].find('.') == 6): + # YYMMDD or HHMMSS[.ss] + s = l[i-1] + if not ymd and l[i-1].find('.') == -1: + ymd.append(info.convertyear(int(s[:2]))) + ymd.append(int(s[2:4])) + ymd.append(int(s[4:])) + else: + # 19990101T235959[.59] + res.hour = int(s[:2]) + res.minute = int(s[2:4]) + res.second, res.microsecond = _parsems(s[4:]) + elif len_li == 8: + # YYYYMMDD + s = l[i-1] + ymd.append(int(s[:4])) + ymd.append(int(s[4:6])) + ymd.append(int(s[6:])) + elif len_li in (12, 14): + # YYYYMMDDhhmm[ss] + s = l[i-1] + ymd.append(int(s[:4])) + ymd.append(int(s[4:6])) + ymd.append(int(s[6:8])) + res.hour = int(s[8:10]) + res.minute = int(s[10:12]) + if len_li == 14: + res.second = int(s[12:]) + elif ((i < len_l and info.hms(l[i]) is not None) or + (i+1 < len_l and l[i] == ' ' and + info.hms(l[i+1]) is not None)): + # HH[ ]h or MM[ ]m or SS[.ss][ ]s + if l[i] == ' ': + i += 1 + idx = info.hms(l[i]) + while True: + if idx == 0: + res.hour = int(value) + if value%1: + res.minute = int(60*(value%1)) + elif idx == 1: + res.minute = int(value) + if value%1: + res.second = int(60*(value%1)) + elif idx == 2: + res.second, res.microsecond = \ + _parsems(value_repr) + i += 1 + if i >= len_l or idx == 2: + break + # 12h00 + try: + value_repr = l[i] + value = float(value_repr) + except ValueError: + break + else: + i += 1 + idx += 1 + if i < len_l: + newidx = info.hms(l[i]) + if newidx is not None: + idx = newidx + elif i+1 < len_l and l[i] == ':': + # HH:MM[:SS[.ss]] + res.hour = int(value) + i += 1 + value = float(l[i]) + res.minute = int(value) + if value%1: + res.second = int(60*(value%1)) + i += 1 + if i < len_l and l[i] == ':': + res.second, res.microsecond = _parsems(l[i+1]) + i += 2 + elif i < len_l and l[i] in ('-', '/', '.'): + sep = l[i] + ymd.append(int(value)) + i += 1 + if i < len_l and not info.jump(l[i]): + try: + # 01-01[-01] + ymd.append(int(l[i])) + except ValueError: + # 01-Jan[-01] + value = info.month(l[i]) + if value is not None: + ymd.append(value) + assert mstridx == -1 + mstridx = len(ymd)-1 + else: + return None + i += 1 + if i < len_l and l[i] == sep: + # We have three members + i += 1 + value = info.month(l[i]) + if value is not None: + ymd.append(value) + mstridx = len(ymd)-1 + assert mstridx == -1 + else: + ymd.append(int(l[i])) + i += 1 + elif i >= len_l or info.jump(l[i]): + if i+1 < len_l and info.ampm(l[i+1]) is not None: + # 12 am + res.hour = int(value) + if res.hour < 12 and info.ampm(l[i+1]) == 1: + res.hour += 12 + elif res.hour == 12 and info.ampm(l[i+1]) == 0: + res.hour = 0 + i += 1 + else: + # Year, month or day + ymd.append(int(value)) + i += 1 + elif info.ampm(l[i]) is not None: + # 12am + res.hour = int(value) + if res.hour < 12 and info.ampm(l[i]) == 1: + res.hour += 12 + elif res.hour == 12 and info.ampm(l[i]) == 0: + res.hour = 0 + i += 1 + elif not fuzzy: + return None + else: + i += 1 + continue + + # Check weekday + value = info.weekday(l[i]) + if value is not None: + res.weekday = value + i += 1 + continue + + # Check month name + value = info.month(l[i]) + if value is not None: + ymd.append(value) + assert mstridx == -1 + mstridx = len(ymd)-1 + i += 1 + if i < len_l: + if l[i] in ('-', '/'): + # Jan-01[-99] + sep = l[i] + i += 1 + ymd.append(int(l[i])) + i += 1 + if i < len_l and l[i] == sep: + # Jan-01-99 + i += 1 + ymd.append(int(l[i])) + i += 1 + elif (i+3 < len_l and l[i] == l[i+2] == ' ' + and info.pertain(l[i+1])): + # Jan of 01 + # In this case, 01 is clearly year + try: + value = int(l[i+3]) + except ValueError: + # Wrong guess + pass + else: + # Convert it here to become unambiguous + ymd.append(info.convertyear(value)) + i += 4 + continue + + # Check am/pm + value = info.ampm(l[i]) + if value is not None: + if value == 1 and res.hour < 12: + res.hour += 12 + elif value == 0 and res.hour == 12: + res.hour = 0 + i += 1 + continue + + # Check for a timezone name + if (res.hour is not None and len(l[i]) <= 5 and + res.tzname is None and res.tzoffset is None and + not [x for x in l[i] if x not in string.ascii_uppercase]): + res.tzname = l[i] + res.tzoffset = info.tzoffset(res.tzname) + i += 1 + + # Check for something like GMT+3, or BRST+3. Notice + # that it doesn't mean "I am 3 hours after GMT", but + # "my time +3 is GMT". If found, we reverse the + # logic so that timezone parsing code will get it + # right. + if i < len_l and l[i] in ('+', '-'): + l[i] = ('+', '-')[l[i] == '+'] + res.tzoffset = None + if info.utczone(res.tzname): + # With something like GMT+3, the timezone + # is *not* GMT. + res.tzname = None + + continue + + # Check for a numbered timezone + if res.hour is not None and l[i] in ('+', '-'): + signal = (-1,1)[l[i] == '+'] + i += 1 + len_li = len(l[i]) + if len_li == 4: + # -0300 + res.tzoffset = int(l[i][:2])*3600+int(l[i][2:])*60 + elif i+1 < len_l and l[i+1] == ':': + # -03:00 + res.tzoffset = int(l[i])*3600+int(l[i+2])*60 + i += 2 + elif len_li <= 2: + # -[0]3 + res.tzoffset = int(l[i][:2])*3600 + else: + return None + i += 1 + res.tzoffset *= signal + + # Look for a timezone name between parenthesis + if (i+3 < len_l and + info.jump(l[i]) and l[i+1] == '(' and l[i+3] == ')' and + 3 <= len(l[i+2]) <= 5 and + not [x for x in l[i+2] + if x not in string.ascii_uppercase]): + # -0300 (BRST) + res.tzname = l[i+2] + i += 4 + continue + + # Check jumps + if not (info.jump(l[i]) or fuzzy): + return None + + i += 1 + + # Process year/month/day + len_ymd = len(ymd) + if len_ymd > 3: + # More than three members!? + return None + elif len_ymd == 1 or (mstridx != -1 and len_ymd == 2): + # One member, or two members with a month string + if mstridx != -1: + res.month = ymd[mstridx] + del ymd[mstridx] + if len_ymd > 1 or mstridx == -1: + if ymd[0] > 31: + res.year = ymd[0] + else: + res.day = ymd[0] + elif len_ymd == 2: + # Two members with numbers + if ymd[0] > 31: + # 99-01 + res.year, res.month = ymd + elif ymd[1] > 31: + # 01-99 + res.month, res.year = ymd + elif dayfirst and ymd[1] <= 12: + # 13-01 + res.day, res.month = ymd + else: + # 01-13 + res.month, res.day = ymd + if len_ymd == 3: + # Three members + if mstridx == 0: + res.month, res.day, res.year = ymd + elif mstridx == 1: + if ymd[0] > 31 or (yearfirst and ymd[2] <= 31): + # 99-Jan-01 + res.year, res.month, res.day = ymd + else: + # 01-Jan-01 + # Give precendence to day-first, since + # two-digit years is usually hand-written. + res.day, res.month, res.year = ymd + elif mstridx == 2: + # WTF!? + if ymd[1] > 31: + # 01-99-Jan + res.day, res.year, res.month = ymd + else: + # 99-01-Jan + res.year, res.day, res.month = ymd + else: + if ymd[0] > 31 or \ + (yearfirst and ymd[1] <= 12 and ymd[2] <= 31): + # 99-01-01 + res.year, res.month, res.day = ymd + elif ymd[0] > 12 or (dayfirst and ymd[1] <= 12): + # 13-01-01 + res.day, res.month, res.year = ymd + else: + # 01-13-01 + res.month, res.day, res.year = ymd + + except (IndexError, ValueError, AssertionError): + return None + + if not info.validate(res): + return None + return res + +DEFAULTPARSER = parser() +def parse(timestr, parserinfo=None, **kwargs): + if parserinfo: + return parser(parserinfo).parse(timestr, **kwargs) + else: + return DEFAULTPARSER.parse(timestr, **kwargs) + + +class _tzparser(object): + + class _result(_resultbase): + + __slots__ = ["stdabbr", "stdoffset", "dstabbr", "dstoffset", + "start", "end"] + + class _attr(_resultbase): + __slots__ = ["month", "week", "weekday", + "yday", "jyday", "day", "time"] + + def __repr__(self): + return self._repr("") + + def __init__(self): + _resultbase.__init__(self) + self.start = self._attr() + self.end = self._attr() + + def parse(self, tzstr): + res = self._result() + l = _timelex.split(tzstr) + try: + + len_l = len(l) + + i = 0 + while i < len_l: + # BRST+3[BRDT[+2]] + j = i + while j < len_l and not [x for x in l[j] + if x in "0123456789:,-+"]: + j += 1 + if j != i: + if not res.stdabbr: + offattr = "stdoffset" + res.stdabbr = "".join(l[i:j]) + else: + offattr = "dstoffset" + res.dstabbr = "".join(l[i:j]) + i = j + if (i < len_l and + (l[i] in ('+', '-') or l[i][0] in "0123456789")): + if l[i] in ('+', '-'): + # Yes, that's right. See the TZ variable + # documentation. + signal = (1,-1)[l[i] == '+'] + i += 1 + else: + signal = -1 + len_li = len(l[i]) + if len_li == 4: + # -0300 + setattr(res, offattr, + (int(l[i][:2])*3600+int(l[i][2:])*60)*signal) + elif i+1 < len_l and l[i+1] == ':': + # -03:00 + setattr(res, offattr, + (int(l[i])*3600+int(l[i+2])*60)*signal) + i += 2 + elif len_li <= 2: + # -[0]3 + setattr(res, offattr, + int(l[i][:2])*3600*signal) + else: + return None + i += 1 + if res.dstabbr: + break + else: + break + + if i < len_l: + for j in range(i, len_l): + if l[j] == ';': l[j] = ',' + + assert l[i] == ',' + + i += 1 + + if i >= len_l: + pass + elif (8 <= l.count(',') <= 9 and + not [y for x in l[i:] if x != ',' + for y in x if y not in "0123456789"]): + # GMT0BST,3,0,30,3600,10,0,26,7200[,3600] + for x in (res.start, res.end): + x.month = int(l[i]) + i += 2 + if l[i] == '-': + value = int(l[i+1])*-1 + i += 1 + else: + value = int(l[i]) + i += 2 + if value: + x.week = value + x.weekday = (int(l[i])-1)%7 + else: + x.day = int(l[i]) + i += 2 + x.time = int(l[i]) + i += 2 + if i < len_l: + if l[i] in ('-','+'): + signal = (-1,1)[l[i] == "+"] + i += 1 + else: + signal = 1 + res.dstoffset = (res.stdoffset+int(l[i]))*signal + elif (l.count(',') == 2 and l[i:].count('/') <= 2 and + not [y for x in l[i:] if x not in (',','/','J','M', + '.','-',':') + for y in x if y not in "0123456789"]): + for x in (res.start, res.end): + if l[i] == 'J': + # non-leap year day (1 based) + i += 1 + x.jyday = int(l[i]) + elif l[i] == 'M': + # month[-.]week[-.]weekday + i += 1 + x.month = int(l[i]) + i += 1 + assert l[i] in ('-', '.') + i += 1 + x.week = int(l[i]) + if x.week == 5: + x.week = -1 + i += 1 + assert l[i] in ('-', '.') + i += 1 + x.weekday = (int(l[i])-1)%7 + else: + # year day (zero based) + x.yday = int(l[i])+1 + + i += 1 + + if i < len_l and l[i] == '/': + i += 1 + # start time + len_li = len(l[i]) + if len_li == 4: + # -0300 + x.time = (int(l[i][:2])*3600+int(l[i][2:])*60) + elif i+1 < len_l and l[i+1] == ':': + # -03:00 + x.time = int(l[i])*3600+int(l[i+2])*60 + i += 2 + if i+1 < len_l and l[i+1] == ':': + i += 2 + x.time += int(l[i]) + elif len_li <= 2: + # -[0]3 + x.time = (int(l[i][:2])*3600) + else: + return None + i += 1 + + assert i == len_l or l[i] == ',' + + i += 1 + + assert i >= len_l + + except (IndexError, ValueError, AssertionError): + return None + + return res + + +DEFAULTTZPARSER = _tzparser() +def _parsetz(tzstr): + return DEFAULTTZPARSER.parse(tzstr) + + +def _parsems(value): + """Parse a I[.F] seconds value into (seconds, microseconds).""" + if "." not in value: + return int(value), 0 + else: + i, f = value.split(".") + return int(i), int(f.ljust(6, "0")[:6]) + + +# vim:ts=4:sw=4:et diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/relativedelta.py b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/relativedelta.py new file mode 100644 index 0000000..0c72a81 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/relativedelta.py @@ -0,0 +1,432 @@ +""" +Copyright (c) 2003-2010 Gustavo Niemeyer + +This module offers extensions to the standard python 2.3+ +datetime module. +""" +__author__ = "Gustavo Niemeyer " +__license__ = "PSF License" + +import datetime +import calendar + +__all__ = ["relativedelta", "MO", "TU", "WE", "TH", "FR", "SA", "SU"] + +class weekday(object): + __slots__ = ["weekday", "n"] + + def __init__(self, weekday, n=None): + self.weekday = weekday + self.n = n + + def __call__(self, n): + if n == self.n: + return self + else: + return self.__class__(self.weekday, n) + + def __eq__(self, other): + try: + if self.weekday != other.weekday or self.n != other.n: + return False + except AttributeError: + return False + return True + + def __repr__(self): + s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday] + if not self.n: + return s + else: + return "%s(%+d)" % (s, self.n) + +MO, TU, WE, TH, FR, SA, SU = weekdays = tuple([weekday(x) for x in range(7)]) + +class relativedelta: + """ +The relativedelta type is based on the specification of the excelent +work done by M.-A. Lemburg in his mx.DateTime extension. However, +notice that this type does *NOT* implement the same algorithm as +his work. Do *NOT* expect it to behave like mx.DateTime's counterpart. + +There's two different ways to build a relativedelta instance. The +first one is passing it two date/datetime classes: + + relativedelta(datetime1, datetime2) + +And the other way is to use the following keyword arguments: + + year, month, day, hour, minute, second, microsecond: + Absolute information. + + years, months, weeks, days, hours, minutes, seconds, microseconds: + Relative information, may be negative. + + weekday: + One of the weekday instances (MO, TU, etc). These instances may + receive a parameter N, specifying the Nth weekday, which could + be positive or negative (like MO(+1) or MO(-2). Not specifying + it is the same as specifying +1. You can also use an integer, + where 0=MO. + + leapdays: + Will add given days to the date found, if year is a leap + year, and the date found is post 28 of february. + + yearday, nlyearday: + Set the yearday or the non-leap year day (jump leap days). + These are converted to day/month/leapdays information. + +Here is the behavior of operations with relativedelta: + +1) Calculate the absolute year, using the 'year' argument, or the + original datetime year, if the argument is not present. + +2) Add the relative 'years' argument to the absolute year. + +3) Do steps 1 and 2 for month/months. + +4) Calculate the absolute day, using the 'day' argument, or the + original datetime day, if the argument is not present. Then, + subtract from the day until it fits in the year and month + found after their operations. + +5) Add the relative 'days' argument to the absolute day. Notice + that the 'weeks' argument is multiplied by 7 and added to + 'days'. + +6) Do steps 1 and 2 for hour/hours, minute/minutes, second/seconds, + microsecond/microseconds. + +7) If the 'weekday' argument is present, calculate the weekday, + with the given (wday, nth) tuple. wday is the index of the + weekday (0-6, 0=Mon), and nth is the number of weeks to add + forward or backward, depending on its signal. Notice that if + the calculated date is already Monday, for example, using + (0, 1) or (0, -1) won't change the day. + """ + + def __init__(self, dt1=None, dt2=None, + years=0, months=0, days=0, leapdays=0, weeks=0, + hours=0, minutes=0, seconds=0, microseconds=0, + year=None, month=None, day=None, weekday=None, + yearday=None, nlyearday=None, + hour=None, minute=None, second=None, microsecond=None): + if dt1 and dt2: + if not isinstance(dt1, datetime.date) or \ + not isinstance(dt2, datetime.date): + raise TypeError, "relativedelta only diffs datetime/date" + if type(dt1) is not type(dt2): + if not isinstance(dt1, datetime.datetime): + dt1 = datetime.datetime.fromordinal(dt1.toordinal()) + elif not isinstance(dt2, datetime.datetime): + dt2 = datetime.datetime.fromordinal(dt2.toordinal()) + self.years = 0 + self.months = 0 + self.days = 0 + self.leapdays = 0 + self.hours = 0 + self.minutes = 0 + self.seconds = 0 + self.microseconds = 0 + self.year = None + self.month = None + self.day = None + self.weekday = None + self.hour = None + self.minute = None + self.second = None + self.microsecond = None + self._has_time = 0 + + months = (dt1.year*12+dt1.month)-(dt2.year*12+dt2.month) + self._set_months(months) + dtm = self.__radd__(dt2) + if dt1 < dt2: + while dt1 > dtm: + months += 1 + self._set_months(months) + dtm = self.__radd__(dt2) + else: + while dt1 < dtm: + months -= 1 + self._set_months(months) + dtm = self.__radd__(dt2) + delta = dt1 - dtm + self.seconds = delta.seconds+delta.days*86400 + self.microseconds = delta.microseconds + else: + self.years = years + self.months = months + self.days = days+weeks*7 + self.leapdays = leapdays + self.hours = hours + self.minutes = minutes + self.seconds = seconds + self.microseconds = microseconds + self.year = year + self.month = month + self.day = day + self.hour = hour + self.minute = minute + self.second = second + self.microsecond = microsecond + + if type(weekday) is int: + self.weekday = weekdays[weekday] + else: + self.weekday = weekday + + yday = 0 + if nlyearday: + yday = nlyearday + elif yearday: + yday = yearday + if yearday > 59: + self.leapdays = -1 + if yday: + ydayidx = [31,59,90,120,151,181,212,243,273,304,334,366] + for idx, ydays in enumerate(ydayidx): + if yday <= ydays: + self.month = idx+1 + if idx == 0: + self.day = yday + else: + self.day = yday-ydayidx[idx-1] + break + else: + raise ValueError, "invalid year day (%d)" % yday + + self._fix() + + def _fix(self): + if abs(self.microseconds) > 999999: + s = self.microseconds//abs(self.microseconds) + div, mod = divmod(self.microseconds*s, 1000000) + self.microseconds = mod*s + self.seconds += div*s + if abs(self.seconds) > 59: + s = self.seconds//abs(self.seconds) + div, mod = divmod(self.seconds*s, 60) + self.seconds = mod*s + self.minutes += div*s + if abs(self.minutes) > 59: + s = self.minutes//abs(self.minutes) + div, mod = divmod(self.minutes*s, 60) + self.minutes = mod*s + self.hours += div*s + if abs(self.hours) > 23: + s = self.hours//abs(self.hours) + div, mod = divmod(self.hours*s, 24) + self.hours = mod*s + self.days += div*s + if abs(self.months) > 11: + s = self.months//abs(self.months) + div, mod = divmod(self.months*s, 12) + self.months = mod*s + self.years += div*s + if (self.hours or self.minutes or self.seconds or self.microseconds or + self.hour is not None or self.minute is not None or + self.second is not None or self.microsecond is not None): + self._has_time = 1 + else: + self._has_time = 0 + + def _set_months(self, months): + self.months = months + if abs(self.months) > 11: + s = self.months//abs(self.months) + div, mod = divmod(self.months*s, 12) + self.months = mod*s + self.years = div*s + else: + self.years = 0 + + def __radd__(self, other): + if not isinstance(other, datetime.date): + raise TypeError, "unsupported type for add operation" + elif self._has_time and not isinstance(other, datetime.datetime): + other = datetime.datetime.fromordinal(other.toordinal()) + year = (self.year or other.year)+self.years + month = self.month or other.month + if self.months: + assert 1 <= abs(self.months) <= 12 + month += self.months + if month > 12: + year += 1 + month -= 12 + elif month < 1: + year -= 1 + month += 12 + day = min(calendar.monthrange(year, month)[1], + self.day or other.day) + repl = {"year": year, "month": month, "day": day} + for attr in ["hour", "minute", "second", "microsecond"]: + value = getattr(self, attr) + if value is not None: + repl[attr] = value + days = self.days + if self.leapdays and month > 2 and calendar.isleap(year): + days += self.leapdays + ret = (other.replace(**repl) + + datetime.timedelta(days=days, + hours=self.hours, + minutes=self.minutes, + seconds=self.seconds, + microseconds=self.microseconds)) + if self.weekday: + weekday, nth = self.weekday.weekday, self.weekday.n or 1 + jumpdays = (abs(nth)-1)*7 + if nth > 0: + jumpdays += (7-ret.weekday()+weekday)%7 + else: + jumpdays += (ret.weekday()-weekday)%7 + jumpdays *= -1 + ret += datetime.timedelta(days=jumpdays) + return ret + + def __rsub__(self, other): + return self.__neg__().__radd__(other) + + def __add__(self, other): + if not isinstance(other, relativedelta): + raise TypeError, "unsupported type for add operation" + return relativedelta(years=other.years+self.years, + months=other.months+self.months, + days=other.days+self.days, + hours=other.hours+self.hours, + minutes=other.minutes+self.minutes, + seconds=other.seconds+self.seconds, + microseconds=other.microseconds+self.microseconds, + leapdays=other.leapdays or self.leapdays, + year=other.year or self.year, + month=other.month or self.month, + day=other.day or self.day, + weekday=other.weekday or self.weekday, + hour=other.hour or self.hour, + minute=other.minute or self.minute, + second=other.second or self.second, + microsecond=other.second or self.microsecond) + + def __sub__(self, other): + if not isinstance(other, relativedelta): + raise TypeError, "unsupported type for sub operation" + return relativedelta(years=other.years-self.years, + months=other.months-self.months, + days=other.days-self.days, + hours=other.hours-self.hours, + minutes=other.minutes-self.minutes, + seconds=other.seconds-self.seconds, + microseconds=other.microseconds-self.microseconds, + leapdays=other.leapdays or self.leapdays, + year=other.year or self.year, + month=other.month or self.month, + day=other.day or self.day, + weekday=other.weekday or self.weekday, + hour=other.hour or self.hour, + minute=other.minute or self.minute, + second=other.second or self.second, + microsecond=other.second or self.microsecond) + + def __neg__(self): + return relativedelta(years=-self.years, + months=-self.months, + days=-self.days, + hours=-self.hours, + minutes=-self.minutes, + seconds=-self.seconds, + microseconds=-self.microseconds, + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + + def __nonzero__(self): + return not (not self.years and + not self.months and + not self.days and + not self.hours and + not self.minutes and + not self.seconds and + not self.microseconds and + not self.leapdays and + self.year is None and + self.month is None and + self.day is None and + self.weekday is None and + self.hour is None and + self.minute is None and + self.second is None and + self.microsecond is None) + + def __mul__(self, other): + f = float(other) + return relativedelta(years=self.years*f, + months=self.months*f, + days=self.days*f, + hours=self.hours*f, + minutes=self.minutes*f, + seconds=self.seconds*f, + microseconds=self.microseconds*f, + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + + def __eq__(self, other): + if not isinstance(other, relativedelta): + return False + if self.weekday or other.weekday: + if not self.weekday or not other.weekday: + return False + if self.weekday.weekday != other.weekday.weekday: + return False + n1, n2 = self.weekday.n, other.weekday.n + if n1 != n2 and not ((not n1 or n1 == 1) and (not n2 or n2 == 1)): + return False + return (self.years == other.years and + self.months == other.months and + self.days == other.days and + self.hours == other.hours and + self.minutes == other.minutes and + self.seconds == other.seconds and + self.leapdays == other.leapdays and + self.year == other.year and + self.month == other.month and + self.day == other.day and + self.hour == other.hour and + self.minute == other.minute and + self.second == other.second and + self.microsecond == other.microsecond) + + def __ne__(self, other): + return not self.__eq__(other) + + def __div__(self, other): + return self.__mul__(1/float(other)) + + def __repr__(self): + l = [] + for attr in ["years", "months", "days", "leapdays", + "hours", "minutes", "seconds", "microseconds"]: + value = getattr(self, attr) + if value: + l.append("%s=%+d" % (attr, value)) + for attr in ["year", "month", "day", "weekday", + "hour", "minute", "second", "microsecond"]: + value = getattr(self, attr) + if value is not None: + l.append("%s=%s" % (attr, `value`)) + return "%s(%s)" % (self.__class__.__name__, ", ".join(l)) + +# vim:ts=4:sw=4:et diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/rrule.py b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/rrule.py new file mode 100644 index 0000000..6bd83ca --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/rrule.py @@ -0,0 +1,1097 @@ +""" +Copyright (c) 2003-2010 Gustavo Niemeyer + +This module offers extensions to the standard python 2.3+ +datetime module. +""" +__author__ = "Gustavo Niemeyer " +__license__ = "PSF License" + +import itertools +import datetime +import calendar +import thread +import sys + +__all__ = ["rrule", "rruleset", "rrulestr", + "YEARLY", "MONTHLY", "WEEKLY", "DAILY", + "HOURLY", "MINUTELY", "SECONDLY", + "MO", "TU", "WE", "TH", "FR", "SA", "SU"] + +# Every mask is 7 days longer to handle cross-year weekly periods. +M366MASK = tuple([1]*31+[2]*29+[3]*31+[4]*30+[5]*31+[6]*30+ + [7]*31+[8]*31+[9]*30+[10]*31+[11]*30+[12]*31+[1]*7) +M365MASK = list(M366MASK) +M29, M30, M31 = range(1,30), range(1,31), range(1,32) +MDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7]) +MDAY365MASK = list(MDAY366MASK) +M29, M30, M31 = range(-29,0), range(-30,0), range(-31,0) +NMDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7]) +NMDAY365MASK = list(NMDAY366MASK) +M366RANGE = (0,31,60,91,121,152,182,213,244,274,305,335,366) +M365RANGE = (0,31,59,90,120,151,181,212,243,273,304,334,365) +WDAYMASK = [0,1,2,3,4,5,6]*55 +del M29, M30, M31, M365MASK[59], MDAY365MASK[59], NMDAY365MASK[31] +MDAY365MASK = tuple(MDAY365MASK) +M365MASK = tuple(M365MASK) + +(YEARLY, + MONTHLY, + WEEKLY, + DAILY, + HOURLY, + MINUTELY, + SECONDLY) = range(7) + +# Imported on demand. +easter = None +parser = None + +class weekday(object): + __slots__ = ["weekday", "n"] + + def __init__(self, weekday, n=None): + if n == 0: + raise ValueError, "Can't create weekday with n == 0" + self.weekday = weekday + self.n = n + + def __call__(self, n): + if n == self.n: + return self + else: + return self.__class__(self.weekday, n) + + def __eq__(self, other): + try: + if self.weekday != other.weekday or self.n != other.n: + return False + except AttributeError: + return False + return True + + def __repr__(self): + s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday] + if not self.n: + return s + else: + return "%s(%+d)" % (s, self.n) + +MO, TU, WE, TH, FR, SA, SU = weekdays = tuple([weekday(x) for x in range(7)]) + +class rrulebase: + def __init__(self, cache=False): + if cache: + self._cache = [] + self._cache_lock = thread.allocate_lock() + self._cache_gen = self._iter() + self._cache_complete = False + else: + self._cache = None + self._cache_complete = False + self._len = None + + def __iter__(self): + if self._cache_complete: + return iter(self._cache) + elif self._cache is None: + return self._iter() + else: + return self._iter_cached() + + def _iter_cached(self): + i = 0 + gen = self._cache_gen + cache = self._cache + acquire = self._cache_lock.acquire + release = self._cache_lock.release + while gen: + if i == len(cache): + acquire() + if self._cache_complete: + break + try: + for j in range(10): + cache.append(gen.next()) + except StopIteration: + self._cache_gen = gen = None + self._cache_complete = True + break + release() + yield cache[i] + i += 1 + while i < self._len: + yield cache[i] + i += 1 + + def __getitem__(self, item): + if self._cache_complete: + return self._cache[item] + elif isinstance(item, slice): + if item.step and item.step < 0: + return list(iter(self))[item] + else: + return list(itertools.islice(self, + item.start or 0, + item.stop or sys.maxint, + item.step or 1)) + elif item >= 0: + gen = iter(self) + try: + for i in range(item+1): + res = gen.next() + except StopIteration: + raise IndexError + return res + else: + return list(iter(self))[item] + + def __contains__(self, item): + if self._cache_complete: + return item in self._cache + else: + for i in self: + if i == item: + return True + elif i > item: + return False + return False + + # __len__() introduces a large performance penality. + def count(self): + if self._len is None: + for x in self: pass + return self._len + + def before(self, dt, inc=False): + if self._cache_complete: + gen = self._cache + else: + gen = self + last = None + if inc: + for i in gen: + if i > dt: + break + last = i + else: + for i in gen: + if i >= dt: + break + last = i + return last + + def after(self, dt, inc=False): + if self._cache_complete: + gen = self._cache + else: + gen = self + if inc: + for i in gen: + if i >= dt: + return i + else: + for i in gen: + if i > dt: + return i + return None + + def between(self, after, before, inc=False): + if self._cache_complete: + gen = self._cache + else: + gen = self + started = False + l = [] + if inc: + for i in gen: + if i > before: + break + elif not started: + if i >= after: + started = True + l.append(i) + else: + l.append(i) + else: + for i in gen: + if i >= before: + break + elif not started: + if i > after: + started = True + l.append(i) + else: + l.append(i) + return l + +class rrule(rrulebase): + def __init__(self, freq, dtstart=None, + interval=1, wkst=None, count=None, until=None, bysetpos=None, + bymonth=None, bymonthday=None, byyearday=None, byeaster=None, + byweekno=None, byweekday=None, + byhour=None, byminute=None, bysecond=None, + cache=False): + rrulebase.__init__(self, cache) + global easter + if not dtstart: + dtstart = datetime.datetime.now().replace(microsecond=0) + elif not isinstance(dtstart, datetime.datetime): + dtstart = datetime.datetime.fromordinal(dtstart.toordinal()) + else: + dtstart = dtstart.replace(microsecond=0) + self._dtstart = dtstart + self._tzinfo = dtstart.tzinfo + self._freq = freq + self._interval = interval + self._count = count + if until and not isinstance(until, datetime.datetime): + until = datetime.datetime.fromordinal(until.toordinal()) + self._until = until + if wkst is None: + self._wkst = calendar.firstweekday() + elif type(wkst) is int: + self._wkst = wkst + else: + self._wkst = wkst.weekday + if bysetpos is None: + self._bysetpos = None + elif type(bysetpos) is int: + if bysetpos == 0 or not (-366 <= bysetpos <= 366): + raise ValueError("bysetpos must be between 1 and 366, " + "or between -366 and -1") + self._bysetpos = (bysetpos,) + else: + self._bysetpos = tuple(bysetpos) + for pos in self._bysetpos: + if pos == 0 or not (-366 <= pos <= 366): + raise ValueError("bysetpos must be between 1 and 366, " + "or between -366 and -1") + if not (byweekno or byyearday or bymonthday or + byweekday is not None or byeaster is not None): + if freq == YEARLY: + if not bymonth: + bymonth = dtstart.month + bymonthday = dtstart.day + elif freq == MONTHLY: + bymonthday = dtstart.day + elif freq == WEEKLY: + byweekday = dtstart.weekday() + # bymonth + if not bymonth: + self._bymonth = None + elif type(bymonth) is int: + self._bymonth = (bymonth,) + else: + self._bymonth = tuple(bymonth) + # byyearday + if not byyearday: + self._byyearday = None + elif type(byyearday) is int: + self._byyearday = (byyearday,) + else: + self._byyearday = tuple(byyearday) + # byeaster + if byeaster is not None: + if not easter: + from dateutil import easter + if type(byeaster) is int: + self._byeaster = (byeaster,) + else: + self._byeaster = tuple(byeaster) + else: + self._byeaster = None + # bymonthay + if not bymonthday: + self._bymonthday = () + self._bynmonthday = () + elif type(bymonthday) is int: + if bymonthday < 0: + self._bynmonthday = (bymonthday,) + self._bymonthday = () + else: + self._bymonthday = (bymonthday,) + self._bynmonthday = () + else: + self._bymonthday = tuple([x for x in bymonthday if x > 0]) + self._bynmonthday = tuple([x for x in bymonthday if x < 0]) + # byweekno + if byweekno is None: + self._byweekno = None + elif type(byweekno) is int: + self._byweekno = (byweekno,) + else: + self._byweekno = tuple(byweekno) + # byweekday / bynweekday + if byweekday is None: + self._byweekday = None + self._bynweekday = None + elif type(byweekday) is int: + self._byweekday = (byweekday,) + self._bynweekday = None + elif hasattr(byweekday, "n"): + if not byweekday.n or freq > MONTHLY: + self._byweekday = (byweekday.weekday,) + self._bynweekday = None + else: + self._bynweekday = ((byweekday.weekday, byweekday.n),) + self._byweekday = None + else: + self._byweekday = [] + self._bynweekday = [] + for wday in byweekday: + if type(wday) is int: + self._byweekday.append(wday) + elif not wday.n or freq > MONTHLY: + self._byweekday.append(wday.weekday) + else: + self._bynweekday.append((wday.weekday, wday.n)) + self._byweekday = tuple(self._byweekday) + self._bynweekday = tuple(self._bynweekday) + if not self._byweekday: + self._byweekday = None + elif not self._bynweekday: + self._bynweekday = None + # byhour + if byhour is None: + if freq < HOURLY: + self._byhour = (dtstart.hour,) + else: + self._byhour = None + elif type(byhour) is int: + self._byhour = (byhour,) + else: + self._byhour = tuple(byhour) + # byminute + if byminute is None: + if freq < MINUTELY: + self._byminute = (dtstart.minute,) + else: + self._byminute = None + elif type(byminute) is int: + self._byminute = (byminute,) + else: + self._byminute = tuple(byminute) + # bysecond + if bysecond is None: + if freq < SECONDLY: + self._bysecond = (dtstart.second,) + else: + self._bysecond = None + elif type(bysecond) is int: + self._bysecond = (bysecond,) + else: + self._bysecond = tuple(bysecond) + + if self._freq >= HOURLY: + self._timeset = None + else: + self._timeset = [] + for hour in self._byhour: + for minute in self._byminute: + for second in self._bysecond: + self._timeset.append( + datetime.time(hour, minute, second, + tzinfo=self._tzinfo)) + self._timeset.sort() + self._timeset = tuple(self._timeset) + + def _iter(self): + year, month, day, hour, minute, second, weekday, yearday, _ = \ + self._dtstart.timetuple() + + # Some local variables to speed things up a bit + freq = self._freq + interval = self._interval + wkst = self._wkst + until = self._until + bymonth = self._bymonth + byweekno = self._byweekno + byyearday = self._byyearday + byweekday = self._byweekday + byeaster = self._byeaster + bymonthday = self._bymonthday + bynmonthday = self._bynmonthday + bysetpos = self._bysetpos + byhour = self._byhour + byminute = self._byminute + bysecond = self._bysecond + + ii = _iterinfo(self) + ii.rebuild(year, month) + + getdayset = {YEARLY:ii.ydayset, + MONTHLY:ii.mdayset, + WEEKLY:ii.wdayset, + DAILY:ii.ddayset, + HOURLY:ii.ddayset, + MINUTELY:ii.ddayset, + SECONDLY:ii.ddayset}[freq] + + if freq < HOURLY: + timeset = self._timeset + else: + gettimeset = {HOURLY:ii.htimeset, + MINUTELY:ii.mtimeset, + SECONDLY:ii.stimeset}[freq] + if ((freq >= HOURLY and + self._byhour and hour not in self._byhour) or + (freq >= MINUTELY and + self._byminute and minute not in self._byminute) or + (freq >= SECONDLY and + self._bysecond and second not in self._bysecond)): + timeset = () + else: + timeset = gettimeset(hour, minute, second) + + total = 0 + count = self._count + while True: + # Get dayset with the right frequency + dayset, start, end = getdayset(year, month, day) + + # Do the "hard" work ;-) + filtered = False + for i in dayset[start:end]: + if ((bymonth and ii.mmask[i] not in bymonth) or + (byweekno and not ii.wnomask[i]) or + (byweekday and ii.wdaymask[i] not in byweekday) or + (ii.nwdaymask and not ii.nwdaymask[i]) or + (byeaster and not ii.eastermask[i]) or + ((bymonthday or bynmonthday) and + ii.mdaymask[i] not in bymonthday and + ii.nmdaymask[i] not in bynmonthday) or + (byyearday and + ((i < ii.yearlen and i+1 not in byyearday + and -ii.yearlen+i not in byyearday) or + (i >= ii.yearlen and i+1-ii.yearlen not in byyearday + and -ii.nextyearlen+i-ii.yearlen + not in byyearday)))): + dayset[i] = None + filtered = True + + # Output results + if bysetpos and timeset: + poslist = [] + for pos in bysetpos: + if pos < 0: + daypos, timepos = divmod(pos, len(timeset)) + else: + daypos, timepos = divmod(pos-1, len(timeset)) + try: + i = [x for x in dayset[start:end] + if x is not None][daypos] + time = timeset[timepos] + except IndexError: + pass + else: + date = datetime.date.fromordinal(ii.yearordinal+i) + res = datetime.datetime.combine(date, time) + if res not in poslist: + poslist.append(res) + poslist.sort() + for res in poslist: + if until and res > until: + self._len = total + return + elif res >= self._dtstart: + total += 1 + yield res + if count: + count -= 1 + if not count: + self._len = total + return + else: + for i in dayset[start:end]: + if i is not None: + date = datetime.date.fromordinal(ii.yearordinal+i) + for time in timeset: + res = datetime.datetime.combine(date, time) + if until and res > until: + self._len = total + return + elif res >= self._dtstart: + total += 1 + yield res + if count: + count -= 1 + if not count: + self._len = total + return + + # Handle frequency and interval + fixday = False + if freq == YEARLY: + year += interval + if year > datetime.MAXYEAR: + self._len = total + return + ii.rebuild(year, month) + elif freq == MONTHLY: + month += interval + if month > 12: + div, mod = divmod(month, 12) + month = mod + year += div + if month == 0: + month = 12 + year -= 1 + if year > datetime.MAXYEAR: + self._len = total + return + ii.rebuild(year, month) + elif freq == WEEKLY: + if wkst > weekday: + day += -(weekday+1+(6-wkst))+self._interval*7 + else: + day += -(weekday-wkst)+self._interval*7 + weekday = wkst + fixday = True + elif freq == DAILY: + day += interval + fixday = True + elif freq == HOURLY: + if filtered: + # Jump to one iteration before next day + hour += ((23-hour)//interval)*interval + while True: + hour += interval + div, mod = divmod(hour, 24) + if div: + hour = mod + day += div + fixday = True + if not byhour or hour in byhour: + break + timeset = gettimeset(hour, minute, second) + elif freq == MINUTELY: + if filtered: + # Jump to one iteration before next day + minute += ((1439-(hour*60+minute))//interval)*interval + while True: + minute += interval + div, mod = divmod(minute, 60) + if div: + minute = mod + hour += div + div, mod = divmod(hour, 24) + if div: + hour = mod + day += div + fixday = True + filtered = False + if ((not byhour or hour in byhour) and + (not byminute or minute in byminute)): + break + timeset = gettimeset(hour, minute, second) + elif freq == SECONDLY: + if filtered: + # Jump to one iteration before next day + second += (((86399-(hour*3600+minute*60+second)) + //interval)*interval) + while True: + second += self._interval + div, mod = divmod(second, 60) + if div: + second = mod + minute += div + div, mod = divmod(minute, 60) + if div: + minute = mod + hour += div + div, mod = divmod(hour, 24) + if div: + hour = mod + day += div + fixday = True + if ((not byhour or hour in byhour) and + (not byminute or minute in byminute) and + (not bysecond or second in bysecond)): + break + timeset = gettimeset(hour, minute, second) + + if fixday and day > 28: + daysinmonth = calendar.monthrange(year, month)[1] + if day > daysinmonth: + while day > daysinmonth: + day -= daysinmonth + month += 1 + if month == 13: + month = 1 + year += 1 + if year > datetime.MAXYEAR: + self._len = total + return + daysinmonth = calendar.monthrange(year, month)[1] + ii.rebuild(year, month) + +class _iterinfo(object): + __slots__ = ["rrule", "lastyear", "lastmonth", + "yearlen", "nextyearlen", "yearordinal", "yearweekday", + "mmask", "mrange", "mdaymask", "nmdaymask", + "wdaymask", "wnomask", "nwdaymask", "eastermask"] + + def __init__(self, rrule): + for attr in self.__slots__: + setattr(self, attr, None) + self.rrule = rrule + + def rebuild(self, year, month): + # Every mask is 7 days longer to handle cross-year weekly periods. + rr = self.rrule + if year != self.lastyear: + self.yearlen = 365+calendar.isleap(year) + self.nextyearlen = 365+calendar.isleap(year+1) + firstyday = datetime.date(year, 1, 1) + self.yearordinal = firstyday.toordinal() + self.yearweekday = firstyday.weekday() + + wday = datetime.date(year, 1, 1).weekday() + if self.yearlen == 365: + self.mmask = M365MASK + self.mdaymask = MDAY365MASK + self.nmdaymask = NMDAY365MASK + self.wdaymask = WDAYMASK[wday:] + self.mrange = M365RANGE + else: + self.mmask = M366MASK + self.mdaymask = MDAY366MASK + self.nmdaymask = NMDAY366MASK + self.wdaymask = WDAYMASK[wday:] + self.mrange = M366RANGE + + if not rr._byweekno: + self.wnomask = None + else: + self.wnomask = [0]*(self.yearlen+7) + #no1wkst = firstwkst = self.wdaymask.index(rr._wkst) + no1wkst = firstwkst = (7-self.yearweekday+rr._wkst)%7 + if no1wkst >= 4: + no1wkst = 0 + # Number of days in the year, plus the days we got + # from last year. + wyearlen = self.yearlen+(self.yearweekday-rr._wkst)%7 + else: + # Number of days in the year, minus the days we + # left in last year. + wyearlen = self.yearlen-no1wkst + div, mod = divmod(wyearlen, 7) + numweeks = div+mod//4 + for n in rr._byweekno: + if n < 0: + n += numweeks+1 + if not (0 < n <= numweeks): + continue + if n > 1: + i = no1wkst+(n-1)*7 + if no1wkst != firstwkst: + i -= 7-firstwkst + else: + i = no1wkst + for j in range(7): + self.wnomask[i] = 1 + i += 1 + if self.wdaymask[i] == rr._wkst: + break + if 1 in rr._byweekno: + # Check week number 1 of next year as well + # TODO: Check -numweeks for next year. + i = no1wkst+numweeks*7 + if no1wkst != firstwkst: + i -= 7-firstwkst + if i < self.yearlen: + # If week starts in next year, we + # don't care about it. + for j in range(7): + self.wnomask[i] = 1 + i += 1 + if self.wdaymask[i] == rr._wkst: + break + if no1wkst: + # Check last week number of last year as + # well. If no1wkst is 0, either the year + # started on week start, or week number 1 + # got days from last year, so there are no + # days from last year's last week number in + # this year. + if -1 not in rr._byweekno: + lyearweekday = datetime.date(year-1,1,1).weekday() + lno1wkst = (7-lyearweekday+rr._wkst)%7 + lyearlen = 365+calendar.isleap(year-1) + if lno1wkst >= 4: + lno1wkst = 0 + lnumweeks = 52+(lyearlen+ + (lyearweekday-rr._wkst)%7)%7//4 + else: + lnumweeks = 52+(self.yearlen-no1wkst)%7//4 + else: + lnumweeks = -1 + if lnumweeks in rr._byweekno: + for i in range(no1wkst): + self.wnomask[i] = 1 + + if (rr._bynweekday and + (month != self.lastmonth or year != self.lastyear)): + ranges = [] + if rr._freq == YEARLY: + if rr._bymonth: + for month in rr._bymonth: + ranges.append(self.mrange[month-1:month+1]) + else: + ranges = [(0, self.yearlen)] + elif rr._freq == MONTHLY: + ranges = [self.mrange[month-1:month+1]] + if ranges: + # Weekly frequency won't get here, so we may not + # care about cross-year weekly periods. + self.nwdaymask = [0]*self.yearlen + for first, last in ranges: + last -= 1 + for wday, n in rr._bynweekday: + if n < 0: + i = last+(n+1)*7 + i -= (self.wdaymask[i]-wday)%7 + else: + i = first+(n-1)*7 + i += (7-self.wdaymask[i]+wday)%7 + if first <= i <= last: + self.nwdaymask[i] = 1 + + if rr._byeaster: + self.eastermask = [0]*(self.yearlen+7) + eyday = easter.easter(year).toordinal()-self.yearordinal + for offset in rr._byeaster: + self.eastermask[eyday+offset] = 1 + + self.lastyear = year + self.lastmonth = month + + def ydayset(self, year, month, day): + return range(self.yearlen), 0, self.yearlen + + def mdayset(self, year, month, day): + set = [None]*self.yearlen + start, end = self.mrange[month-1:month+1] + for i in range(start, end): + set[i] = i + return set, start, end + + def wdayset(self, year, month, day): + # We need to handle cross-year weeks here. + set = [None]*(self.yearlen+7) + i = datetime.date(year, month, day).toordinal()-self.yearordinal + start = i + for j in range(7): + set[i] = i + i += 1 + #if (not (0 <= i < self.yearlen) or + # self.wdaymask[i] == self.rrule._wkst): + # This will cross the year boundary, if necessary. + if self.wdaymask[i] == self.rrule._wkst: + break + return set, start, i + + def ddayset(self, year, month, day): + set = [None]*self.yearlen + i = datetime.date(year, month, day).toordinal()-self.yearordinal + set[i] = i + return set, i, i+1 + + def htimeset(self, hour, minute, second): + set = [] + rr = self.rrule + for minute in rr._byminute: + for second in rr._bysecond: + set.append(datetime.time(hour, minute, second, + tzinfo=rr._tzinfo)) + set.sort() + return set + + def mtimeset(self, hour, minute, second): + set = [] + rr = self.rrule + for second in rr._bysecond: + set.append(datetime.time(hour, minute, second, tzinfo=rr._tzinfo)) + set.sort() + return set + + def stimeset(self, hour, minute, second): + return (datetime.time(hour, minute, second, + tzinfo=self.rrule._tzinfo),) + + +class rruleset(rrulebase): + + class _genitem: + def __init__(self, genlist, gen): + try: + self.dt = gen() + genlist.append(self) + except StopIteration: + pass + self.genlist = genlist + self.gen = gen + + def next(self): + try: + self.dt = self.gen() + except StopIteration: + self.genlist.remove(self) + + def __cmp__(self, other): + return cmp(self.dt, other.dt) + + def __init__(self, cache=False): + rrulebase.__init__(self, cache) + self._rrule = [] + self._rdate = [] + self._exrule = [] + self._exdate = [] + + def rrule(self, rrule): + self._rrule.append(rrule) + + def rdate(self, rdate): + self._rdate.append(rdate) + + def exrule(self, exrule): + self._exrule.append(exrule) + + def exdate(self, exdate): + self._exdate.append(exdate) + + def _iter(self): + rlist = [] + self._rdate.sort() + self._genitem(rlist, iter(self._rdate).next) + for gen in [iter(x).next for x in self._rrule]: + self._genitem(rlist, gen) + rlist.sort() + exlist = [] + self._exdate.sort() + self._genitem(exlist, iter(self._exdate).next) + for gen in [iter(x).next for x in self._exrule]: + self._genitem(exlist, gen) + exlist.sort() + lastdt = None + total = 0 + while rlist: + ritem = rlist[0] + if not lastdt or lastdt != ritem.dt: + while exlist and exlist[0] < ritem: + exlist[0].next() + exlist.sort() + if not exlist or ritem != exlist[0]: + total += 1 + yield ritem.dt + lastdt = ritem.dt + ritem.next() + rlist.sort() + self._len = total + +class _rrulestr: + + _freq_map = {"YEARLY": YEARLY, + "MONTHLY": MONTHLY, + "WEEKLY": WEEKLY, + "DAILY": DAILY, + "HOURLY": HOURLY, + "MINUTELY": MINUTELY, + "SECONDLY": SECONDLY} + + _weekday_map = {"MO":0,"TU":1,"WE":2,"TH":3,"FR":4,"SA":5,"SU":6} + + def _handle_int(self, rrkwargs, name, value, **kwargs): + rrkwargs[name.lower()] = int(value) + + def _handle_int_list(self, rrkwargs, name, value, **kwargs): + rrkwargs[name.lower()] = [int(x) for x in value.split(',')] + + _handle_INTERVAL = _handle_int + _handle_COUNT = _handle_int + _handle_BYSETPOS = _handle_int_list + _handle_BYMONTH = _handle_int_list + _handle_BYMONTHDAY = _handle_int_list + _handle_BYYEARDAY = _handle_int_list + _handle_BYEASTER = _handle_int_list + _handle_BYWEEKNO = _handle_int_list + _handle_BYHOUR = _handle_int_list + _handle_BYMINUTE = _handle_int_list + _handle_BYSECOND = _handle_int_list + + def _handle_FREQ(self, rrkwargs, name, value, **kwargs): + rrkwargs["freq"] = self._freq_map[value] + + def _handle_UNTIL(self, rrkwargs, name, value, **kwargs): + global parser + if not parser: + from dateutil import parser + try: + rrkwargs["until"] = parser.parse(value, + ignoretz=kwargs.get("ignoretz"), + tzinfos=kwargs.get("tzinfos")) + except ValueError: + raise ValueError, "invalid until date" + + def _handle_WKST(self, rrkwargs, name, value, **kwargs): + rrkwargs["wkst"] = self._weekday_map[value] + + def _handle_BYWEEKDAY(self, rrkwargs, name, value, **kwarsg): + l = [] + for wday in value.split(','): + for i in range(len(wday)): + if wday[i] not in '+-0123456789': + break + n = wday[:i] or None + w = wday[i:] + if n: n = int(n) + l.append(weekdays[self._weekday_map[w]](n)) + rrkwargs["byweekday"] = l + + _handle_BYDAY = _handle_BYWEEKDAY + + def _parse_rfc_rrule(self, line, + dtstart=None, + cache=False, + ignoretz=False, + tzinfos=None): + if line.find(':') != -1: + name, value = line.split(':') + if name != "RRULE": + raise ValueError, "unknown parameter name" + else: + value = line + rrkwargs = {} + for pair in value.split(';'): + name, value = pair.split('=') + name = name.upper() + value = value.upper() + try: + getattr(self, "_handle_"+name)(rrkwargs, name, value, + ignoretz=ignoretz, + tzinfos=tzinfos) + except AttributeError: + raise ValueError, "unknown parameter '%s'" % name + except (KeyError, ValueError): + raise ValueError, "invalid '%s': %s" % (name, value) + return rrule(dtstart=dtstart, cache=cache, **rrkwargs) + + def _parse_rfc(self, s, + dtstart=None, + cache=False, + unfold=False, + forceset=False, + compatible=False, + ignoretz=False, + tzinfos=None): + global parser + if compatible: + forceset = True + unfold = True + s = s.upper() + if not s.strip(): + raise ValueError, "empty string" + if unfold: + lines = s.splitlines() + i = 0 + while i < len(lines): + line = lines[i].rstrip() + if not line: + del lines[i] + elif i > 0 and line[0] == " ": + lines[i-1] += line[1:] + del lines[i] + else: + i += 1 + else: + lines = s.split() + if (not forceset and len(lines) == 1 and + (s.find(':') == -1 or s.startswith('RRULE:'))): + return self._parse_rfc_rrule(lines[0], cache=cache, + dtstart=dtstart, ignoretz=ignoretz, + tzinfos=tzinfos) + else: + rrulevals = [] + rdatevals = [] + exrulevals = [] + exdatevals = [] + for line in lines: + if not line: + continue + if line.find(':') == -1: + name = "RRULE" + value = line + else: + name, value = line.split(':', 1) + parms = name.split(';') + if not parms: + raise ValueError, "empty property name" + name = parms[0] + parms = parms[1:] + if name == "RRULE": + for parm in parms: + raise ValueError, "unsupported RRULE parm: "+parm + rrulevals.append(value) + elif name == "RDATE": + for parm in parms: + if parm != "VALUE=DATE-TIME": + raise ValueError, "unsupported RDATE parm: "+parm + rdatevals.append(value) + elif name == "EXRULE": + for parm in parms: + raise ValueError, "unsupported EXRULE parm: "+parm + exrulevals.append(value) + elif name == "EXDATE": + for parm in parms: + if parm != "VALUE=DATE-TIME": + raise ValueError, "unsupported RDATE parm: "+parm + exdatevals.append(value) + elif name == "DTSTART": + for parm in parms: + raise ValueError, "unsupported DTSTART parm: "+parm + if not parser: + from dateutil import parser + dtstart = parser.parse(value, ignoretz=ignoretz, + tzinfos=tzinfos) + else: + raise ValueError, "unsupported property: "+name + if (forceset or len(rrulevals) > 1 or + rdatevals or exrulevals or exdatevals): + if not parser and (rdatevals or exdatevals): + from dateutil import parser + set = rruleset(cache=cache) + for value in rrulevals: + set.rrule(self._parse_rfc_rrule(value, dtstart=dtstart, + ignoretz=ignoretz, + tzinfos=tzinfos)) + for value in rdatevals: + for datestr in value.split(','): + set.rdate(parser.parse(datestr, + ignoretz=ignoretz, + tzinfos=tzinfos)) + for value in exrulevals: + set.exrule(self._parse_rfc_rrule(value, dtstart=dtstart, + ignoretz=ignoretz, + tzinfos=tzinfos)) + for value in exdatevals: + for datestr in value.split(','): + set.exdate(parser.parse(datestr, + ignoretz=ignoretz, + tzinfos=tzinfos)) + if compatible and dtstart: + set.rdate(dtstart) + return set + else: + return self._parse_rfc_rrule(rrulevals[0], + dtstart=dtstart, + cache=cache, + ignoretz=ignoretz, + tzinfos=tzinfos) + + def __call__(self, s, **kwargs): + return self._parse_rfc(s, **kwargs) + +rrulestr = _rrulestr() + +# vim:ts=4:sw=4:et diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/tz.py b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/tz.py new file mode 100644 index 0000000..0e28d6b --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/tz.py @@ -0,0 +1,951 @@ +""" +Copyright (c) 2003-2007 Gustavo Niemeyer + +This module offers extensions to the standard python 2.3+ +datetime module. +""" +__author__ = "Gustavo Niemeyer " +__license__ = "PSF License" + +import datetime +import struct +import time +import sys +import os + +relativedelta = None +parser = None +rrule = None + +__all__ = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange", + "tzstr", "tzical", "tzwin", "tzwinlocal", "gettz"] + +try: + from dateutil.tzwin import tzwin, tzwinlocal +except (ImportError, OSError): + tzwin, tzwinlocal = None, None + +ZERO = datetime.timedelta(0) +EPOCHORDINAL = datetime.datetime.utcfromtimestamp(0).toordinal() + +class tzutc(datetime.tzinfo): + + def utcoffset(self, dt): + return ZERO + + def dst(self, dt): + return ZERO + + def tzname(self, dt): + return "UTC" + + def __eq__(self, other): + return (isinstance(other, tzutc) or + (isinstance(other, tzoffset) and other._offset == ZERO)) + + def __ne__(self, other): + return not self.__eq__(other) + + def __repr__(self): + return "%s()" % self.__class__.__name__ + + __reduce__ = object.__reduce__ + +class tzoffset(datetime.tzinfo): + + def __init__(self, name, offset): + self._name = name + self._offset = datetime.timedelta(seconds=offset) + + def utcoffset(self, dt): + return self._offset + + def dst(self, dt): + return ZERO + + def tzname(self, dt): + return self._name + + def __eq__(self, other): + return (isinstance(other, tzoffset) and + self._offset == other._offset) + + def __ne__(self, other): + return not self.__eq__(other) + + def __repr__(self): + return "%s(%s, %s)" % (self.__class__.__name__, + `self._name`, + self._offset.days*86400+self._offset.seconds) + + __reduce__ = object.__reduce__ + +class tzlocal(datetime.tzinfo): + + _std_offset = datetime.timedelta(seconds=-time.timezone) + if time.daylight: + _dst_offset = datetime.timedelta(seconds=-time.altzone) + else: + _dst_offset = _std_offset + + def utcoffset(self, dt): + if self._isdst(dt): + return self._dst_offset + else: + return self._std_offset + + def dst(self, dt): + if self._isdst(dt): + return self._dst_offset-self._std_offset + else: + return ZERO + + def tzname(self, dt): + return time.tzname[self._isdst(dt)] + + def _isdst(self, dt): + # We can't use mktime here. It is unstable when deciding if + # the hour near to a change is DST or not. + # + # timestamp = time.mktime((dt.year, dt.month, dt.day, dt.hour, + # dt.minute, dt.second, dt.weekday(), 0, -1)) + # return time.localtime(timestamp).tm_isdst + # + # The code above yields the following result: + # + #>>> import tz, datetime + #>>> t = tz.tzlocal() + #>>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() + #'BRDT' + #>>> datetime.datetime(2003,2,16,0,tzinfo=t).tzname() + #'BRST' + #>>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() + #'BRST' + #>>> datetime.datetime(2003,2,15,22,tzinfo=t).tzname() + #'BRDT' + #>>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() + #'BRDT' + # + # Here is a more stable implementation: + # + timestamp = ((dt.toordinal() - EPOCHORDINAL) * 86400 + + dt.hour * 3600 + + dt.minute * 60 + + dt.second) + return time.localtime(timestamp+time.timezone).tm_isdst + + def __eq__(self, other): + if not isinstance(other, tzlocal): + return False + return (self._std_offset == other._std_offset and + self._dst_offset == other._dst_offset) + return True + + def __ne__(self, other): + return not self.__eq__(other) + + def __repr__(self): + return "%s()" % self.__class__.__name__ + + __reduce__ = object.__reduce__ + +class _ttinfo(object): + __slots__ = ["offset", "delta", "isdst", "abbr", "isstd", "isgmt"] + + def __init__(self): + for attr in self.__slots__: + setattr(self, attr, None) + + def __repr__(self): + l = [] + for attr in self.__slots__: + value = getattr(self, attr) + if value is not None: + l.append("%s=%s" % (attr, `value`)) + return "%s(%s)" % (self.__class__.__name__, ", ".join(l)) + + def __eq__(self, other): + if not isinstance(other, _ttinfo): + return False + return (self.offset == other.offset and + self.delta == other.delta and + self.isdst == other.isdst and + self.abbr == other.abbr and + self.isstd == other.isstd and + self.isgmt == other.isgmt) + + def __ne__(self, other): + return not self.__eq__(other) + + def __getstate__(self): + state = {} + for name in self.__slots__: + state[name] = getattr(self, name, None) + return state + + def __setstate__(self, state): + for name in self.__slots__: + if name in state: + setattr(self, name, state[name]) + +class tzfile(datetime.tzinfo): + + # http://www.twinsun.com/tz/tz-link.htm + # ftp://elsie.nci.nih.gov/pub/tz*.tar.gz + + def __init__(self, fileobj): + if isinstance(fileobj, basestring): + self._filename = fileobj + fileobj = open(fileobj) + elif hasattr(fileobj, "name"): + self._filename = fileobj.name + else: + self._filename = `fileobj` + + # From tzfile(5): + # + # The time zone information files used by tzset(3) + # begin with the magic characters "TZif" to identify + # them as time zone information files, followed by + # sixteen bytes reserved for future use, followed by + # six four-byte values of type long, written in a + # ``standard'' byte order (the high-order byte + # of the value is written first). + + if fileobj.read(4) != "TZif": + raise ValueError, "magic not found" + + fileobj.read(16) + + ( + # The number of UTC/local indicators stored in the file. + ttisgmtcnt, + + # The number of standard/wall indicators stored in the file. + ttisstdcnt, + + # The number of leap seconds for which data is + # stored in the file. + leapcnt, + + # The number of "transition times" for which data + # is stored in the file. + timecnt, + + # The number of "local time types" for which data + # is stored in the file (must not be zero). + typecnt, + + # The number of characters of "time zone + # abbreviation strings" stored in the file. + charcnt, + + ) = struct.unpack(">6l", fileobj.read(24)) + + # The above header is followed by tzh_timecnt four-byte + # values of type long, sorted in ascending order. + # These values are written in ``standard'' byte order. + # Each is used as a transition time (as returned by + # time(2)) at which the rules for computing local time + # change. + + if timecnt: + self._trans_list = struct.unpack(">%dl" % timecnt, + fileobj.read(timecnt*4)) + else: + self._trans_list = [] + + # Next come tzh_timecnt one-byte values of type unsigned + # char; each one tells which of the different types of + # ``local time'' types described in the file is associated + # with the same-indexed transition time. These values + # serve as indices into an array of ttinfo structures that + # appears next in the file. + + if timecnt: + self._trans_idx = struct.unpack(">%dB" % timecnt, + fileobj.read(timecnt)) + else: + self._trans_idx = [] + + # Each ttinfo structure is written as a four-byte value + # for tt_gmtoff of type long, in a standard byte + # order, followed by a one-byte value for tt_isdst + # and a one-byte value for tt_abbrind. In each + # structure, tt_gmtoff gives the number of + # seconds to be added to UTC, tt_isdst tells whether + # tm_isdst should be set by localtime(3), and + # tt_abbrind serves as an index into the array of + # time zone abbreviation characters that follow the + # ttinfo structure(s) in the file. + + ttinfo = [] + + for i in range(typecnt): + ttinfo.append(struct.unpack(">lbb", fileobj.read(6))) + + abbr = fileobj.read(charcnt) + + # Then there are tzh_leapcnt pairs of four-byte + # values, written in standard byte order; the + # first value of each pair gives the time (as + # returned by time(2)) at which a leap second + # occurs; the second gives the total number of + # leap seconds to be applied after the given time. + # The pairs of values are sorted in ascending order + # by time. + + # Not used, for now + if leapcnt: + leap = struct.unpack(">%dl" % (leapcnt*2), + fileobj.read(leapcnt*8)) + + # Then there are tzh_ttisstdcnt standard/wall + # indicators, each stored as a one-byte value; + # they tell whether the transition times associated + # with local time types were specified as standard + # time or wall clock time, and are used when + # a time zone file is used in handling POSIX-style + # time zone environment variables. + + if ttisstdcnt: + isstd = struct.unpack(">%db" % ttisstdcnt, + fileobj.read(ttisstdcnt)) + + # Finally, there are tzh_ttisgmtcnt UTC/local + # indicators, each stored as a one-byte value; + # they tell whether the transition times associated + # with local time types were specified as UTC or + # local time, and are used when a time zone file + # is used in handling POSIX-style time zone envi- + # ronment variables. + + if ttisgmtcnt: + isgmt = struct.unpack(">%db" % ttisgmtcnt, + fileobj.read(ttisgmtcnt)) + + # ** Everything has been read ** + + # Build ttinfo list + self._ttinfo_list = [] + for i in range(typecnt): + gmtoff, isdst, abbrind = ttinfo[i] + # Round to full-minutes if that's not the case. Python's + # datetime doesn't accept sub-minute timezones. Check + # http://python.org/sf/1447945 for some information. + gmtoff = (gmtoff+30)//60*60 + tti = _ttinfo() + tti.offset = gmtoff + tti.delta = datetime.timedelta(seconds=gmtoff) + tti.isdst = isdst + tti.abbr = abbr[abbrind:abbr.find('\x00', abbrind)] + tti.isstd = (ttisstdcnt > i and isstd[i] != 0) + tti.isgmt = (ttisgmtcnt > i and isgmt[i] != 0) + self._ttinfo_list.append(tti) + + # Replace ttinfo indexes for ttinfo objects. + trans_idx = [] + for idx in self._trans_idx: + trans_idx.append(self._ttinfo_list[idx]) + self._trans_idx = tuple(trans_idx) + + # Set standard, dst, and before ttinfos. before will be + # used when a given time is before any transitions, + # and will be set to the first non-dst ttinfo, or to + # the first dst, if all of them are dst. + self._ttinfo_std = None + self._ttinfo_dst = None + self._ttinfo_before = None + if self._ttinfo_list: + if not self._trans_list: + self._ttinfo_std = self._ttinfo_first = self._ttinfo_list[0] + else: + for i in range(timecnt-1,-1,-1): + tti = self._trans_idx[i] + if not self._ttinfo_std and not tti.isdst: + self._ttinfo_std = tti + elif not self._ttinfo_dst and tti.isdst: + self._ttinfo_dst = tti + if self._ttinfo_std and self._ttinfo_dst: + break + else: + if self._ttinfo_dst and not self._ttinfo_std: + self._ttinfo_std = self._ttinfo_dst + + for tti in self._ttinfo_list: + if not tti.isdst: + self._ttinfo_before = tti + break + else: + self._ttinfo_before = self._ttinfo_list[0] + + # Now fix transition times to become relative to wall time. + # + # I'm not sure about this. In my tests, the tz source file + # is setup to wall time, and in the binary file isstd and + # isgmt are off, so it should be in wall time. OTOH, it's + # always in gmt time. Let me know if you have comments + # about this. + laststdoffset = 0 + self._trans_list = list(self._trans_list) + for i in range(len(self._trans_list)): + tti = self._trans_idx[i] + if not tti.isdst: + # This is std time. + self._trans_list[i] += tti.offset + laststdoffset = tti.offset + else: + # This is dst time. Convert to std. + self._trans_list[i] += laststdoffset + self._trans_list = tuple(self._trans_list) + + def _find_ttinfo(self, dt, laststd=0): + timestamp = ((dt.toordinal() - EPOCHORDINAL) * 86400 + + dt.hour * 3600 + + dt.minute * 60 + + dt.second) + idx = 0 + for trans in self._trans_list: + if timestamp < trans: + break + idx += 1 + else: + return self._ttinfo_std + if idx == 0: + return self._ttinfo_before + if laststd: + while idx > 0: + tti = self._trans_idx[idx-1] + if not tti.isdst: + return tti + idx -= 1 + else: + return self._ttinfo_std + else: + return self._trans_idx[idx-1] + + def utcoffset(self, dt): + if not self._ttinfo_std: + return ZERO + return self._find_ttinfo(dt).delta + + def dst(self, dt): + if not self._ttinfo_dst: + return ZERO + tti = self._find_ttinfo(dt) + if not tti.isdst: + return ZERO + + # The documentation says that utcoffset()-dst() must + # be constant for every dt. + return tti.delta-self._find_ttinfo(dt, laststd=1).delta + + # An alternative for that would be: + # + # return self._ttinfo_dst.offset-self._ttinfo_std.offset + # + # However, this class stores historical changes in the + # dst offset, so I belive that this wouldn't be the right + # way to implement this. + + def tzname(self, dt): + if not self._ttinfo_std: + return None + return self._find_ttinfo(dt).abbr + + def __eq__(self, other): + if not isinstance(other, tzfile): + return False + return (self._trans_list == other._trans_list and + self._trans_idx == other._trans_idx and + self._ttinfo_list == other._ttinfo_list) + + def __ne__(self, other): + return not self.__eq__(other) + + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, `self._filename`) + + def __reduce__(self): + if not os.path.isfile(self._filename): + raise ValueError, "Unpickable %s class" % self.__class__.__name__ + return (self.__class__, (self._filename,)) + +class tzrange(datetime.tzinfo): + + def __init__(self, stdabbr, stdoffset=None, + dstabbr=None, dstoffset=None, + start=None, end=None): + global relativedelta + if not relativedelta: + from dateutil import relativedelta + self._std_abbr = stdabbr + self._dst_abbr = dstabbr + if stdoffset is not None: + self._std_offset = datetime.timedelta(seconds=stdoffset) + else: + self._std_offset = ZERO + if dstoffset is not None: + self._dst_offset = datetime.timedelta(seconds=dstoffset) + elif dstabbr and stdoffset is not None: + self._dst_offset = self._std_offset+datetime.timedelta(hours=+1) + else: + self._dst_offset = ZERO + if dstabbr and start is None: + self._start_delta = relativedelta.relativedelta( + hours=+2, month=4, day=1, weekday=relativedelta.SU(+1)) + else: + self._start_delta = start + if dstabbr and end is None: + self._end_delta = relativedelta.relativedelta( + hours=+1, month=10, day=31, weekday=relativedelta.SU(-1)) + else: + self._end_delta = end + + def utcoffset(self, dt): + if self._isdst(dt): + return self._dst_offset + else: + return self._std_offset + + def dst(self, dt): + if self._isdst(dt): + return self._dst_offset-self._std_offset + else: + return ZERO + + def tzname(self, dt): + if self._isdst(dt): + return self._dst_abbr + else: + return self._std_abbr + + def _isdst(self, dt): + if not self._start_delta: + return False + year = datetime.datetime(dt.year,1,1) + start = year+self._start_delta + end = year+self._end_delta + dt = dt.replace(tzinfo=None) + if start < end: + return dt >= start and dt < end + else: + return dt >= start or dt < end + + def __eq__(self, other): + if not isinstance(other, tzrange): + return False + return (self._std_abbr == other._std_abbr and + self._dst_abbr == other._dst_abbr and + self._std_offset == other._std_offset and + self._dst_offset == other._dst_offset and + self._start_delta == other._start_delta and + self._end_delta == other._end_delta) + + def __ne__(self, other): + return not self.__eq__(other) + + def __repr__(self): + return "%s(...)" % self.__class__.__name__ + + __reduce__ = object.__reduce__ + +class tzstr(tzrange): + + def __init__(self, s): + global parser + if not parser: + from dateutil import parser + self._s = s + + res = parser._parsetz(s) + if res is None: + raise ValueError, "unknown string format" + + # Here we break the compatibility with the TZ variable handling. + # GMT-3 actually *means* the timezone -3. + if res.stdabbr in ("GMT", "UTC"): + res.stdoffset *= -1 + + # We must initialize it first, since _delta() needs + # _std_offset and _dst_offset set. Use False in start/end + # to avoid building it two times. + tzrange.__init__(self, res.stdabbr, res.stdoffset, + res.dstabbr, res.dstoffset, + start=False, end=False) + + if not res.dstabbr: + self._start_delta = None + self._end_delta = None + else: + self._start_delta = self._delta(res.start) + if self._start_delta: + self._end_delta = self._delta(res.end, isend=1) + + def _delta(self, x, isend=0): + kwargs = {} + if x.month is not None: + kwargs["month"] = x.month + if x.weekday is not None: + kwargs["weekday"] = relativedelta.weekday(x.weekday, x.week) + if x.week > 0: + kwargs["day"] = 1 + else: + kwargs["day"] = 31 + elif x.day: + kwargs["day"] = x.day + elif x.yday is not None: + kwargs["yearday"] = x.yday + elif x.jyday is not None: + kwargs["nlyearday"] = x.jyday + if not kwargs: + # Default is to start on first sunday of april, and end + # on last sunday of october. + if not isend: + kwargs["month"] = 4 + kwargs["day"] = 1 + kwargs["weekday"] = relativedelta.SU(+1) + else: + kwargs["month"] = 10 + kwargs["day"] = 31 + kwargs["weekday"] = relativedelta.SU(-1) + if x.time is not None: + kwargs["seconds"] = x.time + else: + # Default is 2AM. + kwargs["seconds"] = 7200 + if isend: + # Convert to standard time, to follow the documented way + # of working with the extra hour. See the documentation + # of the tzinfo class. + delta = self._dst_offset-self._std_offset + kwargs["seconds"] -= delta.seconds+delta.days*86400 + return relativedelta.relativedelta(**kwargs) + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, `self._s`) + +class _tzicalvtzcomp: + def __init__(self, tzoffsetfrom, tzoffsetto, isdst, + tzname=None, rrule=None): + self.tzoffsetfrom = datetime.timedelta(seconds=tzoffsetfrom) + self.tzoffsetto = datetime.timedelta(seconds=tzoffsetto) + self.tzoffsetdiff = self.tzoffsetto-self.tzoffsetfrom + self.isdst = isdst + self.tzname = tzname + self.rrule = rrule + +class _tzicalvtz(datetime.tzinfo): + def __init__(self, tzid, comps=[]): + self._tzid = tzid + self._comps = comps + self._cachedate = [] + self._cachecomp = [] + + def _find_comp(self, dt): + if len(self._comps) == 1: + return self._comps[0] + dt = dt.replace(tzinfo=None) + try: + return self._cachecomp[self._cachedate.index(dt)] + except ValueError: + pass + lastcomp = None + lastcompdt = None + for comp in self._comps: + if not comp.isdst: + # Handle the extra hour in DST -> STD + compdt = comp.rrule.before(dt-comp.tzoffsetdiff, inc=True) + else: + compdt = comp.rrule.before(dt, inc=True) + if compdt and (not lastcompdt or lastcompdt < compdt): + lastcompdt = compdt + lastcomp = comp + if not lastcomp: + # RFC says nothing about what to do when a given + # time is before the first onset date. We'll look for the + # first standard component, or the first component, if + # none is found. + for comp in self._comps: + if not comp.isdst: + lastcomp = comp + break + else: + lastcomp = comp[0] + self._cachedate.insert(0, dt) + self._cachecomp.insert(0, lastcomp) + if len(self._cachedate) > 10: + self._cachedate.pop() + self._cachecomp.pop() + return lastcomp + + def utcoffset(self, dt): + return self._find_comp(dt).tzoffsetto + + def dst(self, dt): + comp = self._find_comp(dt) + if comp.isdst: + return comp.tzoffsetdiff + else: + return ZERO + + def tzname(self, dt): + return self._find_comp(dt).tzname + + def __repr__(self): + return "" % `self._tzid` + + __reduce__ = object.__reduce__ + +class tzical: + def __init__(self, fileobj): + global rrule + if not rrule: + from dateutil import rrule + + if isinstance(fileobj, basestring): + self._s = fileobj + fileobj = open(fileobj) + elif hasattr(fileobj, "name"): + self._s = fileobj.name + else: + self._s = `fileobj` + + self._vtz = {} + + self._parse_rfc(fileobj.read()) + + def keys(self): + return self._vtz.keys() + + def get(self, tzid=None): + if tzid is None: + keys = self._vtz.keys() + if len(keys) == 0: + raise ValueError, "no timezones defined" + elif len(keys) > 1: + raise ValueError, "more than one timezone available" + tzid = keys[0] + return self._vtz.get(tzid) + + def _parse_offset(self, s): + s = s.strip() + if not s: + raise ValueError, "empty offset" + if s[0] in ('+', '-'): + signal = (-1,+1)[s[0]=='+'] + s = s[1:] + else: + signal = +1 + if len(s) == 4: + return (int(s[:2])*3600+int(s[2:])*60)*signal + elif len(s) == 6: + return (int(s[:2])*3600+int(s[2:4])*60+int(s[4:]))*signal + else: + raise ValueError, "invalid offset: "+s + + def _parse_rfc(self, s): + lines = s.splitlines() + if not lines: + raise ValueError, "empty string" + + # Unfold + i = 0 + while i < len(lines): + line = lines[i].rstrip() + if not line: + del lines[i] + elif i > 0 and line[0] == " ": + lines[i-1] += line[1:] + del lines[i] + else: + i += 1 + + tzid = None + comps = [] + invtz = False + comptype = None + for line in lines: + if not line: + continue + name, value = line.split(':', 1) + parms = name.split(';') + if not parms: + raise ValueError, "empty property name" + name = parms[0].upper() + parms = parms[1:] + if invtz: + if name == "BEGIN": + if value in ("STANDARD", "DAYLIGHT"): + # Process component + pass + else: + raise ValueError, "unknown component: "+value + comptype = value + founddtstart = False + tzoffsetfrom = None + tzoffsetto = None + rrulelines = [] + tzname = None + elif name == "END": + if value == "VTIMEZONE": + if comptype: + raise ValueError, \ + "component not closed: "+comptype + if not tzid: + raise ValueError, \ + "mandatory TZID not found" + if not comps: + raise ValueError, \ + "at least one component is needed" + # Process vtimezone + self._vtz[tzid] = _tzicalvtz(tzid, comps) + invtz = False + elif value == comptype: + if not founddtstart: + raise ValueError, \ + "mandatory DTSTART not found" + if tzoffsetfrom is None: + raise ValueError, \ + "mandatory TZOFFSETFROM not found" + if tzoffsetto is None: + raise ValueError, \ + "mandatory TZOFFSETFROM not found" + # Process component + rr = None + if rrulelines: + rr = rrule.rrulestr("\n".join(rrulelines), + compatible=True, + ignoretz=True, + cache=True) + comp = _tzicalvtzcomp(tzoffsetfrom, tzoffsetto, + (comptype == "DAYLIGHT"), + tzname, rr) + comps.append(comp) + comptype = None + else: + raise ValueError, \ + "invalid component end: "+value + elif comptype: + if name == "DTSTART": + rrulelines.append(line) + founddtstart = True + elif name in ("RRULE", "RDATE", "EXRULE", "EXDATE"): + rrulelines.append(line) + elif name == "TZOFFSETFROM": + if parms: + raise ValueError, \ + "unsupported %s parm: %s "%(name, parms[0]) + tzoffsetfrom = self._parse_offset(value) + elif name == "TZOFFSETTO": + if parms: + raise ValueError, \ + "unsupported TZOFFSETTO parm: "+parms[0] + tzoffsetto = self._parse_offset(value) + elif name == "TZNAME": + if parms: + raise ValueError, \ + "unsupported TZNAME parm: "+parms[0] + tzname = value + elif name == "COMMENT": + pass + else: + raise ValueError, "unsupported property: "+name + else: + if name == "TZID": + if parms: + raise ValueError, \ + "unsupported TZID parm: "+parms[0] + tzid = value + elif name in ("TZURL", "LAST-MODIFIED", "COMMENT"): + pass + else: + raise ValueError, "unsupported property: "+name + elif name == "BEGIN" and value == "VTIMEZONE": + tzid = None + comps = [] + invtz = True + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, `self._s`) + +if sys.platform != "win32": + TZFILES = ["/etc/localtime", "localtime"] + TZPATHS = ["/usr/share/zoneinfo", "/usr/lib/zoneinfo", "/etc/zoneinfo"] +else: + TZFILES = [] + TZPATHS = [] + +def gettz(name=None): + tz = None + if not name: + try: + name = os.environ["TZ"] + except KeyError: + pass + if name is None or name == ":": + for filepath in TZFILES: + if not os.path.isabs(filepath): + filename = filepath + for path in TZPATHS: + filepath = os.path.join(path, filename) + if os.path.isfile(filepath): + break + else: + continue + if os.path.isfile(filepath): + try: + tz = tzfile(filepath) + break + except (IOError, OSError, ValueError): + pass + else: + tz = tzlocal() + else: + if name.startswith(":"): + name = name[:-1] + if os.path.isabs(name): + if os.path.isfile(name): + tz = tzfile(name) + else: + tz = None + else: + for path in TZPATHS: + filepath = os.path.join(path, name) + if not os.path.isfile(filepath): + filepath = filepath.replace(' ','_') + if not os.path.isfile(filepath): + continue + try: + tz = tzfile(filepath) + break + except (IOError, OSError, ValueError): + pass + else: + tz = None + if tzwin: + try: + tz = tzwin(name) + except OSError: + pass + if not tz: + from dateutil.zoneinfo import gettz + tz = gettz(name) + if not tz: + for c in name: + # name must have at least one offset to be a tzstr + if c in "0123456789": + try: + tz = tzstr(name) + except ValueError: + pass + break + else: + if name in ("GMT", "UTC"): + tz = tzutc() + elif name in time.tzname: + tz = tzlocal() + return tz + +# vim:ts=4:sw=4:et diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/tzwin.py b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/tzwin.py new file mode 100644 index 0000000..073e0ff --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/tzwin.py @@ -0,0 +1,180 @@ +# This code was originally contributed by Jeffrey Harris. +import datetime +import struct +import _winreg + +__author__ = "Jeffrey Harris & Gustavo Niemeyer " + +__all__ = ["tzwin", "tzwinlocal"] + +ONEWEEK = datetime.timedelta(7) + +TZKEYNAMENT = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones" +TZKEYNAME9X = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Time Zones" +TZLOCALKEYNAME = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation" + +def _settzkeyname(): + global TZKEYNAME + handle = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE) + try: + _winreg.OpenKey(handle, TZKEYNAMENT).Close() + TZKEYNAME = TZKEYNAMENT + except WindowsError: + TZKEYNAME = TZKEYNAME9X + handle.Close() + +_settzkeyname() + +class tzwinbase(datetime.tzinfo): + """tzinfo class based on win32's timezones available in the registry.""" + + def utcoffset(self, dt): + if self._isdst(dt): + return datetime.timedelta(minutes=self._dstoffset) + else: + return datetime.timedelta(minutes=self._stdoffset) + + def dst(self, dt): + if self._isdst(dt): + minutes = self._dstoffset - self._stdoffset + return datetime.timedelta(minutes=minutes) + else: + return datetime.timedelta(0) + + def tzname(self, dt): + if self._isdst(dt): + return self._dstname + else: + return self._stdname + + def list(): + """Return a list of all time zones known to the system.""" + handle = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE) + tzkey = _winreg.OpenKey(handle, TZKEYNAME) + result = [_winreg.EnumKey(tzkey, i) + for i in range(_winreg.QueryInfoKey(tzkey)[0])] + tzkey.Close() + handle.Close() + return result + list = staticmethod(list) + + def display(self): + return self._display + + def _isdst(self, dt): + dston = picknthweekday(dt.year, self._dstmonth, self._dstdayofweek, + self._dsthour, self._dstminute, + self._dstweeknumber) + dstoff = picknthweekday(dt.year, self._stdmonth, self._stddayofweek, + self._stdhour, self._stdminute, + self._stdweeknumber) + if dston < dstoff: + return dston <= dt.replace(tzinfo=None) < dstoff + else: + return not dstoff <= dt.replace(tzinfo=None) < dston + + +class tzwin(tzwinbase): + + def __init__(self, name): + self._name = name + + handle = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE) + tzkey = _winreg.OpenKey(handle, "%s\%s" % (TZKEYNAME, name)) + keydict = valuestodict(tzkey) + tzkey.Close() + handle.Close() + + self._stdname = keydict["Std"].encode("iso-8859-1") + self._dstname = keydict["Dlt"].encode("iso-8859-1") + + self._display = keydict["Display"] + + # See http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm + tup = struct.unpack("=3l16h", keydict["TZI"]) + self._stdoffset = -tup[0]-tup[1] # Bias + StandardBias * -1 + self._dstoffset = self._stdoffset-tup[2] # + DaylightBias * -1 + + (self._stdmonth, + self._stddayofweek, # Sunday = 0 + self._stdweeknumber, # Last = 5 + self._stdhour, + self._stdminute) = tup[4:9] + + (self._dstmonth, + self._dstdayofweek, # Sunday = 0 + self._dstweeknumber, # Last = 5 + self._dsthour, + self._dstminute) = tup[12:17] + + def __repr__(self): + return "tzwin(%s)" % repr(self._name) + + def __reduce__(self): + return (self.__class__, (self._name,)) + + +class tzwinlocal(tzwinbase): + + def __init__(self): + + handle = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE) + + tzlocalkey = _winreg.OpenKey(handle, TZLOCALKEYNAME) + keydict = valuestodict(tzlocalkey) + tzlocalkey.Close() + + self._stdname = keydict["StandardName"].encode("iso-8859-1") + self._dstname = keydict["DaylightName"].encode("iso-8859-1") + + try: + tzkey = _winreg.OpenKey(handle, "%s\%s"%(TZKEYNAME, self._stdname)) + _keydict = valuestodict(tzkey) + self._display = _keydict["Display"] + tzkey.Close() + except OSError: + self._display = None + + handle.Close() + + self._stdoffset = -keydict["Bias"]-keydict["StandardBias"] + self._dstoffset = self._stdoffset-keydict["DaylightBias"] + + + # See http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm + tup = struct.unpack("=8h", keydict["StandardStart"]) + + (self._stdmonth, + self._stddayofweek, # Sunday = 0 + self._stdweeknumber, # Last = 5 + self._stdhour, + self._stdminute) = tup[1:6] + + tup = struct.unpack("=8h", keydict["DaylightStart"]) + + (self._dstmonth, + self._dstdayofweek, # Sunday = 0 + self._dstweeknumber, # Last = 5 + self._dsthour, + self._dstminute) = tup[1:6] + + def __reduce__(self): + return (self.__class__, ()) + +def picknthweekday(year, month, dayofweek, hour, minute, whichweek): + """dayofweek == 0 means Sunday, whichweek 5 means last instance""" + first = datetime.datetime(year, month, 1, hour, minute) + weekdayone = first.replace(day=((dayofweek-first.isoweekday())%7+1)) + for n in xrange(whichweek): + dt = weekdayone+(whichweek-n)*ONEWEEK + if dt.month == month: + return dt + +def valuestodict(key): + """Convert a registry key's values to a dictionary.""" + dict = {} + size = _winreg.QueryInfoKey(key)[1] + for i in range(size): + data = _winreg.EnumValue(key, i) + dict[data[0]] = data[1] + return dict diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/zoneinfo/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/zoneinfo/__init__.py new file mode 100644 index 0000000..9bed626 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/zoneinfo/__init__.py @@ -0,0 +1,87 @@ +""" +Copyright (c) 2003-2005 Gustavo Niemeyer + +This module offers extensions to the standard python 2.3+ +datetime module. +""" +from dateutil.tz import tzfile +from tarfile import TarFile +import os + +__author__ = "Gustavo Niemeyer " +__license__ = "PSF License" + +__all__ = ["setcachesize", "gettz", "rebuild"] + +CACHE = [] +CACHESIZE = 10 + +class tzfile(tzfile): + def __reduce__(self): + return (gettz, (self._filename,)) + +def getzoneinfofile(): + filenames = os.listdir(os.path.join(os.path.dirname(__file__))) + filenames.sort() + filenames.reverse() + for entry in filenames: + if entry.startswith("zoneinfo") and ".tar." in entry: + return os.path.join(os.path.dirname(__file__), entry) + return None + +ZONEINFOFILE = getzoneinfofile() + +del getzoneinfofile + +def setcachesize(size): + global CACHESIZE, CACHE + CACHESIZE = size + del CACHE[size:] + +def gettz(name): + tzinfo = None + if ZONEINFOFILE: + for cachedname, tzinfo in CACHE: + if cachedname == name: + break + else: + tf = TarFile.open(ZONEINFOFILE) + try: + zonefile = tf.extractfile(name) + except KeyError: + tzinfo = None + else: + tzinfo = tzfile(zonefile) + tf.close() + CACHE.insert(0, (name, tzinfo)) + del CACHE[CACHESIZE:] + return tzinfo + +def rebuild(filename, tag=None, format="gz"): + import tempfile, shutil + tmpdir = tempfile.mkdtemp() + zonedir = os.path.join(tmpdir, "zoneinfo") + moduledir = os.path.dirname(__file__) + if tag: tag = "-"+tag + targetname = "zoneinfo%s.tar.%s" % (tag, format) + try: + tf = TarFile.open(filename) + for name in tf.getnames(): + if not (name.endswith(".sh") or + name.endswith(".tab") or + name == "leapseconds"): + tf.extract(name, tmpdir) + filepath = os.path.join(tmpdir, name) + os.system("zic -d %s %s" % (zonedir, filepath)) + tf.close() + target = os.path.join(moduledir, targetname) + for entry in os.listdir(moduledir): + if entry.startswith("zoneinfo") and ".tar." in entry: + os.unlink(os.path.join(moduledir, entry)) + tf = TarFile.open(target, "w:%s" % format) + for entry in os.listdir(zonedir): + entrypath = os.path.join(zonedir, entry) + tf.add(entrypath, entry) + tf.close() + finally: + shutil.rmtree(tmpdir) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/zoneinfo/zoneinfo-2010g.tar.gz b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/zoneinfo/zoneinfo-2010g.tar.gz new file mode 100644 index 0000000..8bd4f96 Binary files /dev/null and b/interactive-mining-3rdparty-madis/madis/src/lib/dateutil/zoneinfo/zoneinfo-2010g.tar.gz differ diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/dsv.py b/interactive-mining-3rdparty-madis/madis/src/lib/dsv.py new file mode 100644 index 0000000..3c5f587 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/dsv.py @@ -0,0 +1,232 @@ +import csv +import codecs +import cStringIO + +""" +Differences from csv.reader module +Default dialect: SQLITE TABS DUMP +encoding parameter (default utf-8) +delimiter can be a multicaharacter string - given as extra parameter , not in dialect +......BUT IF YOUR FILE HAS THE chr(30) character(apart the delimiter) it will be disaster (or if encoding is multibyte )!!!!!!!! +""" + +#many string delimiter!!! + +class sqlitedmp(csv.Dialect): + def __init__(self): + self.delimiter="\t" + #self.doublequote=True + self.quotechar=None + self.quoting=csv.QUOTE_NONE + #self.quotechar='"' + #self.quoting=csv.QUOTE_MINIMAL + self.lineterminator='\n' + +SQLITE_DIALECT=sqlitedmp() + +class Onedel: + def __init__(self,reader,big,one): + self.reader=reader + self.big=big + self.one=one + def next(self): + return self.reader.next().replace(self.big,self.one) + def __iter__(self): + return self + +#delimiter seperated values + + +class writer: + """ + A CSV writer with default dialect sqlite dump files and utf8 encoding, NO multicharacter delimiter + """ + def __init__(self,tsvfile,dialect=SQLITE_DIALECT,encoding="utf_8",**kwds): + self.writer=UnicodeWriter(tsvfile,dialect,encoding,**kwds) + def writerow(self,row): + self.writer.writerow(row) + def writerows(self,rows): + self.writer.writerows(rows) + +class reader: + """ + A CSV reader which will iterate over lines in the CSV file "tsvfile", + which is encoded in the given encoding. + (with default dialect sqlite dump files and utf8 encoding, multicharacter delimiter YES) + """ + def __init__(self,tsvfile,hasheader=False,dialect=SQLITE_DIALECT,encoding="utf_8",**kwds): + self.hasheader=hasheader + self.fast = False + if not hasheader: + self.reader=UnicodeReader(tsvfile,dialect,encoding,**kwds) + else: + self.reader=UnicodeDictReader(tsvfile,dialect,encoding,**kwds) + + def __iter__(self): + return self.reader + + def fieldnames(self): + return None + +class UTF8Recoder: + """ + Iterator that reads an encoded stream and reencodes the input to UTF-8 + """ + def __init__(self, f, encoding): + self.reader = codecs.iterdecode(f, encoding, 'replace') + self.encoding = encoding.lower() + self.f = f + + def __iter__(self): + # Shortcircuit for default case + if self.encoding == 'utf_8': + return self.f + return self + + def next(self): + return self.reader.next().encode("utf_8") + +class UnicodeReader: + """ + A CSV reader which will iterate over lines in the CSV file "f", + which is encoded in the given encoding. + To accept multicharacter delimiters a temporal replacement with ~ character happens + """ + + def __init__(self, f, dialect=csv.excel, encoding="utf_8", **kwds): + f = UTF8Recoder(f, encoding) + self.replace=False + if 'delimiter' in kwds and len(kwds['delimiter'])>1: + self.replace=True + self.mdel=chr(30) + self.big=kwds['delimiter'] + kwds['delimiter']=self.mdel + self.reader = csv.reader(Onedel(f,self.big,self.mdel), dialect=dialect, **kwds) + self.next = self.nextwithreplace + else: + self.reader = csv.reader(f, dialect=dialect, **kwds) + + def next(self): + return [unicode(s, "utf_8") for s in self.reader.next()] + + def nextwithreplace(self): + return [unicode(s.replace(self.mdel,self.big), "utf_8") for s in self.reader.next()] + + def __iter__(self): + return self + + def fieldnames(self): + return None + +class UnicodeDictReader: + """ + A CSV reader which will iterate over lines in the CSV file "f", + which is encoded in the given encoding. + To accept multicharacter delimiters a temporal replacement with ~ character happens + """ + + def __init__(self, f, dialect=csv.excel, encoding="utf_8", **kwds): + f = UTF8Recoder(f, encoding) + self.replace=False + if 'delimiter' in kwds and len(kwds['delimiter'])>1: + self.replace=True + self.mdel=chr(30) + self.big=kwds['delimiter'] + kwds['delimiter']=self.mdel + self.reader = csv.reader(Onedel(f,self.big,self.mdel), dialect=dialect, **kwds) + else: + self.reader = csv.reader(f, dialect=dialect, **kwds) + self.fields=None + + def __readheader(self): + if not self.fields: + row = self.reader.next() + self.fields=[unicode(s, "utf_8") for s in row] + + def next(self): + if not self.fields: + self.__readheader() + row = self.reader.next() + rowdict=dict() + if self.replace: + for field,cell in zip(self.fields,row): + rowdict[field]=unicode(cell.replace(self.mdel,self.big), "utf_8") + else: + for field,cell in zip(self.fields,row): + rowdict[field]=unicode(cell, "utf_8") + + return rowdict + + def fieldnames(self): + if not self.fields: + self.__readheader() + return self.fields + + def __iter__(self): + return self + +def anytouni(i): + if i is None: + return u'null' + if isinstance(i,str): + return unicode(i) + elif not isinstance(i,basestring): + return unicode(repr(i)) + else: + return i + return unirow + + + + +##one delimiter only +class UnicodeWriter: + """ + A CSV writer which will write rows to CSV file "f", + which is encoded in the given encoding. + """ + + def __init__(self, f, dialect=csv.excel, encoding="utf_8", **kwds): + # Redirect output to a queue + self.queue = cStringIO.StringIO() + self.writer = csv.writer(self.queue, dialect=dialect, **kwds) + self.stream = f + self.encoder = codecs.getincrementalencoder(encoding)() + + def writerow(self, row): + self.writer.writerow([anytouni(s).encode("utf_8") for s in row]) + # Fetch UTF-8 output from the queue ... + data = self.queue.getvalue() + data = data.decode("utf_8") + # ... and reencode it into the target encoding + data = self.encoder.encode(data) + # write to the target stream + self.stream.write(data) + # empty queue + self.queue.truncate(0) + + def writerows(self, rows): + for row in rows: + self.writerow(row) + + + + +def main(): + import sys + import time + fname='partheaders.tsv' + print "Test file %s" %(fname) + print >> sys.stderr , time.strftime("%Y-%m-%d %H:%M:%S"),"\tBEGIN" + + with open('partheaders.tsv') as f: + p=reader(f,hasheader=True) + for line in p: + print line + print >> sys.stderr , time.strftime("%Y-%m-%d %H:%M:%S"),"\tEND" + + + +if __name__ == "__main__": + main() + \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/NOTICE.txt b/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/NOTICE.txt new file mode 100644 index 0000000..acadea2 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/NOTICE.txt @@ -0,0 +1,14 @@ +fastavro is a derivative work of Apache AVRO, below is the original NOTICE.txt +from the Apache Avro (http://svn.apache.org/viewvc/avro/trunk) + +------------------------------------------------------------ +Apache Avro +Copyright 2010 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + +C JSON parsing provided by Jansson and +written by Petri Lehtinen. The original software is +available from http://www.digip.org/jansson/. +------------------------------------------------------------ diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/PKG-INFO b/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/PKG-INFO new file mode 100644 index 0000000..bf4a903 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/PKG-INFO @@ -0,0 +1,122 @@ +Metadata-Version: 1.1 +Name: fastavro +Version: 0.7.9 +Summary: Fast iteration of AVRO files +Home-page: https://bitbucket.org/tebeka/fastavro +Author: Miki Tebeka +Author-email: miki.tebeka@gmail.com +License: MIT +Description: fastavro + ======== + + The current Python `avro` package is packed with features but dog slow. + + On a test case of about 10K records, it takes about 14sec to iterate over all of + them. In comparison the JAVA `avro` SDK does it in about 1.9sec. + + `fastavro` is less feature complete than `avro`, however it's much faster. It + iterates over the same 10K records in 2.9sec, and if you use it with PyPy it'll + do it in 1.5sec (to be fair, the JAVA benchmark is doing some extra JSON + encoding/decoding). + + If the optional C extension (generated by `Cython`_) is available, then + `fastavro` will be even faster. For the same 10K records it'll run in about + 1.7sec. + + .. _`Cython`: http://cython.org/ + + .. image:: http://i.imgur.com/lg9rx9w.png + :alt: gittip + :target: https://www.gittip.com/Miki%20Tebeka/ + + + Usage + ===== + :: + + import fastavro as avro + + with open('weather.avro', 'rb') as fo: + reader = avro.reader(fo) + schema = reader.schema + + for record in reader: + process_record(record) + + You can also use the `fastavro` script from the command line to dump `avro` + files. + :: + + fastavro weather.avro + + By default fastavro prints one JSON object per line, you can use the `--pretty` + flag to change this. + + You can also dump the avro schema:: + + fastavro --schema weather.avro + + + Here's the full command line help + + :: + + usage: fastavro [-h] [--schema] [--codecs] [--version] [-p] [file [file ...]] + + iter over avro file, emit records as JSON + + positional arguments: + file file(s) to parse + + optional arguments: + -h, --help show this help message and exit + --schema dump schema instead of records + --codecs print supported codecs + --version show program's version number and exit + -p, --pretty pretty print json + + Limitations + =========== + * Support only iteration + - No writing for you! + * No reader schema + + Hacking + ======= + As recommended by Cython, the C files output is distributed. This has the + advantage that the end user does not need to have Cython installed. However it + means that every time you change `fastavro/pyfastavro.py` you need to run + `make`. + + For `make` to succeed you need both python and python3 installed, cython on both + of them. For `./test-install.sh` you'll need virtualenv_. + + .. _virtualenv: http://pypi.python.org/pypi/virtualenv + + Builds + ====== + We're currently using `travis.ci`_ + + .. _`travis.ci`: http://travis-ci.org/#!/tebeka/fastavro + + + Changes + ======= + See the ChangeLog_ + + .. _ChangeLog: https://bitbucket.org/tebeka/fastavro/raw/tip/ChangeLog + + Contact + ======= + Miki Tebeka + https://bitbucket.org/tebeka/fastavro + +Platform: UNKNOWN +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 +Classifier: Topic :: Software Development :: Libraries +Classifier: Topic :: Software Development :: Libraries :: Python Modules diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/__init__.py new file mode 100644 index 0000000..98c53e9 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/__init__.py @@ -0,0 +1,31 @@ +'''Fast Avro file iteration. + +Most of the code here is ripped off the Python avro package. It's missing a lot +of features in order to get speed. + +The only onterface function is iter_avro, example usage:: + + import fastavro as avro + + with open('some-file.avro', 'rb') as fo: + reader = fastavro.reader(fo) + schema = reader.schema + + for record in reader: + process_record(record) +''' + +__all__ = ['iter_avro', 'reader'] +__version__ = '0.7.9' + + +try: + from . import _reader + from . import _writer +except ImportError as e: + from . import reader as _reader + from . import writer as _writer + +reader = iter_avro = _reader.iter_avro +load = _reader.read_data +write = _writer.write diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/__main__.py b/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/__main__.py new file mode 100644 index 0000000..e6c2d66 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/__main__.py @@ -0,0 +1,62 @@ +import fastavro as avro +from fastavro.six import json_dump +from sys import stdout + +encoding = stdout.encoding or "UTF-8" + + +def main(argv=None): + import sys + from argparse import ArgumentParser + + argv = argv or sys.argv + + parser = ArgumentParser( + description='iter over avro file, emit records as JSON') + parser.add_argument('file', help='file(s) to parse', nargs='*') + parser.add_argument('--schema', help='dump schema instead of records', + action='store_true', default=False) + parser.add_argument('--codecs', help='print supported codecs', + action='store_true', default=False) + parser.add_argument('--version', action='version', + version='fastavro {0}'.format(avro.__version__)) + parser.add_argument('-p', '--pretty', help='pretty print json', + action='store_true', default=False) + args = parser.parse_args(argv[1:]) + + if args.codecs: + import fastavro + print('\n'.join(sorted(fastavro._reader.BLOCK_READERS))) + raise SystemExit + + files = args.file or ['-'] + for filename in files: + if filename == '-': + fo = sys.stdin + else: + try: + fo = open(filename, 'rb') + except IOError as e: + raise SystemExit( + 'error: cannot open {0} - {1}'.format(filename, e)) + + try: + reader = avro.reader(fo) + except ValueError as e: + raise SystemExit('error: {0}'.format(e)) + + if args.schema: + json_dump(reader.schema, True) + sys.stdout.write('\n') + continue + + indent = 4 if args.pretty else None + try: + for record in reader: + json_dump(record, indent) + sys.stdout.write('\n') + except (IOError, KeyboardInterrupt): + pass + +if __name__ == '__main__': + main() diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/reader.py b/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/reader.py new file mode 100644 index 0000000..542336e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/reader.py @@ -0,0 +1,380 @@ +# cython: auto_cpdef=True + +'''Python code for reading AVRO files''' + +# This code is a modified version of the code at +# http://svn.apache.org/viewvc/avro/trunk/lang/py/src/avro/ which is under +# Apache 2.0 license (http://www.apache.org/licenses/LICENSE-2.0) + +import json +from os import SEEK_CUR +from struct import pack, unpack +from zlib import decompress +try: + from ._six import MemoryIO, xrange, btou +except ImportError: + from .six import MemoryIO, xrange, btou + +VERSION = 1 +MAGIC = 'Obj' + chr(VERSION) +SYNC_SIZE = 16 +HEADER_SCHEMA = { + 'type': 'record', + 'name': 'org.apache.avro.file.Header', + 'fields': [ + { + 'name': 'magic', + 'type': {'type': 'fixed', 'name': 'magic', 'size': len(MAGIC)}, + }, + { + 'name': 'meta', + 'type': {'type': 'map', 'values': 'bytes'} + }, + { + 'name': 'sync', + 'type': {'type': 'fixed', 'name': 'sync', 'size': SYNC_SIZE} + }, + ] +} +MASK = 0xFF + + +def read_null(fo, schema): + '''null is written as zero bytes.''' + return None + + +def read_boolean(fo, schema): + '''A boolean is written as a single byte whose value is either 0 (false) or + 1 (true). + ''' + return ord(fo.read(1)) == 1 + + +def read_long(fo, schema): + '''int and long values are written using variable-length, zig-zag + coding.''' + c = fo.read(1) + + # We do EOF checking only here, since most reader start here + if not c: + raise StopIteration + + b = ord(c) + n = b & 0x7F + shift = 7 + + while (b & 0x80) != 0: + b = ord(fo.read(1)) + n |= (b & 0x7F) << shift + shift += 7 + + return (n >> 1) ^ -(n & 1) + + +def read_float(fo, schema): + '''A float is written as 4 bytes. + + The float is converted into a 32-bit integer using a method equivalent to + Java's floatToIntBits and then encoded in little-endian format. + ''' + bits = (((ord(fo.read(1)) & MASK)) | + ((ord(fo.read(1)) & MASK) << 8) | + ((ord(fo.read(1)) & MASK) << 16) | + ((ord(fo.read(1)) & MASK) << 24)) + + return unpack('!f', pack('!I', bits))[0] + + +def read_double(fo, schema): + '''A double is written as 8 bytes. + + The double is converted into a 64-bit integer using a method equivalent to + Java's doubleToLongBits and then encoded in little-endian format. + ''' + bits = (((ord(fo.read(1)) & MASK)) | + ((ord(fo.read(1)) & MASK) << 8) | + ((ord(fo.read(1)) & MASK) << 16) | + ((ord(fo.read(1)) & MASK) << 24) | + ((ord(fo.read(1)) & MASK) << 32) | + ((ord(fo.read(1)) & MASK) << 40) | + ((ord(fo.read(1)) & MASK) << 48) | + ((ord(fo.read(1)) & MASK) << 56)) + + return unpack('!d', pack('!Q', bits))[0] + + +def read_bytes(fo, schema): + '''Bytes are encoded as a long followed by that many bytes of data.''' + size = read_long(fo, schema) + return fo.read(size) + + +def read_utf8(fo, schema): + '''A string is encoded as a long followed by that many bytes of UTF-8 + encoded character data. + ''' + return btou(read_bytes(fo, schema), 'utf-8') + + +def read_fixed(fo, schema): + '''Fixed instances are encoded using the number of bytes declared in the + schema.''' + return fo.read(schema['size']) + + +def read_enum(fo, schema): + '''An enum is encoded by a int, representing the zero-based position of the + symbol in the schema. + ''' + return schema['symbols'][read_long(fo, schema)] + + +def read_array(fo, schema): + '''Arrays are encoded as a series of blocks. + + Each block consists of a long count value, followed by that many array + items. A block with count zero indicates the end of the array. Each item + is encoded per the array's item schema. + + If a block's count is negative, then the count is followed immediately by a + long block size, indicating the number of bytes in the block. The actual + count in this case is the absolute value of the count written. + ''' + read_items = [] + + block_count = read_long(fo, schema) + + while block_count != 0: + if block_count < 0: + block_count = -block_count + # Read block size, unused + read_long(fo, schema) + + for i in xrange(block_count): + read_items.append(read_data(fo, schema['items'])) + block_count = read_long(fo, schema) + + return read_items + + +def read_map(fo, schema): + '''Maps are encoded as a series of blocks. + + Each block consists of a long count value, followed by that many key/value + pairs. A block with count zero indicates the end of the map. Each item is + encoded per the map's value schema. + + If a block's count is negative, then the count is followed immediately by a + long block size, indicating the number of bytes in the block. The actual + count in this case is the absolute value of the count written. + ''' + read_items = {} + block_count = read_long(fo, schema) + while block_count != 0: + if block_count < 0: + block_count = -block_count + # Read block size, unused + read_long(fo, schema) + + for i in range(block_count): + key = read_utf8(fo, schema) + read_items[key] = read_data(fo, schema['values']) + block_count = read_long(fo, schema) + + return read_items + + +def read_union(fo, schema): + '''A union is encoded by first writing a long value indicating the + zero-based position within the union of the schema of its value. + + The value is then encoded per the indicated schema within the union. + ''' + # schema resolution + index = read_long(fo, schema) + return read_data(fo, schema[index]) + + +def read_record(fo, schema): + '''A record is encoded by encoding the values of its fields in the order + that they are declared. In other words, a record is encoded as just the + concatenation of the encodings of its fields. Field values are encoded per + their schema. + + Schema Resolution: + * the ordering of fields may be different: fields are matched by name. + * schemas for fields with the same name in both records are resolved + recursively. + * if the writer's record contains a field with a name not present in the + reader's record, the writer's value for that field is ignored. + * if the reader's record schema has a field that contains a default value, + and writer's schema does not have a field with the same name, then the + reader should use the default value from its field. + * if the reader's record schema has a field with no default value, and + writer's schema does not have a field with the same name, then the + field's value is unset. + ''' + record = {} + for field in schema['fields']: + record[field['name']] = read_data(fo, field['type']) + + return record + +READERS = { + 'null': read_null, + 'boolean': read_boolean, + 'string': read_utf8, + 'int': read_long, + 'long': read_long, + 'float': read_float, + 'double': read_double, + 'bytes': read_bytes, + 'fixed': read_fixed, + 'enum': read_enum, + 'array': read_array, + 'map': read_map, + 'union': read_union, + 'error_union': read_union, + 'record': read_record, + 'error': read_record, + 'request': read_record, +} + + +def read_data(fo, schema): + '''Read data from file object according to schema.''' + st = type(schema) + if st is dict: + record_type = schema['type'] + elif st is list: + record_type = 'union' + else: + record_type = schema + + reader = READERS[record_type] + return reader(fo, schema) + + +def skip_sync(fo, sync_marker): + '''Skip sync marker, might raise StopIteration.''' + mark = fo.read(SYNC_SIZE) + + if not mark: + raise StopIteration + + if mark != sync_marker: + fo.seek(-SYNC_SIZE, SEEK_CUR) + + +def null_read_block(fo): + '''Read block in "null" codec.''' + read_long(fo, None) + return fo + + +def deflate_read_block(fo): + '''Read block in "deflate" codec.''' + data = read_bytes(fo, None) + # -15 is the log of the window size; negative indicates "raw" (no + # zlib headers) decompression. See zlib.h. + return MemoryIO(decompress(data, -15)) + +BLOCK_READERS = { + 'null': null_read_block, + 'deflate': deflate_read_block +} + +try: + import snappy + + def snappy_read_block(fo): + length = read_long(fo, None) + data = fo.read(length - 4) + fo.read(4) # CRC + return MemoryIO(snappy.decompress(data)) + + BLOCK_READERS['snappy'] = snappy_read_block +except ImportError: + pass + + +def _iter_avro(fo, header, schema): + '''Return iterator over avro records.''' + sync_marker = header['sync'] + # Value in schema is bytes + codec = header['meta'].get('avro.codec') + codec = btou(codec) if codec else 'null' + + read_block = BLOCK_READERS.get(codec) + if not read_block: + raise ValueError('unknown codec: {0}'.format(codec)) + + block_count = 0 + while True: + skip_sync(fo, sync_marker) + block_count = read_long(fo, None) + block_fo = read_block(fo) + + for i in xrange(block_count): + yield read_data(block_fo, schema) + + +def schema_name(schema): + name = schema.get('name') + if not name: + return + namespace = schema.get('namespace') + if not namespace: + return name + + return namespace + '.' + name + + +def extract_named(schema): + '''Inject named schemas into READERS.''' + if type(schema) == list: + for enum in schema: + extract_named(enum) + return + + if type(schema) != dict: + return + + name = schema_name(schema) + if name and (name not in READERS): + READERS[name] = lambda fo, _: read_data(fo, schema) + + for field in schema.get('fields', []): + extract_named(field['type']) + + +class iter_avro: + '''Custom iterator over avro file. + + Example: + with open('some-file.avro', 'rb') as fo: + avro = iter_avro(fo) + schema = avro.schema + + for record in avro: + process_record(record) + ''' + def __init__(self, fo): + self.fo = fo + try: + self._header = read_data(fo, HEADER_SCHEMA) + except StopIteration: + raise ValueError('cannot read header - is it an avro file?') + + self.schema = schema = \ + json.loads(btou(self._header['meta']['avro.schema'])) + + extract_named(schema) + self._records = _iter_avro(fo, self._header, schema) + + def __iter__(self): + return self._records + + def next(self): + return next(self._records) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/six.py b/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/six.py new file mode 100644 index 0000000..94da205 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/six.py @@ -0,0 +1,55 @@ +# cython: auto_cpdef=True + +'''Compatiblity for Python versions. + +Some of this code is "lifted" from CherryPy. +''' +import sys +import json +from sys import stdout + +_encoding = 'UTF-8' + +if sys.version_info >= (3, 0): + from io import BytesIO as MemoryIO + xrange = range + + def py3_btou(n, encoding=_encoding): + return n.decode(encoding) + + def py3_utob(n, encoding=_encoding): + return bytes(n, encoding) + + unicode = str + long = int + + def py3_json_dump(obj, indent): + json.dump(obj, stdout, indent=indent) + +else: # Python 2x + from cStringIO import StringIO as MemoryIO # NOQA + xrange = xrange + + def py2_btou(n, encoding=_encoding): + return unicode(n, 'utf_8') + + def py2_utob(n, encoding=_encoding): + return n + + unicode = unicode + long = long + + _outenc = getattr(stdout, 'encoding', None) or _encoding + + def py2_json_dump(obj, indent): + json.dump(obj, stdout, indent=indent, encoding=_outenc) + +# We do it this way and not just redifine function since Cython do not like it +if sys.version_info >= (3, 0): + btou = py3_btou + utob = py3_utob + json_dump = py3_json_dump +else: + btou = py2_btou + utob = py2_utob + json_dump = py2_json_dump diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/writer.py b/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/writer.py new file mode 100644 index 0000000..50451a5 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/fastavro/writer.py @@ -0,0 +1,260 @@ +# cython: auto_cpdef=True + +'''Python code for writing AVRO files''' + +# This code is a modified version of the code at +# http://svn.apache.org/viewvc/avro/trunk/lang/py/src/avro/ which is under +# Apache 2.0 license (http://www.apache.org/licenses/LICENSE-2.0) + +try: + from ._six import utob, unicode, MemoryIO, long + from ._reader import MASK, HEADER_SCHEMA, SYNC_SIZE, MAGIC +except ImportError: + from .six import utob, unicode, MemoryIO, long + from .reader import MASK, HEADER_SCHEMA, SYNC_SIZE, MAGIC + +from binascii import crc32 +from os import urandom, SEEK_SET +from struct import pack, unpack +import json + +NoneType = type(None) + + +def write_null(fo, datum, schema=None): + '''null is written as zero bytes''' + pass + + +def write_boolean(fo, datum, schema=None): + '''A boolean is written as a single byte whose value is either 0 (false) or + 1 (true).''' + fo.write(chr(1) if datum else chr(0)) + + +def write_int(fo, datum, schema=None): + '''int and long values are written using variable-length, zig-zag coding. + ''' + datum = (datum << 1) ^ (datum >> 63) + while (datum & ~0x7F) != 0: + fo.write(chr((datum & 0x7f) | 0x80)) + datum >>= 7 + fo.write(chr(datum)) + +write_long = write_int + + +def write_float(fo, datum, schema=None): + '''A float is written as 4 bytes. The float is converted into a 32-bit + integer using a method equivalent to Java's floatToIntBits and then encoded + in little-endian format.''' + bits = unpack('!I', pack('!f', datum))[0] + + fo.write(chr((bits) & MASK)) + fo.write(chr((bits >> 8) & MASK)) + fo.write(chr((bits >> 16) & MASK)) + fo.write(chr((bits >> 24) & MASK)) + + +def write_double(fo, datum, schema=None): + '''A double is written as 8 bytes. The double is converted into a 64-bit + integer using a method equivalent to Java's doubleToLongBits and then + encoded in little-endian format. ''' + bits = unpack('!Q', pack('!d', datum))[0] + + fo.write(chr((bits) & MASK)) + fo.write(chr((bits >> 8) & MASK)) + fo.write(chr((bits >> 16) & MASK)) + fo.write(chr((bits >> 24) & MASK)) + fo.write(chr((bits >> 32) & MASK)) + fo.write(chr((bits >> 40) & MASK)) + fo.write(chr((bits >> 48) & MASK)) + fo.write(chr((bits >> 56) & MASK)) + + +def write_bytes(fo, datum, schema=None): + '''Bytes are encoded as a long followed by that many bytes of data.''' + write_long(fo, len(datum)) + fmt = '{}s'.format(len(datum)) + fo.write(pack(fmt, datum)) + + +def write_utf8(fo, datum, schema=None): + '''A string is encoded as a long followed by that many bytes of UTF-8 + encoded character data.''' + datum = utob(datum) + write_bytes(fo, datum) + + +def write_crc32(fo, bytes): + '''A 4-byte, big-endian CRC32 checksum''' + data = crc32(bytes) & 0xFFFFFFFF + fo.write(pack('>I', data)) + + +def write_fixed(fo, datum, schema=None): + '''Fixed instances are encoded using the number of bytes declared in the + schema.''' + fo.write(datum) + + +def write_enum(fo, datum, schema): + """An enum is encoded by a int, representing the zero-based position of + the symbol in the schema.""" + index = schema['symbols'].index(datum) + write_int(fo, index) + + +def write_array(fo, datum, schema): + """Arrays are encoded as a series of blocks. + + Each block consists of a long count value, followed by that many array + items. A block with count zero indicates the end of the array. Each item + is encoded per the array's item schema. + + If a block's count is negative, then the count is followed immediately by a + long block size, indicating the number of bytes in the block. The actual + count in this case is the absolute value of the count written. """ + + if not datum: + return + + dtype = schema['items'] + write_long(fo, len(datum)) + for item in datum: + write_data(fo, item, dtype) + write_long(fo, 0) + + +def write_map(fo, datum, schema): + """Maps are encoded as a series of blocks. + + Each block consists of a long count value, followed by that many key/value + pairs. A block with count zero indicates the end of the map. Each item is + encoded per the map's value schema. + + If a block's count is negative, then the count is followed immediately by a + long block size, indicating the number of bytes in the block. The actual + count in this case is the absolute value of the count written.""" + if not datum: + return + + vtype = schema['values'] + write_long(fo, len(datum)) + for key, val in datum.iteritems(): + write_utf8(fo, key) + write_data(fo, val, vtype) + write_long(fo, 0) + + +typeconv = { + 'null': set([NoneType]), + 'boolean': set([bool]), + 'string': set([str, unicode]), + 'bytes': set([bytes]), + 'int': set([int, long]), + 'long': set([int, long]), + 'float': set([int, long, float]), + 'double': set([int, long, float]), +} + + +def write_union(fo, datum, schema): + """A union is encoded by first writing a long value indicating the + zero-based position within the union of the schema of its value. The value + is then encoded per the indicated schema within the union.""" + + pytype = type(datum) + for index, atype in enumerate(schema): + if pytype in typeconv[atype]: + break + else: + raise ValueError('{} (type {}) do not match {}'.format( + datum, pytype, schema)) + + # write data + write_long(fo, index) + write_data(fo, datum, schema[index]) + + +def write_record(fo, datum, schema): + """A record is encoded by encoding the values of its fields in the order + that they are declared. In other words, a record is encoded as just the + concatenation of the encodings of its fields. Field values are encoded per + their schema.""" + for field in schema['fields']: + write_data(fo, datum[field['name']], field['type']) + + +WRITERS = { + 'null': write_null, + 'boolean': write_boolean, + 'string': write_utf8, + 'int': write_long, + 'long': write_long, + 'float': write_float, + 'double': write_double, + 'bytes': write_bytes, + 'fixed': write_fixed, + 'enum': write_enum, + 'array': write_array, + 'map': write_map, + 'union': write_union, + 'error_union': write_union, + 'record': write_record, +} + + +def write_data(fo, datum, schema): + '''Write data to file object according to schema.''' + st = type(schema) + if st is dict: + record_type = schema['type'] + elif st is list: + record_type = 'union' + else: + record_type = schema + + writer = WRITERS[record_type] + return writer(fo, datum, schema) + + +def write_header(fo, schema, sync_marker): + header = { + 'magic': MAGIC, + 'meta': { + 'avro.codec': 'null', # FIXME: Compression + 'avro.schema': utob(json.dumps(schema)), + }, + 'sync': sync_marker + } + write_data(fo, header, HEADER_SCHEMA) + + +def write(fo, schema, records): + sync_marker = urandom(SYNC_SIZE) + write_header(fo, schema, sync_marker) + sync_interval = 1000 * SYNC_SIZE + io = MemoryIO() + + nblocks = 0 + + def dump(): + # FIXME: Compression + write_long(fo, nblocks, schema) + fo.write(io.getvalue()) + fo.write(sync_marker) + io.truncate(0) + io.seek(0, SEEK_SET) + + for record in records: + write_data(io, record, schema) + nblocks += 1 + if io.tell() >= sync_interval: + dump() + nblocks = 0 + + if io.tell(): + dump() + + fo.flush() diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/gtable.py b/interactive-mining-3rdparty-madis/madis/src/lib/gtable.py new file mode 100644 index 0000000..9700eff --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/gtable.py @@ -0,0 +1,132 @@ +from lib.simpleutils import latinnum + +from lib.unicodeops import unistr + +def numeric(el): ####Oi upoloipoi typoi + el=unistr(el) + if el.startswith("0") and not el.startswith("0."): + return el + try: + return int(el) + except ValueError: + try: + return float(el) + except ValueError: + return el + + +def gjsonFull(rows,titleslist,typelist): ###does not support date type + + import json + response={"cols":[],"rows":[]} + for name, type,num in zip(titleslist, typelist,xrange(len(titleslist))): + id=latinnum(num+1) + response["cols"]+=[{"id":id, "label":name,"type":type}] + for row in rows: + rowdict={"c":[]} + for val,type in zip(row, typelist): + if type=="number": + try: + rowdict["c"]+=[{"v":numeric(val)}] + except ValueError: + raise ValueError("Type problem in %s:\nRow:%sTypes:%s" %(val,row,typelist)) + else: + rowdict["c"]+=[{"v":val}] + response["rows"]+=[rowdict] + + return json.dumps(response,sort_keys=True) + +def mkoutputGoogleTableCol(names, types): + #######{id:'A',label:'State',type:'string'} + counter = ord('A') + rawValues = "" + for name, type in zip(names, types): + rawValues += "{id:'%s',label:'%s',type:'%s'}," % (chr(counter), name, type) + counter += 1 + return rawValues[:-1] ####OMITT THE LAST COMMA + + +def mkoutputGoogleTableRow(values, types, format = '%Y-%m'): + ##### {c:[{v:'Alabama'},{v:Date(1,1,2008),f:'Jan-08'},{v:203.6,f:'203.6'},{v:4.5,f:'4.5'},{v:'South'},{v:4452.0,f:'4452'},{v:0.122,f:'0.122'}]} + #print values + rawValues = "" + for val, type in zip(values, types): + if type == 'string': + if val == 'null': + rawValues += "{v:%s}," % (val) + else: + rawValues += "{v:'%s'}," % (val) + elif type == 'date': + timemonth = time.strptime(val, format) + rawValues += "{v:new Date(%s,%s,1)}," % (int(time.strftime('%Y', timemonth)), int(time.strftime('%m', timemonth))-1) + else: #type =='number' + if val == 'null': + rawValues += "{v:0}," + else: + rawValues += "{v:%s}," % (val) + + rawRow = "{c:[%s]}" % (rawValues[:-1]) ####OMITT THE LAST COMMA + return rawRow + +def gtableIter(iter,names,types): + yield '{cols:[%s],rows:[' %(mkoutputGoogleTableCol(names, types)) + f=True + for row in iter: + if f: + f=False + yield mkoutputGoogleTableRow(row, types) + else: + yield ","+mkoutputGoogleTableRow(row, types) + yield ']}' + return + +def gjsonIter(rows,titleslist,typelist): ###does not support date type + + import json + #response={"cols":[],"rows":[]} + yield '{"cols": ' + header=[] + first=True + for name, type,num in zip(titleslist, typelist,xrange(len(titleslist))): + id=latinnum(num+1) + header+=[{"id":id, "label":name,"type":type}] + yield json.dumps(header,sort_keys=True) + yield ', "rows": [' + for row in rows: + rowdict={"c":[]} + for val,type in zip(row, typelist): + if type=="number": + try: + rowdict["c"]+=[{"v":numeric(val)}] + except ValueError: + raise ValueError("Type problem in %s:\nRow:%sTypes:%s" %(val,row,typelist)) + else: + rowdict["c"]+=[{"v":val}] + if not first: + yield ', '+json.dumps(rowdict,sort_keys=True) + else: + yield json.dumps(rowdict,sort_keys=True) + first=False + yield ']}' + + return + +#def gtableFull(rows,titleslist,typelist): ORIGINAL +# columsstr = mkoutputGoogleTableCol(titleslist, typelist) +# googleDatatable = [mkoutputGoogleTableRow(row, typelist, dateformat) for row in rows] +# rowstr = ','.join(googleDatatable) +# googleDatatableJSstring = "{cols:[%s],rows:[%s]}" % (columsstr, rowstr) +# return googleDatatableJSstring + +def gtableFull(rows,titleslist,typelist): + return "".join(gtableIter(rows,titleslist,typelist)) + + + + +def gjsonfileFull(iterin,fiterout,names,types): + for wr in gjsonIter(iterin, names, types): + fiterout.write(wr.encode('utf-8')) +def gtablefileFull(iterin,fiterout,names,types): + for wr in gtableIter(iterin, names, types): + fiterout.write(wr.encode('utf-8')) \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/gzip32.py b/interactive-mining-3rdparty-madis/madis/src/lib/gzip32.py new file mode 100644 index 0000000..6551182 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/gzip32.py @@ -0,0 +1,683 @@ +"""Functions that read and write gzipped files. + +The user of the file doesn't have to worry about the compression, +but random access is not allowed.""" + +# based on Andrew Kuchling's minigzip.py distributed with the zlib module + +import struct, sys, time, os +import zlib +try: + import builtins +except: + builtins=lambda x:x + builtins.open=open +import io + +__all__ = ["GzipFile", "open", "compress", "decompress"] + +FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16 + +READ, WRITE = 1, 2 + +def open(filename, mode="rb", compresslevel=9, + encoding=None, errors=None, newline=None): + """Open a gzip-compressed file in binary or text mode. + + The filename argument can be an actual filename (a str or bytes object), or + an existing file object to read from or write to. + + The mode argument can be "r", "rb", "w", "wb", "a" or "ab" for binary mode, + or "rt", "wt" or "at" for text mode. The default mode is "rb", and the + default compresslevel is 9. + + For binary mode, this function is equivalent to the GzipFile constructor: + GzipFile(filename, mode, compresslevel). In this case, the encoding, errors + and newline arguments must not be provided. + + For text mode, a GzipFile object is created, and wrapped in an + io.TextIOWrapper instance with the specified encoding, error handling + behavior, and line ending(s). + + """ + if "t" in mode: + if "b" in mode: + raise ValueError("Invalid mode: %r" % (mode,)) + else: + if encoding is not None: + raise ValueError("Argument 'encoding' not supported in binary mode") + if errors is not None: + raise ValueError("Argument 'errors' not supported in binary mode") + if newline is not None: + raise ValueError("Argument 'newline' not supported in binary mode") + + gz_mode = mode.replace("t", "") + if isinstance(filename, (str, bytes)): + binary_file = GzipFile(filename, gz_mode, compresslevel) + elif hasattr(filename, "read") or hasattr(filename, "write"): + binary_file = GzipFile(None, gz_mode, compresslevel, filename) + else: + raise TypeError("filename must be a str or bytes object, or a file") + + if "t" in mode: + return io.TextIOWrapper(binary_file, encoding, errors, newline) + else: + return binary_file + +def write32u(output, value): + # The L format writes the bit pattern correctly whether signed + # or unsigned. + output.write(struct.pack("' + + def _check_closed(self): + """Raises a ValueError if the underlying file object has been closed. + + """ + if self.closed: + raise ValueError('I/O operation on closed file.') + + def _init_write(self, filename): + self.name = filename + self.crc = zlib.crc32(b"") & 0xffffffff + self.size = 0 + self.writebuf = [] + self.bufsize = 0 + + def _write_gzip_header(self): + self.fileobj.write(b'\037\213') # magic header + self.fileobj.write(b'\010') # compression method + try: + # RFC 1952 requires the FNAME field to be Latin-1. Do not + # include filenames that cannot be represented that way. + fname = os.path.basename(self.name) + if not isinstance(fname, bytes): + fname = fname.encode('latin-1') + if fname.endswith(b'.gz'): + fname = fname[:-3] + except UnicodeEncodeError: + fname = b'' + flags = 0 + if fname: + flags = FNAME + self.fileobj.write(chr(flags).encode('latin-1')) + mtime = self.mtime + if mtime is None: + mtime = time.time() + write32u(self.fileobj, int(mtime)) + self.fileobj.write(b'\002') + self.fileobj.write(b'\377') + if fname: + self.fileobj.write(fname + b'\000') + + def _init_read(self): + self.crc = zlib.crc32(b"") & 0xffffffff + self.size = 0 + + def _read_gzip_header(self): + magic = self.fileobj.read(2) + if magic == b'': + raise EOFError("Reached EOF") + + if magic != b'\037\213': + raise IOError('Not a gzipped file') + method = ord( self.fileobj.read(1) ) + if method != 8: + raise IOError('Unknown compression method') + flag = ord( self.fileobj.read(1) ) + self.mtime = read32(self.fileobj) + # extraflag = self.fileobj.read(1) + # os = self.fileobj.read(1) + self.fileobj.read(2) + + if flag & FEXTRA: + # Read & discard the extra field, if present + xlen = ord(self.fileobj.read(1)) + xlen = xlen + 256*ord(self.fileobj.read(1)) + self.fileobj.read(xlen) + if flag & FNAME: + # Read and discard a null-terminated string containing the filename + while True: + s = self.fileobj.read(1) + if not s or s==b'\000': + break + if flag & FCOMMENT: + # Read and discard a null-terminated string containing a comment + while True: + s = self.fileobj.read(1) + if not s or s==b'\000': + break + if flag & FHCRC: + self.fileobj.read(2) # Read & discard the 16-bit header CRC + + unused = self.fileobj.unused() + if unused: + uncompress = self.decompress.decompress(unused) + self._add_read_data(uncompress) + + def write(self,data): + self._check_closed() + if self.mode != WRITE: + import errno + raise IOError(errno.EBADF, "write() on read-only GzipFile object") + + if self.fileobj is None: + raise ValueError("write() on closed GzipFile object") + + # Convert data type if called by io.BufferedWriter. + if isinstance(data, memoryview): + data = data.tobytes() + + if len(data) > 0: + self.size = self.size + len(data) + self.crc = zlib.crc32(data, self.crc) & 0xffffffff + self.fileobj.write( self.compress.compress(data) ) + self.offset += len(data) + + return len(data) + + def read(self, size=-1): + self._check_closed() + if self.mode != READ: + import errno + raise IOError(errno.EBADF, "read() on write-only GzipFile object") + + if self.extrasize <= 0 and self.fileobj is None: + return b'' + + readsize = 1024 + if size < 0: # get the whole thing + try: + while True: + self._read(readsize) + readsize = min(self.max_read_chunk, readsize * 2) + except EOFError: + size = self.extrasize + else: # just get some more of it + try: + while size > self.extrasize: + self._read(readsize) + readsize = min(self.max_read_chunk, readsize * 2) + except EOFError: + if size > self.extrasize: + size = self.extrasize + + offset = self.offset - self.extrastart + chunk = self.extrabuf[offset: offset + size] + self.extrasize = self.extrasize - size + + self.offset += size + return chunk + + def read1(self, size=-1): + self._check_closed() + if self.mode != READ: + import errno + raise IOError(errno.EBADF, "read1() on write-only GzipFile object") + + if self.extrasize <= 0 and self.fileobj is None: + return b'' + + try: + # For certain input data, a single call to _read() may not return + # any data. In this case, retry until we get some data or reach EOF. + while self.extrasize <= 0: + self._read() + except EOFError: + pass + if size < 0 or size > self.extrasize: + size = self.extrasize + + offset = self.offset - self.extrastart + chunk = self.extrabuf[offset: offset + size] + self.extrasize -= size + self.offset += size + return chunk + + def peek(self, n): + if self.mode != READ: + import errno + raise IOError(errno.EBADF, "peek() on write-only GzipFile object") + + # Do not return ridiculously small buffers, for one common idiom + # is to call peek(1) and expect more bytes in return. + if n < 100: + n = 100 + if self.extrasize == 0: + if self.fileobj is None: + return b'' + try: + # Ensure that we don't return b"" if we haven't reached EOF. + while self.extrasize == 0: + # 1024 is the same buffering heuristic used in read() + self._read(max(n, 1024)) + except EOFError: + pass + offset = self.offset - self.extrastart + remaining = self.extrasize + assert remaining == len(self.extrabuf) - offset + return self.extrabuf[offset:offset + n] + + def _unread(self, buf): + self.extrasize = len(buf) + self.extrasize + self.offset -= len(buf) + + def _read(self, size=1024): + if self.fileobj is None: + raise EOFError("Reached EOF") + + if self._new_member: + # If the _new_member flag is set, we have to + # jump to the next member, if there is one. + self._init_read() + self._read_gzip_header() + self.decompress = zlib.decompressobj(-zlib.MAX_WBITS) + self._new_member = False + + # Read a chunk of data from the file + buf = self.fileobj.read(size) + + # If the EOF has been reached, flush the decompression object + # and mark this object as finished. + + if buf == b"": + uncompress = self.decompress.flush() + # Prepend the already read bytes to the fileobj to they can be + # seen by _read_eof() + self.fileobj.prepend(self.decompress.unused_data, True) + self._read_eof() + self._add_read_data( uncompress ) + raise EOFError('Reached EOF') + + uncompress = self.decompress.decompress(buf) + self._add_read_data( uncompress ) + + if self.decompress.unused_data != b"": + # Ending case: we've come to the end of a member in the file, + # so seek back to the start of the unused data, finish up + # this member, and read a new gzip header. + # Prepend the already read bytes to the fileobj to they can be + # seen by _read_eof() and _read_gzip_header() + self.fileobj.prepend(self.decompress.unused_data, True) + # Check the CRC and file size, and set the flag so we read + # a new member on the next call + self._read_eof() + self._new_member = True + + def _add_read_data(self, data): + self.crc = zlib.crc32(data, self.crc) & 0xffffffff + offset = self.offset - self.extrastart + self.extrabuf = self.extrabuf[offset:] + data + self.extrasize = self.extrasize + len(data) + self.extrastart = self.offset + self.size = self.size + len(data) + + def _read_eof(self): + # We've read to the end of the file + # We check the that the computed CRC and size of the + # uncompressed data matches the stored values. Note that the size + # stored is the true file size mod 2**32. + crc32 = read32(self.fileobj) + isize = read32(self.fileobj) # may exceed 2GB + if crc32 != self.crc: + raise IOError("CRC check failed %s != %s" % (hex(crc32), + hex(self.crc))) + elif isize != (self.size & 0xffffffff): + raise IOError("Incorrect length of data produced") + + # Gzip files can be padded with zeroes and still have archives. + # Consume all zero bytes and set the file position to the first + # non-zero byte. See http://www.gzip.org/#faq8 + c = b"\x00" + while c == b"\x00": + c = self.fileobj.read(1) + if c: + self.fileobj.prepend(c, True) + + @property + def closed(self): + return self.fileobj is None + + def close(self): + if self.fileobj is None: + return + if self.mode == WRITE: + self.fileobj.write(self.compress.flush()) + write32u(self.fileobj, self.crc) + # self.size may exceed 2GB, or even 4GB + write32u(self.fileobj, self.size & 0xffffffff) + self.fileobj = None + elif self.mode == READ: + self.fileobj = None + if self.myfileobj: + self.myfileobj.close() + self.myfileobj = None + + def flush(self,zlib_mode=zlib.Z_SYNC_FLUSH): + self._check_closed() + if self.mode == WRITE: + # Ensure the compressor's buffer is flushed + self.fileobj.write(self.compress.flush(zlib_mode)) + self.fileobj.flush() + + def fileno(self): + """Invoke the underlying file object's fileno() method. + + This will raise AttributeError if the underlying file object + doesn't support fileno(). + """ + return self.fileobj.fileno() + + def rewind(self): + '''Return the uncompressed stream file position indicator to the + beginning of the file''' + if self.mode != READ: + raise IOError("Can't rewind in write mode") + self.fileobj.seek(0) + self._new_member = True + self.extrabuf = b"" + self.extrasize = 0 + self.extrastart = 0 + self.offset = 0 + + def readable(self): + return self.mode == READ + + def writable(self): + return self.mode == WRITE + + def seekable(self): + return True + + def seek(self, offset, whence=0): + if whence: + if whence == 1: + offset = self.offset + offset + else: + raise ValueError('Seek from end not supported') + if self.mode == WRITE: + if offset < self.offset: + raise IOError('Negative seek in write mode') + count = offset - self.offset + chunk = bytes(1024) + for i in range(count // 1024): + self.write(chunk) + self.write(bytes(count % 1024)) + elif self.mode == READ: + if offset < self.offset: + # for negative seek, rewind and do positive seek + self.rewind() + count = offset - self.offset + for i in range(count // 1024): + self.read(1024) + self.read(count % 1024) + + return self.offset + + def readline(self, size=-1): + if size < 0: + # Shortcut common case - newline found in buffer. + offset = self.offset - self.extrastart + i = self.extrabuf.find(b'\n', offset) + 1 + if i > 0: + self.extrasize -= i - offset + self.offset += i - offset + return self.extrabuf[offset: i] + + size = sys.maxsize + readsize = self.min_readsize + else: + readsize = size + bufs = [] + while size != 0: + c = self.read(readsize) + i = c.find(b'\n') + + # We set i=size to break out of the loop under two + # conditions: 1) there's no newline, and the chunk is + # larger than size, or 2) there is a newline, but the + # resulting line would be longer than 'size'. + if (size <= i) or (i == -1 and len(c) > size): + i = size - 1 + + if i >= 0 or c == b'': + bufs.append(c[:i + 1]) # Add portion of last chunk + self._unread(c[i + 1:]) # Push back rest of chunk + break + + # Append chunk to list, decrease 'size', + bufs.append(c) + size = size - len(c) + readsize = min(size, readsize * 2) + if readsize > self.min_readsize: + self.min_readsize = min(readsize, self.min_readsize * 2, 512) + return b''.join(bufs) # Return resulting line + + +def compress(data, compresslevel=9): + """Compress data in one shot and return the compressed string. + Optional argument is the compression level, in range of 1-9. + """ + buf = io.BytesIO() + with GzipFile(fileobj=buf, mode='wb', compresslevel=compresslevel) as f: + f.write(data) + return buf.getvalue() + +def decompress(data): + """Decompress a gzip compressed string in one shot. + Return the decompressed string. + """ + with GzipFile(fileobj=io.BytesIO(data)) as f: + return f.read() + + +def _test(): + # Act like gzip; with -d, act like gunzip. + # The input file is not deleted, however, nor are any other gzip + # options or features supported. + args = sys.argv[1:] + decompress = args and args[0] == "-d" + if decompress: + args = args[1:] + if not args: + args = ["-"] + for arg in args: + if decompress: + if arg == "-": + f = GzipFile(filename="", mode="rb", fileobj=sys.stdin.buffer) + g = sys.stdout.buffer + else: + if arg[-3:] != ".gz": + print("filename doesn't end in .gz:", repr(arg)) + continue + f = open(arg, "rb") + g = builtins.open(arg[:-3], "wb") + else: + if arg == "-": + f = sys.stdin.buffer + g = GzipFile(filename="", mode="wb", fileobj=sys.stdout.buffer) + else: + f = builtins.open(arg, "rb") + g = open(arg + ".gz", "wb") + while True: + chunk = f.read(1024) + if not chunk: + break + g.write(chunk) + if g is not sys.stdout.buffer: + g.close() + if f is not sys.stdin.buffer: + f.close() + +if __name__ == '__main__': + _test() diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/gzip34.py b/interactive-mining-3rdparty-madis/madis/src/lib/gzip34.py new file mode 100644 index 0000000..705e203 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/gzip34.py @@ -0,0 +1,672 @@ +"""Functions that read and write gzipped files. + +The user of the file doesn't have to worry about the compression, +but random access is not allowed.""" + +# based on Andrew Kuchling's minigzip.py distributed with the zlib module + +import struct, sys, time, os +import zlib +import io + +__all__ = ["GzipFile", "open", "compress", "decompress"] + +FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16 + +READ, WRITE = 1, 2 + +def open(filename, mode="rb", compresslevel=9, + encoding=None, errors=None, newline=None): + """Open a gzip-compressed file in binary or text mode. + + The filename argument can be an actual filename (a str or bytes object), or + an existing file object to read from or write to. + + The mode argument can be "r", "rb", "w", "wb", "x", "xb", "a" or "ab" for + binary mode, or "rt", "wt", "xt" or "at" for text mode. The default mode is + "rb", and the default compresslevel is 9. + + For binary mode, this function is equivalent to the GzipFile constructor: + GzipFile(filename, mode, compresslevel). In this case, the encoding, errors + and newline arguments must not be provided. + + For text mode, a GzipFile object is created, and wrapped in an + io.TextIOWrapper instance with the specified encoding, error handling + behavior, and line ending(s). + + """ + if "t" in mode: + if "b" in mode: + raise ValueError("Invalid mode: %r" % (mode,)) + else: + if encoding is not None: + raise ValueError("Argument 'encoding' not supported in binary mode") + if errors is not None: + raise ValueError("Argument 'errors' not supported in binary mode") + if newline is not None: + raise ValueError("Argument 'newline' not supported in binary mode") + + gz_mode = mode.replace("t", "") + if isinstance(filename, (str, bytes)): + binary_file = GzipFile(filename, gz_mode, compresslevel) + elif hasattr(filename, "read") or hasattr(filename, "write"): + binary_file = GzipFile(None, gz_mode, compresslevel, filename) + else: + raise TypeError("filename must be a str or bytes object, or a file") + + if "t" in mode: + return io.TextIOWrapper(binary_file, encoding, errors, newline) + else: + return binary_file + +def write32u(output, value): + # The L format writes the bit pattern correctly whether signed + # or unsigned. + output.write(struct.pack("' + + def _check_closed(self): + """Raises a ValueError if the underlying file object has been closed. + + """ + if self.closed: + raise ValueError('I/O operation on closed file.') + + def _init_write(self, filename): + self.name = filename + self.crc = zlib.crc32(b"") & 0xffffffff + self.size = 0 + self.writebuf = [] + self.bufsize = 0 + + def _write_gzip_header(self): + self.fileobj.write(b'\037\213') # magic header + self.fileobj.write(b'\010') # compression method + try: + # RFC 1952 requires the FNAME field to be Latin-1. Do not + # include filenames that cannot be represented that way. + fname = os.path.basename(self.name) + if not isinstance(fname, bytes): + fname = fname.encode('latin-1') + if fname.endswith(b'.gz'): + fname = fname[:-3] + except UnicodeEncodeError: + fname = b'' + flags = 0 + if fname: + flags = FNAME + self.fileobj.write(chr(flags).encode('latin-1')) + mtime = self.mtime + if mtime is None: + mtime = time.time() + write32u(self.fileobj, int(mtime)) + self.fileobj.write(b'\002') + self.fileobj.write(b'\377') + if fname: + self.fileobj.write(fname + b'\000') + + def _init_read(self): + self.crc = zlib.crc32(b"") & 0xffffffff + self.size = 0 + + def _read_exact(self, n): + data = self.fileobj.read(n) + while len(data) < n: + b = self.fileobj.read(n - len(data)) + if not b: + raise EOFError("Compressed file ended before the " + "end-of-stream marker was reached") + data += b + return data + + def _read_gzip_header(self): + magic = self.fileobj.read(2) + if magic == b'': + return False + + if magic != b'\037\213': + raise OSError('Not a gzipped file') + + method, flag, self.mtime = struct.unpack(" 0: + self.size = self.size + len(data) + self.crc = zlib.crc32(data, self.crc) & 0xffffffff + self.fileobj.write( self.compress.compress(data) ) + self.offset += len(data) + + return len(data) + + def read(self, size=-1): + self._check_closed() + if self.mode != READ: + import errno + raise OSError(errno.EBADF, "read() on write-only GzipFile object") + + if self.extrasize <= 0 and self.fileobj is None: + return b'' + + readsize = 1024 + if size < 0: # get the whole thing + while self._read(readsize): + readsize = min(self.max_read_chunk, readsize * 2) + size = self.extrasize + else: # just get some more of it + while size > self.extrasize: + if not self._read(readsize): + if size > self.extrasize: + size = self.extrasize + break + readsize = min(self.max_read_chunk, readsize * 2) + + offset = self.offset - self.extrastart + chunk = self.extrabuf[offset: offset + size] + self.extrasize = self.extrasize - size + + self.offset += size + return chunk + + def read1(self, size=-1): + self._check_closed() + if self.mode != READ: + import errno + raise OSError(errno.EBADF, "read1() on write-only GzipFile object") + + if self.extrasize <= 0 and self.fileobj is None: + return b'' + + # For certain input data, a single call to _read() may not return + # any data. In this case, retry until we get some data or reach EOF. + while self.extrasize <= 0 and self._read(): + pass + if size < 0 or size > self.extrasize: + size = self.extrasize + + offset = self.offset - self.extrastart + chunk = self.extrabuf[offset: offset + size] + self.extrasize -= size + self.offset += size + return chunk + + def peek(self, n): + if self.mode != READ: + import errno + raise OSError(errno.EBADF, "peek() on write-only GzipFile object") + + # Do not return ridiculously small buffers, for one common idiom + # is to call peek(1) and expect more bytes in return. + if n < 100: + n = 100 + if self.extrasize == 0: + if self.fileobj is None: + return b'' + # Ensure that we don't return b"" if we haven't reached EOF. + # 1024 is the same buffering heuristic used in read() + while self.extrasize == 0 and self._read(max(n, 1024)): + pass + offset = self.offset - self.extrastart + remaining = self.extrasize + assert remaining == len(self.extrabuf) - offset + return self.extrabuf[offset:offset + n] + + def _unread(self, buf): + self.extrasize = len(buf) + self.extrasize + self.offset -= len(buf) + + def _read(self, size=1024): + if self.fileobj is None: + return False + + if self._new_member: + # If the _new_member flag is set, we have to + # jump to the next member, if there is one. + self._init_read() + if not self._read_gzip_header(): + return False + self.decompress = zlib.decompressobj(-zlib.MAX_WBITS) + self._new_member = False + + # Read a chunk of data from the file + buf = self.fileobj.read(size) + + # If the EOF has been reached, flush the decompression object + # and mark this object as finished. + + if buf == b"": + uncompress = self.decompress.flush() + # Prepend the already read bytes to the fileobj to they can be + # seen by _read_eof() + self.fileobj.prepend(self.decompress.unused_data, True) + self._read_eof() + self._add_read_data( uncompress ) + return False + + uncompress = self.decompress.decompress(buf) + self._add_read_data( uncompress ) + + if self.decompress.unused_data != b"": + # Ending case: we've come to the end of a member in the file, + # so seek back to the start of the unused data, finish up + # this member, and read a new gzip header. + # Prepend the already read bytes to the fileobj to they can be + # seen by _read_eof() and _read_gzip_header() + self.fileobj.prepend(self.decompress.unused_data, True) + # Check the CRC and file size, and set the flag so we read + # a new member on the next call + self._read_eof() + self._new_member = True + return True + + def _add_read_data(self, data): + self.crc = zlib.crc32(data, self.crc) & 0xffffffff + offset = self.offset - self.extrastart + self.extrabuf = self.extrabuf[offset:] + data + self.extrasize = self.extrasize + len(data) + self.extrastart = self.offset + self.size = self.size + len(data) + + def _read_eof(self): + # We've read to the end of the file + # We check the that the computed CRC and size of the + # uncompressed data matches the stored values. Note that the size + # stored is the true file size mod 2**32. + crc32, isize = struct.unpack(" 0: + tmp = i - offset + self.extrasize -= tmp + self.offset += tmp + return self.extrabuf[offset: i] + + size = sys.maxsize + readsize = self.min_readsize + bufs = [] + + while size != 0: + c = self.read(readsize) + i = c.find(b'\n') + + # We set i=size to break out of the loop under two + # conditions: 1) there's no newline, and the chunk is + # larger than size, or 2) there is a newline, but the + # resulting line would be longer than 'size'. + if (size <= i) or (i == -1 and len(c) > size): + i = size - 1 + + if i >= 0 or c == b'': + bufs.append(c[:i + 1]) # Add portion of last chunk + self._unread(c[i + 1:]) # Push back rest of chunk + break + + # Append chunk to list, decrease 'size', + bufs.append(c) + size -= len(c) + readsize = min(size, readsize * 2) + if readsize > self.min_readsize: + self.min_readsize = min(self.min_readsize * 2, 512) + return b''.join(bufs) # Return resulting line + + +def compress(data, compresslevel=9): + """Compress data in one shot and return the compressed string. + Optional argument is the compression level, in range of 0-9. + """ + buf = io.BytesIO() + with GzipFile(fileobj=buf, mode='wb', compresslevel=compresslevel) as f: + f.write(data) + return buf.getvalue() + +def decompress(data): + """Decompress a gzip compressed string in one shot. + Return the decompressed string. + """ + with GzipFile(fileobj=io.BytesIO(data)) as f: + return f.read() + + +def _test(): + # Act like gzip; with -d, act like gunzip. + # The input file is not deleted, however, nor are any other gzip + # options or features supported. + args = sys.argv[1:] + decompress = args and args[0] == "-d" + if decompress: + args = args[1:] + if not args: + args = ["-"] + for arg in args: + if decompress: + if arg == "-": + f = GzipFile(filename="", mode="rb", fileobj=sys.stdin.buffer) + g = sys.stdout.buffer + else: + if arg[-3:] != ".gz": + print("filename doesn't end in .gz:", repr(arg)) + continue + f = open(arg, "rb") + g = open(arg[:-3], "wb") + else: + if arg == "-": + f = sys.stdin.buffer + g = GzipFile(filename="", mode="wb", fileobj=sys.stdout.buffer) + else: + f = open(arg, "rb") + g = open(arg + ".gz", "wb") + while True: + chunk = f.read(1024) + if not chunk: + break + g.write(chunk) + if g is not sys.stdout.buffer: + g.close() + if f is not sys.stdin.buffer: + f.close() + +if __name__ == '__main__': + _test() diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/htmlentities.py b/interactive-mining-3rdparty-madis/madis/src/lib/htmlentities.py new file mode 100644 index 0000000..44fe48c --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/htmlentities.py @@ -0,0 +1,2474 @@ +"""HTML character entity references.""" + +# html/xml named entities +entities = { +'AElig': r'\xc6', +'Aacgr': 'Ά', +'Aacute': r'\xc1', +'Abreve': 'Ă', +'Abreveac': 'Ắ', +'Abrevedb': 'Ặ', +'Abrevegr': 'Ằ', +'Abreveha': 'Ẳ', +'Abreveti': 'Ẵ', +'Acaron': 'Ǎ', +'Acirc': r'\xc2', +'Acy': 'А', +'Adot': 'Ȧ', +'Adotama': 'Ǡ', +'Adotb': 'Ạ', +'Aeacute': 'Ǽ', +'Aemacr': 'Ǣ', +'Afr': '𝔄', +'Agr': 'Α', +'Agrave': r'\xc0', +'Ahooka': 'Ả', +'Alpha': 'Α', +'Amacr': 'Ā', +'And': '⩓', +'Aogon': 'Ą', +'Aopf': '𝔸', +'ApplyFunction': '⁡', +'Aring': r'\xc5', +'Ascr': '𝒜', +'Assign': '≔', +'Atilde': r'\xc3', +'Auml': r'\xc4', +'Backslash': '∖', +'Barv': '⫧', +'Barwed': '⌆', +'Bcy': 'Б', +'Bdota': 'Ḃ', +'Bdotb': 'Ḅ', +'Because': '∵', +'Bernoullis': 'ℬ', +'Beta': 'Β', +'Bfr': '𝔅', +'Bgr': 'Β', +'Bmacrb': 'Ḇ', +'Bopf': '𝔹', +'Breve': '˘', +'Bscr': 'ℬ', +'Bumpeq': '≎', +'CHcy': 'Ч', +'COPY': r'\xa9', +'Cacute': 'Ć', +'Cap': '⋒', +'CapitalDifferentialD': 'ⅅ', +'Cayleys': 'ℭ', +'Ccaron': 'Č', +'Ccedil': r'\xc7', +'Ccirc': 'Ĉ', +'Cconint': '∰', +'Cdot': 'Ċ', +'Cedilla': r'\xb8', +'CenterDot': r'\xb7', +'Cfr': 'ℭ', +'Chi': 'Χ', +'CircleDot': '⊙', +'CircleMinus': '⊖', +'CirclePlus': '⊕', +'CircleTimes': '⊗', +'ClockwiseContourIntegral': '∲', +'CloseCurlyDoubleQuote': '”', +'CloseCurlyQuote': '’', +'Colon': '∷', +'Colone': '⩴', +'Congruent': '≡', +'Conint': '∯', +'ContourIntegral': '∮', +'Copf': 'ℂ', +'Coproduct': '∐', +'CounterClockwiseContourIntegral': '∳', +'Cross': '⨯', +'Cscr': '𝒞', +'Cup': '⋓', +'CupCap': '≍', +'DD': 'ⅅ', +'DDotrahd': '⤑', +'DJcy': 'Ђ', +'DScy': 'Ѕ', +'DZcy': 'Џ', +'Dagger': '‡', +'Darr': '↡', +'Dashv': '⫤', +'Dcaron': 'Ď', +'Dcommab': 'Ḑ', +'Dcy': 'Д', +'Ddota': 'Ḋ', +'Ddotb': 'Ḍ', +'Del': '∇', +'Delta': 'Δ', +'Dfr': '𝔇', +'Dgr': 'Δ', +'DiacriticalAcute': r'\xb4', +'DiacriticalDot': '˙', +'DiacriticalDoubleAcute': '˝', +'DiacriticalGrave': r'`', +'DiacriticalTilde': '˜', +'Diamond': '⋄', +'DifferentialD': 'ⅆ', +'Dmacrb': 'Ḏ', +'Dopf': '𝔻', +'Dot': r'\xa8', +'DotDot': '⃜', +'DotEqual': '≐', +'DoubleContourIntegral': '∯', +'DoubleDot': r'\xa8', +'DoubleDownArrow': '⇓', +'DoubleLeftArrow': '⇐', +'DoubleLeftRightArrow': '⇔', +'DoubleLeftTee': '⫤', +'DoubleLongLeftArrow': '⟸', +'DoubleLongLeftRightArrow': '⟺', +'DoubleLongRightArrow': '⟹', +'DoubleRightArrow': '⇒', +'DoubleRightTee': '⊨', +'DoubleUpArrow': '⇑', +'DoubleUpDownArrow': '⇕', +'DoubleVerticalBar': '∥', +'DownArrow': '↓', +'DownArrowBar': '⤓', +'DownArrowUpArrow': '⇵', +'DownBreve': '̑', +'DownLeftRightVector': '⥐', +'DownLeftTeeVector': '⥞', +'DownLeftVector': '↽', +'DownLeftVectorBar': '⥖', +'DownRightTeeVector': '⥟', +'DownRightVector': '⇁', +'DownRightVectorBar': '⥗', +'DownTee': '⊤', +'DownTeeArrow': '↧', +'Downarrow': '⇓', +'Dscr': '𝒟', +'Dstrok': 'Đ', +'EEacgr': 'Ή', +'EEgr': 'Η', +'ENG': 'Ŋ', +'ETH': r'\xd0', +'Eacgr': 'Έ', +'Eacute': r'\xc9', +'Ebreve': 'Ĕ', +'Ecaron': 'Ě', +'Ecedil': 'Ȩ', +'Ecedilbr': 'Ḝ', +'Ecirc': r'\xca', +'Ecy': 'Э', +'Edot': 'Ė', +'Edotb': 'Ẹ', +'Efr': '𝔈', +'Egr': 'Ε', +'Egrave': r'\xc8', +'Ehooka': 'Ẻ', +'Element': '∈', +'Emacr': 'Ē', +'Emacrac': 'Ḗ', +'Emacrgr': 'Ḕ', +'EmptySmallSquare': '◻', +'EmptyVerySmallSquare': '▫', +'Eogon': 'Ę', +'Eopf': '𝔼', +'Epsilon': 'Ε', +'Equal': '⩵', +'EqualTilde': '≂', +'Equilibrium': '⇌', +'Escr': 'ℰ', +'Esim': '⩳', +'Eta': 'Η', +'Etilde': 'Ẽ', +'Euml': r'\xcb', +'Exists': '∃', +'ExponentialE': 'ⅇ', +'Fcy': 'Ф', +'Fdot': 'Ḟ', +'Ffr': '𝔉', +'FilledSmallSquare': '◼', +'FilledVerySmallSquare': '▪', +'Fopf': '𝔽', +'ForAll': '∀', +'Fouriertrf': 'ℱ', +'Fscr': 'ℱ', +'GJcy': 'Ѓ', +'GT': r'>', +'Gacute': 'Ǵ', +'Gamma': 'Γ', +'Gammad': 'Ϝ', +'Gbreve': 'Ğ', +'Gcaron': 'Ǧ', +'Gcedil': 'Ģ', +'Gcirc': 'Ĝ', +'Gcy': 'Г', +'Gdot': 'Ġ', +'Gfr': '𝔊', +'Gg': '⋙', +'Ggr': 'Γ', +'Gmacr': 'Ḡ', +'Gopf': '𝔾', +'GreaterEqual': '≥', +'GreaterEqualLess': '⋛', +'GreaterFullEqual': '≧', +'GreaterGreater': '⪢', +'GreaterLess': '≷', +'GreaterSlantEqual': '⩾', +'GreaterTilde': '≳', +'Gscr': '𝒢', +'Gstrok': 'Ǥ', +'Gt': '≫', +'HARDcy': 'Ъ', +'Hacek': 'ˇ', +'Hat': r'^', +'Hbreveb': 'Ḫ', +'Hcaron': 'Ȟ', +'Hcedil': 'Ḩ', +'Hcirc': 'Ĥ', +'Hdot': 'Ḣ', +'Hdotb': 'Ḥ', +'Hfr': 'ℌ', +'HilbertSpace': 'ℋ', +'Hopf': 'ℍ', +'HorizontalLine': '─', +'Hscr': 'ℋ', +'Hstrok': 'Ħ', +'Hstroke': 'Ħ', +'Huml': 'Ḧ', +'HumpDownHump': '≎', +'HumpEqual': '≏', +'IEcy': 'Е', +'IJlig': 'IJ', +'IOcy': 'Ё', +'Iacgr': 'Ί', +'Iacute': r'\xcd', +'Ibreve': 'Ĭ', +'Icaron': 'Ǐ', +'Icirc': r'\xce', +'Icy': 'И', +'Idigr': 'Ϊ', +'Idot': 'İ', +'Idotb': 'Ị', +'Ifr': 'ℑ', +'Igr': 'Ι', +'Igrave': r'\xcc', +'Ihooka': 'Ỉ', +'Im': 'ℑ', +'Imacr': 'Ī', +'ImaginaryI': 'ⅈ', +'Implies': '⇒', +'Int': '∬', +'Integral': '∫', +'Intersection': '⋂', +'InvisibleComma': '⁣', +'InvisibleTimes': '⁢', +'Iogon': 'Į', +'Iopf': '𝕀', +'Iota': 'Ι', +'Iscr': 'ℐ', +'Itilde': 'Ĩ', +'Iukcy': 'І', +'Iuml': r'\xcf', +'Jcirc': 'Ĵ', +'Jcy': 'Й', +'Jfr': '𝔍', +'Jopf': '𝕁', +'Jscr': '𝒥', +'Jsercy': 'Ј', +'Jukcy': 'Є', +'KHcy': 'Х', +'KHgr': 'Χ', +'KJcy': 'Ќ', +'Kacute': 'Ḱ', +'Kappa': 'Κ', +'Kcedil': 'Ķ', +'Kcirc': 'Ǩ', +'Kcy': 'К', +'Kdotb': 'Ḳ', +'Kfr': '𝔎', +'Kgr': 'Κ', +'Kmacrb': 'Ḵ', +'Kopf': '𝕂', +'Kscr': '𝒦', +'LJcy': 'Љ', +'LT': r'<', +'Lacute': 'Ĺ', +'Lambda': 'Λ', +'Lang': '⟪', +'Laplacetrf': 'ℒ', +'Larr': '↞', +'Lcaron': 'Ľ', +'Lcedil': 'Ļ', +'Lcirc': 'Ḽ', +'Lcy': 'Л', +'Ldotb': 'Ḷ', +'Ldotbma': 'Ḹ', +'LeftAngleBracket': '⟨', +'LeftArrow': '←', +'LeftArrowBar': '⇤', +'LeftArrowRightArrow': '⇆', +'LeftCeiling': '⌈', +'LeftDoubleBracket': '⟦', +'LeftDownTeeVector': '⥡', +'LeftDownVector': '⇃', +'LeftDownVectorBar': '⥙', +'LeftFloor': '⌊', +'LeftRightArrow': '↔', +'LeftRightVector': '⥎', +'LeftTee': '⊣', +'LeftTeeArrow': '↤', +'LeftTeeVector': '⥚', +'LeftTriangle': '⊲', +'LeftTriangleBar': '⧏', +'LeftTriangleEqual': '⊴', +'LeftUpDownVector': '⥑', +'LeftUpTeeVector': '⥠', +'LeftUpVector': '↿', +'LeftUpVectorBar': '⥘', +'LeftVector': '↼', +'LeftVectorBar': '⥒', +'Leftarrow': '⇐', +'Leftrightarrow': '⇔', +'LessEqualGreater': '⋚', +'LessFullEqual': '≦', +'LessGreater': '≶', +'LessLess': '⪡', +'LessSlantEqual': '⩽', +'LessTilde': '≲', +'Lfr': '𝔏', +'Lgr': 'Λ', +'Ll': '⋘', +'Lleftarrow': '⇚', +'Lmacrb': 'Ḻ', +'Lmidot': 'Ŀ', +'LongLeftArrow': '⟵', +'LongLeftRightArrow': '⟷', +'LongRightArrow': '⟶', +'Longleftarrow': '⟸', +'Longleftrightarrow': '⟺', +'Longrightarrow': '⟹', +'Lopf': '𝕃', +'LowerLeftArrow': '↙', +'LowerRightArrow': '↘', +'Lscr': 'ℒ', +'Lsh': '↰', +'Lstrok': 'Ł', +'Lt': '≪', +'Macute': 'Ḿ', +'Map': '⤅', +'Mcy': 'М', +'Mdot': 'Ṁ', +'Mdotb': 'Ṃ', +'MediumSpace': ' ', +'Mellintrf': 'ℳ', +'Mfr': '𝔐', +'Mgr': 'Μ', +'MinusPlus': '∓', +'Mopf': '𝕄', +'Mscr': 'ℳ', +'Mu': 'Μ', +'NJcy': 'Њ', +'Nacute': 'Ń', +'Ncaron': 'Ň', +'Ncedil': 'Ņ', +'Ncy': 'Н', +'Ndot': 'Ṅ', +'Ndotb': 'Ṇ', +'NegativeMediumSpace': '​', +'NegativeThickSpace': '​', +'NegativeThinSpace': '​', +'NegativeVeryThinSpace': '​', +'NestedGreaterGreater': '≫', +'NestedLessLess': '≪', +'NewLine': r'\\n', +'Nfr': '𝔑', +'Ngr': 'Ν', +'Ngrave': 'Ǹ', +'Nmacrb': 'Ṉ', +'NoBreak': '⁠', +'NonBreakingSpace': r'\xa0', +'Nopf': 'ℕ', +'Not': '⫬', +'NotCongruent': '≢', +'NotCupCap': '≭', +'NotDoubleVerticalBar': '∦', +'NotElement': '∉', +'NotEqual': '≠', +'NotEqualTilde': '≂̸', +'NotExists': '∄', +'NotGreater': '≯', +'NotGreaterEqual': '≱', +'NotGreaterFullEqual': '≧̸', +'NotGreaterGreater': '≫̸', +'NotGreaterLess': '≹', +'NotGreaterSlantEqual': '⩾̸', +'NotGreaterTilde': '≵', +'NotHumpDownHump': '≎̸', +'NotHumpEqual': '≏̸', +'NotLeftTriangle': '⋪', +'NotLeftTriangleBar': '⧏̸', +'NotLeftTriangleEqual': '⋬', +'NotLess': '≮', +'NotLessEqual': '≰', +'NotLessGreater': '≸', +'NotLessLess': '≪̸', +'NotLessSlantEqual': '⩽̸', +'NotLessTilde': '≴', +'NotNestedGreaterGreater': '⪢̸', +'NotNestedLessLess': '⪡̸', +'NotPrecedes': '⊀', +'NotPrecedesEqual': '⪯̸', +'NotPrecedesSlantEqual': '⋠', +'NotReverseElement': '∌', +'NotRightTriangle': '⋫', +'NotRightTriangleBar': '⧐̸', +'NotRightTriangleEqual': '⋭', +'NotSquareSubset': '⊏̸', +'NotSquareSubsetEqual': '⋢', +'NotSquareSuperset': '⊐̸', +'NotSquareSupersetEqual': '⋣', +'NotSubset': '⊂⃒', +'NotSubsetEqual': '⊈', +'NotSucceeds': '⊁', +'NotSucceedsEqual': '⪰̸', +'NotSucceedsSlantEqual': '⋡', +'NotSucceedsTilde': '≿̸', +'NotSuperset': '⊃⃒', +'NotSupersetEqual': '⊉', +'NotTilde': '≁', +'NotTildeEqual': '≄', +'NotTildeFullEqual': '≇', +'NotTildeTilde': '≉', +'NotVerticalBar': '∤', +'Nscr': '𝒩', +'Ntilde': r'\xd1', +'Nu': 'Ν', +'OElig': 'Œ', +'OHacgr': 'Ώ', +'OHgr': 'Ω', +'Oacgr': 'Ό', +'Oacute': r'\xd3', +'Obreve': 'Ŏ', +'Ocaron': 'Ǒ', +'Ocirc': r'\xd4', +'Ocy': 'О', +'Odblac': 'Ő', +'Odota': 'Ȯ', +'Odotama': 'Ȱ', +'Odotb': 'Ọ', +'Ofr': '𝔒', +'Ogr': 'Ο', +'Ograve': r'\xd2', +'Ohooka': 'Ỏ', +'Ohorn': 'Ơ', +'Ohornac': 'Ứ', +'Ohorndb': 'Ợ', +'Ohorngr': 'Ờ', +'Ohornha': 'Ở', +'Ohornti': 'Ỡ', +'Omacr': 'Ō', +'Omacrac': 'Ṓ', +'Omacrgr': 'Ṑ', +'Omega': 'Ω', +'Omicron': 'Ο', +'Oogon': 'Ǫ', +'Oogonma': 'Ǭ', +'Oopf': '𝕆', +'OpenCurlyDoubleQuote': '“', +'OpenCurlyQuote': '‘', +'Or': '⩔', +'Oscr': '𝒪', +'Oslash': r'\xd8', +'Otilde': r'\xd5', +'Otimes': '⨷', +'Ouml': r'\xd6', +'OverBar': '‾', +'OverBrace': '⏞', +'OverBracket': '⎴', +'OverParenthesis': '⏜', +'PHgr': 'Φ', +'PSgr': 'Ψ', +'Pacute': 'Ṕ', +'PartialD': '∂', +'Pcy': 'П', +'Pdota': 'Ṗ', +'Pfr': '𝔓', +'Pgr': 'Π', +'Phi': 'Φ', +'Pi': 'Π', +'PlusMinus': r'\xb1', +'Poincareplane': 'ℌ', +'Popf': 'ℙ', +'Pr': '⪻', +'Precedes': '≺', +'PrecedesEqual': '⪯', +'PrecedesSlantEqual': '≼', +'PrecedesTilde': '≾', +'Prime': '″', +'Product': '∏', +'Proportion': '∷', +'Proportional': '∝', +'Pscr': '𝒫', +'Psi': 'Ψ', +'Qfr': '𝔔', +'Qopf': 'ℚ', +'Qscr': '𝒬', +'RBarr': '⤐', +'REG': r'\xae', +'Racute': 'Ŕ', +'Rang': '⟫', +'Rarr': '↠', +'Rarrtl': '⤖', +'Rcaron': 'Ř', +'Rcedil': 'Ŗ', +'Rcy': 'Р', +'Rdota': 'Ṙ', +'Rdotb': 'Ṛ', +'Re': 'ℜ', +'ReverseElement': '∋', +'ReverseEquilibrium': '⇋', +'ReverseUpEquilibrium': '⥯', +'Rfr': 'ℜ', +'Rgr': 'Ρ', +'Rho': 'Ρ', +'RightAngleBracket': '⟩', +'RightArrow': '→', +'RightArrowBar': '⇥', +'RightArrowLeftArrow': '⇄', +'RightCeiling': '⌉', +'RightDoubleBracket': '⟧', +'RightDownTeeVector': '⥝', +'RightDownVector': '⇂', +'RightDownVectorBar': '⥕', +'RightFloor': '⌋', +'RightTee': '⊢', +'RightTeeArrow': '↦', +'RightTeeVector': '⥛', +'RightTriangle': '⊳', +'RightTriangleBar': '⧐', +'RightTriangleEqual': '⊵', +'RightUpDownVector': '⥏', +'RightUpTeeVector': '⥜', +'RightUpVector': '↾', +'RightUpVectorBar': '⥔', +'RightVector': '⇀', +'RightVectorBar': '⥓', +'Rightarrow': '⇒', +'Rmacrb': 'Ṟ', +'Ropf': 'ℝ', +'RoundImplies': '⥰', +'Rrightarrow': '⇛', +'Rscr': 'ℛ', +'Rsh': '↱', +'RuleDelayed': '⧴', +'SHCHcy': 'Щ', +'SHcy': 'Ш', +'SOFTcy': 'Ь', +'Sacute': 'Ś', +'Sacuteda': 'Ṥ', +'Sc': '⪼', +'Scaron': 'Š', +'Scaronda': 'Ṧ', +'Scedil': 'Ş', +'Scirc': 'Ŝ', +'Scy': 'С', +'Sdota': 'Ṡ', +'Sdotb': 'Ṣ', +'Sdotbda': 'Ṩ', +'Sfr': '𝔖', +'Sgr': 'Σ', +'ShortDownArrow': '↓', +'ShortLeftArrow': '←', +'ShortRightArrow': '→', +'ShortUpArrow': '↑', +'Sigma': 'Σ', +'SmallCircle': '∘', +'Sopf': '𝕊', +'Sqrt': '√', +'Square': '□', +'SquareIntersection': '⊓', +'SquareSubset': '⊏', +'SquareSubsetEqual': '⊑', +'SquareSuperset': '⊐', +'SquareSupersetEqual': '⊒', +'SquareUnion': '⊔', +'Sscr': '𝒮', +'Star': '⋆', +'Sub': '⋐', +'Subset': '⋐', +'SubsetEqual': '⊆', +'Succeeds': '≻', +'SucceedsEqual': '⪰', +'SucceedsSlantEqual': '≽', +'SucceedsTilde': '≿', +'SuchThat': '∋', +'Sum': '∑', +'Sup': '⋑', +'Superset': '⊃', +'SupersetEqual': '⊇', +'Supset': '⋑', +'THORN': r'\xde', +'THgr': 'Θ', +'TRADE': '™', +'TSHcy': 'Ћ', +'TScy': 'Ц', +'Tab': r'\t', +'Tau': 'Τ', +'Tcaron': 'Ť', +'Tcedil': 'Ţ', +'Tcommab': 'Ț', +'Tcy': 'Т', +'Tdot': 'Ṫ', +'Tdotb': 'Ṭ', +'Tfr': '𝔗', +'Tgr': 'Τ', +'Therefore': '∴', +'Theta': 'Θ', +'ThickSpace': '  ', +'ThinSpace': ' ', +'Tilde': '∼', +'TildeEqual': '≃', +'TildeFullEqual': '≅', +'TildeTilde': '≈', +'Tmacrb': 'Ṯ', +'Topf': '𝕋', +'TripleDot': '⃛', +'Tscr': '𝒯', +'Tstrok': 'Ŧ', +'Uacgr': 'Ύ', +'Uacute': r'\xda', +'Uarr': '↟', +'Uarrocir': '⥉', +'Ubrcy': 'Ў', +'Ubreve': 'Ŭ', +'Ucirc': r'\xdb', +'Ucy': 'У', +'Udblac': 'Ű', +'Udigr': 'Ϋ', +'Udlbdb': 'Ṳ', +'Udotb': 'Ụ', +'Ufr': '𝔘', +'Ugr': 'Υ', +'Ugrave': r'\xd9', +'Uhorn': 'Ư', +'Uhorndb': 'Ự', +'Uhorngr': 'Ừ', +'Uhornha': 'Ử', +'Uhornti': 'Ữ', +'Umacr': 'Ū', +'Umacrum': 'Ṻ', +'UnderBar': r'_', +'UnderBrace': '⏟', +'UnderBracket': '⎵', +'UnderParenthesis': '⏝', +'Union': '⋃', +'UnionPlus': '⊎', +'Uogon': 'Ų', +'Uopf': '𝕌', +'UpArrow': '↑', +'UpArrowBar': '⤒', +'UpArrowDownArrow': '⇅', +'UpDownArrow': '↕', +'UpEquilibrium': '⥮', +'UpTee': '⊥', +'UpTeeArrow': '↥', +'Uparrow': '⇑', +'Updownarrow': '⇕', +'UpperLeftArrow': '↖', +'UpperRightArrow': '↗', +'Upsi': 'Υ', +'Upsilon': 'Υ', +'Uring': 'Ů', +'Uscr': '𝒰', +'Utilde': 'Ũ', +'Uuml': r'\xdc', +'VDash': '⊫', +'Vbar': '⫫', +'Vcy': 'В', +'Vdash': '⊩', +'Vdashl': '⫦', +'Vdotb': 'Ṿ', +'Vee': '⋁', +'Verbar': '‖', +'Vert': '‖', +'VerticalBar': '∣', +'VerticalLine': r'|', +'VerticalSeparator': '❘', +'VerticalTilde': '≀', +'VeryThinSpace': ' ', +'Vfr': '𝔙', +'Vopf': '𝕍', +'Vscr': '𝒱', +'Vtilde': 'Ṽ', +'Vvdash': '⊪', +'Wacute': 'Ẃ', +'Wcirc': 'Ŵ', +'Wdot': 'Ẇ', +'Wedge': '⋀', +'Wfr': '𝔚', +'Wgrave': 'Ẁ', +'Wopf': '𝕎', +'Wscr': '𝒲', +'Wuml': 'Ẅ', +'Xdot': 'Ẋ', +'Xfr': '𝔛', +'Xgr': 'Ξ', +'Xi': 'Ξ', +'Xopf': '𝕏', +'Xscr': '𝒳', +'Xuml': 'Ẍ', +'YAcy': 'Я', +'YIcy': 'Ї', +'YUcy': 'Ю', +'Yacute': r'\xdd', +'Ycirc': 'Ŷ', +'Ycy': 'Ы', +'Ydot': 'Ẏ', +'Ydotb': 'Ỵ', +'Yfr': '𝔜', +'Ygrave': 'Ỳ', +'Yhooka': 'Ỷ', +'Ymacr': 'Ȳ', +'Yopf': '𝕐', +'Yscr': '𝒴', +'Ytilde': 'Ỹ', +'Yuml': 'Ÿ', +'ZHcy': 'Ж', +'Zacute': 'Ź', +'Zcaron': 'Ž', +'Zcirc': 'Ẑ', +'Zcy': 'З', +'Zdot': 'Ż', +'Zdotb': 'Ẓ', +'ZeroWidthSpace': '​', +'Zeta': 'Ζ', +'Zfr': 'ℨ', +'Zgr': 'Ζ', +'Zlowline': 'Ẕ', +'Zopf': 'ℤ', +'Zscr': '𝒵', +'aacgr': 'ά', +'aacute': r'\xe1', +'abreve': 'ă', +'abreveac': 'ắ', +'abrevedb': 'ặ', +'abrevegr': 'ằ', +'abreveha': 'ẳ', +'abreveti': 'ẵ', +'ac': '∾', +'acE': '∾̳', +'acaron': 'ǎ', +'acd': '∿', +'acirc': r'\xe2', +'acute': r'\xb4', +'acy': 'а', +'adot': 'ȧ', +'adotama': 'ǡ', +'adotb': 'ạ', +'aeacute': 'ǽ', +'aelig': r'\xe6', +'aemacr': 'ǣ', +'af': '⁡', +'afr': '𝔞', +'agr': 'α', +'agrave': r'\xe0', +'ahooka': 'ả', +'alefsym': 'ℵ', +'aleph': 'ℵ', +'alpha': 'α', +'amacr': 'ā', +'amalg': '⨿', +'and': '∧', +'andand': '⩕', +'andd': '⩜', +'andslope': '⩘', +'andv': '⩚', +'ang': '∠', +'ange': '⦤', +'angle': '∠', +'angmsd': '∡', +'angmsdaa': '⦨', +'angmsdab': '⦩', +'angmsdac': '⦪', +'angmsdad': '⦫', +'angmsdae': '⦬', +'angmsdaf': '⦭', +'angmsdag': '⦮', +'angmsdah': '⦯', +'angrt': '∟', +'angrtvb': '⊾', +'angrtvbd': '⦝', +'angsph': '∢', +'angst': r'\xc5', +'angzarr': '⍼', +'aogon': 'ą', +'aopf': '𝕒', +'ap': '≈', +'apE': '⩰', +'apacir': '⩯', +'ape': '≊', +'apid': '≋', +'apos': 'ʼ', +'approx': '≈', +'approxeq': '≊', +'aring': r'\xe5', +'ascr': '𝒶', +'ast': r'*', +'asymp': '≈', +'asympeq': '≍', +'atilde': r'\xe3', +'auml': r'\xe4', +'awconint': '∳', +'awint': '⨑', +'bNot': '⫭', +'backcong': '≌', +'backepsilon': '϶', +'backprime': '‵', +'backsim': '∽', +'backsimeq': '⋍', +'barvee': '⊽', +'barwed': '⌅', +'barwedge': '⌅', +'bbrk': '⎵', +'bbrktbrk': '⎶', +'bcong': '≌', +'bcy': 'б', +'bdota': 'ḃ', +'bdotb': 'ḅ', +'bdquo': '„', +'becaus': '∵', +'because': '∵', +'bemptyv': '⦰', +'bepsi': '϶', +'bernou': 'ℬ', +'beta': 'β', +'beth': 'ℶ', +'between': '≬', +'bfr': '𝔟', +'bgr': 'β', +'bigcap': '⋂', +'bigcirc': '◯', +'bigcup': '⋃', +'bigodot': '⨀', +'bigoplus': '⨁', +'bigotimes': '⨂', +'bigsqcup': '⨆', +'bigstar': '★', +'bigtriangledown': '▽', +'bigtriangleup': '△', +'biguplus': '⨄', +'bigvee': '⋁', +'bigwedge': '⋀', +'bkarow': '⤍', +'blacklozenge': '⧫', +'blacksquare': '▪', +'blacktriangle': '▴', +'blacktriangledown': '▾', +'blacktriangleleft': '◂', +'blacktriangleright': '▸', +'blank': '␣', +'blk12': '▒', +'blk14': '░', +'blk34': '▓', +'block': '█', +'bmacrb': 'ḇ', +'bne': '⃥', +'bnequiv': '≡⃥', +'bnot': '⌐', +'bopf': '𝕓', +'bot': '⊥', +'bottom': '⊥', +'bowtie': '⋈', +'boxDL': '╗', +'boxDR': '╔', +'boxDl': '╖', +'boxDr': '╓', +'boxH': '═', +'boxHD': '╦', +'boxHU': '╩', +'boxHd': '╤', +'boxHu': '╧', +'boxUL': '╝', +'boxUR': '╚', +'boxUl': '╜', +'boxUr': '╙', +'boxV': '║', +'boxVH': '╬', +'boxVL': '╣', +'boxVR': '╠', +'boxVh': '╫', +'boxVl': '╢', +'boxVr': '╟', +'boxbox': '⧉', +'boxdL': '╕', +'boxdR': '╒', +'boxdl': '┐', +'boxdr': '┌', +'boxh': '─', +'boxhD': '╥', +'boxhU': '╨', +'boxhd': '┬', +'boxhu': '┴', +'boxminus': '⊟', +'boxplus': '⊞', +'boxtimes': '⊠', +'boxuL': '╛', +'boxuR': '╘', +'boxul': '┘', +'boxur': '└', +'boxv': '│', +'boxvH': '╪', +'boxvL': '╡', +'boxvR': '╞', +'boxvh': '┼', +'boxvl': '┤', +'boxvr': '├', +'bprime': '‵', +'breve': '˘', +'breveb': '̮', +'brvbar': r'\xa6', +'bscr': '𝒷', +'bsemi': '⁏', +'bsim': '∽', +'bsime': '⋍', +'bsol': r'\\', +'bsolb': '⧅', +'bsolhsub': '⟈', +'bull': '•', +'bullet': '•', +'bump': '≎', +'bumpE': '⪮', +'bumpe': '≏', +'bumpeq': '≏', +'cacute': 'ć', +'candra': '̐', +'cap': '∩', +'capand': '⩄', +'capbrcup': '⩉', +'capcap': '⩋', +'capcup': '⩇', +'capdot': '⩀', +'caps': '∩︀', +'caret': '⁁', +'caron': 'ˇ', +'ccaps': '⩍', +'ccaron': 'č', +'ccedil': r'\xe7', +'ccirc': 'ĉ', +'ccups': '⩌', +'ccupssm': '⩐', +'cdot': 'ċ', +'cedil': r'\xb8', +'cemptyv': '⦲', +'cent': r'\xa2', +'centerdot': r'\xb7', +'cfr': '𝔠', +'chcy': 'ч', +'check': '✓', +'checkmark': '✓', +'chi': 'χ', +'cir': '○', +'cirE': '⧃', +'circ': 'ˆ', +'circeq': '≗', +'circlearrowleft': '↺', +'circlearrowright': '↻', +'circledR': r'\xae', +'circledS': 'Ⓢ', +'circledast': '⊛', +'circledcirc': '⊚', +'circleddash': '⊝', +'cire': '≗', +'cirfnint': '⨐', +'cirmid': '⫯', +'cirscir': '⧂', +'clubs': '♣', +'clubsuit': '♣', +'colon': r':', +'colone': '≔', +'coloneq': '≔', +'comma': r',', +'commaa': '̓', +'commab': '̦', +'commat': r'@', +'comp': '∁', +'compfn': '∘', +'complement': '∁', +'complexes': 'ℂ', +'cong': '≅', +'congdot': '⩭', +'conint': '∮', +'copf': '𝕔', +'coprod': '∐', +'copy': r'\xa9', +'copysr': '℗', +'crarr': '↵', +'cross': '✗', +'cscr': '𝒸', +'csub': '⫏', +'csube': '⫑', +'csup': '⫐', +'csupe': '⫒', +'ctdot': '⋯', +'cudarrl': '⤸', +'cudarrr': '⤵', +'cuepr': '⋞', +'cuesc': '⋟', +'cularr': '↶', +'cularrp': '⤽', +'cup': '∪', +'cupbrcap': '⩈', +'cupcap': '⩆', +'cupcup': '⩊', +'cupdot': '⊍', +'cupor': '⩅', +'cups': '∪︀', +'curarr': '↷', +'curarrm': '⤼', +'curlyeqprec': '⋞', +'curlyeqsucc': '⋟', +'curlyvee': '⋎', +'curlywedge': '⋏', +'curren': r'\xa4', +'curvearrowleft': '↶', +'curvearrowright': '↷', +'cuvee': '⋎', +'cuwed': '⋏', +'cwconint': '∲', +'cwint': '∱', +'cylcty': '⌭', +'dArr': '⇓', +'dHar': '⥥', +'dagger': '†', +'daleth': 'ℸ', +'darr': '↓', +'dash': '‐', +'dashv': '⊣', +'dbkarow': '⤏', +'dblac': '˝', +'dbldotb': '̤', +'dblunder': '̳', +'dcaron': 'ď', +'dcommab': 'ḑ', +'dcy': 'д', +'dd': 'ⅆ', +'ddagger': '‡', +'ddarr': '⇊', +'ddota': 'ḋ', +'ddotb': 'ḍ', +'ddotseq': '⩷', +'deg': r'\xb0', +'delta': 'δ', +'demptyv': '⦱', +'dfisht': '⥿', +'dfr': '𝔡', +'dgr': 'δ', +'dharl': '⇃', +'dharr': '⇂', +'diam': '⋄', +'diamond': '⋄', +'diamondsuit': '♦', +'diams': '♦', +'die': r'\xa8', +'digamma': 'ϝ', +'disin': '⋲', +'div': r'\xf7', +'divide': r'\xf7', +'divideontimes': '⋇', +'divonx': '⋇', +'djcy': 'ђ', +'dlcorn': '⌞', +'dlcrop': '⌍', +'dmacrb': 'ḏ', +'dollar': r'$', +'dopf': '𝕕', +'dot': '˙', +'dotb': '̣', +'doteq': '≐', +'doteqdot': '≑', +'dotminus': '∸', +'dotplus': '∔', +'dotsquare': '⊡', +'doublebarwedge': '⌆', +'downarrow': '↓', +'downdownarrows': '⇊', +'downharpoonleft': '⇃', +'downharpoonright': '⇂', +'drbkarow': '⤐', +'drcorn': '⌟', +'drcrop': '⌌', +'dscr': '𝒹', +'dscy': 'ѕ', +'dsol': '⧶', +'dstrok': 'đ', +'dtdot': '⋱', +'dtri': '▿', +'dtrif': '▾', +'duarr': '⇵', +'duhar': '⥯', +'dwangle': '⦦', +'dzcy': 'џ', +'dzigrarr': '⟿', +'eDDot': '⩷', +'eDot': '≑', +'eacgr': 'έ', +'eacute': r'\xe9', +'easter': '⩮', +'ebreve': 'ĕ', +'ecaron': 'ě', +'ecedil': 'ȩ', +'ecedilbr': 'ḝ', +'ecir': '≖', +'ecirc': r'\xea', +'ecolon': '≕', +'ecy': 'э', +'edot': 'ė', +'edotb': 'ẹ', +'ee': 'ⅇ', +'eeacgr': 'ή', +'eegr': 'η', +'efDot': '≒', +'efr': '𝔢', +'eg': '⪚', +'egr': 'ε', +'egrave': r'\xe8', +'egs': '⪖', +'egsdot': '⪘', +'ehooka': 'ẻ', +'el': '⪙', +'elinters': '⏧', +'ell': 'ℓ', +'els': '⪕', +'elsdot': '⪗', +'emacr': 'ē', +'emacrac': 'ḗ', +'emacrgr': 'ḕ', +'empty': '∅', +'emptyset': '∅', +'emptyv': '∅', +'emsp': ' ', +'emsp13': ' ', +'emsp14': ' ', +'eng': 'ŋ', +'ensp': ' ', +'eogon': 'ę', +'eopf': '𝕖', +'epar': '⋕', +'eparsl': '⧣', +'eplus': '⩱', +'epsi': 'ε', +'epsilon': 'ε', +'epsiv': 'ϵ', +'eqcirc': '≖', +'eqcolon': '≕', +'eqsim': '≂', +'eqslantgtr': '⪖', +'eqslantless': '⪕', +'equals': r'=', +'equest': '≟', +'equiv': '≡', +'equivDD': '⩸', +'eqvparsl': '⧥', +'erDot': '≓', +'erarr': '⥱', +'escr': 'ℯ', +'esdot': '≐', +'esim': '≂', +'eta': 'η', +'eth': r'\xf0', +'etilde': 'ẽ', +'euml': r'\xeb', +'euro': '€', +'excl': r'!', +'exist': '∃', +'expectation': 'ℰ', +'exponentiale': 'ⅇ', +'fallingdotseq': '≒', +'fcy': 'ф', +'fdot': 'ḟ', +'female': '♀', +'ffilig': 'ffi', +'fflig': 'ff', +'ffllig': 'ffl', +'ffr': '𝔣', +'filig': 'fi', +'fjlig': r'fj', +'flat': '♭', +'fllig': 'fl', +'fltns': '▱', +'fnof': 'ƒ', +'fopf': '𝕗', +'forall': '∀', +'fork': '⋔', +'forkv': '⫙', +'fpartint': '⨍', +'frac12': r'\xbd', +'frac13': '⅓', +'frac14': r'\xbc', +'frac15': '⅕', +'frac16': '⅙', +'frac18': '⅛', +'frac23': '⅔', +'frac25': '⅖', +'frac34': r'\xbe', +'frac35': '⅗', +'frac38': '⅜', +'frac45': '⅘', +'frac56': '⅚', +'frac58': '⅝', +'frac78': '⅞', +'frasl': '⁄', +'frown': '⌢', +'fscr': '𝒻', +'gE': '≧', +'gEl': '⪌', +'gacute': 'ǵ', +'gamma': 'γ', +'gammad': 'ϝ', +'gap': '⪆', +'gbreve': 'ğ', +'gcaron': 'ǧ', +'gcedil': 'ģ', +'gcirc': 'ĝ', +'gcy': 'г', +'gdot': 'ġ', +'ge': '≥', +'gel': '⋛', +'geq': '≥', +'geqq': '≧', +'geqslant': '⩾', +'ges': '⩾', +'gescc': '⪩', +'gesdot': '⪀', +'gesdoto': '⪂', +'gesdotol': '⪄', +'gesl': '⋛︀', +'gesles': '⪔', +'gfr': '𝔤', +'gg': '≫', +'ggg': '⋙', +'ggr': 'γ', +'gimel': 'ℷ', +'gjcy': 'ѓ', +'gl': '≷', +'glE': '⪒', +'gla': '⪥', +'glj': '⪤', +'gmacr': 'ḡ', +'gnE': '≩', +'gnap': '⪊', +'gnapprox': '⪊', +'gne': '⪈', +'gneq': '⪈', +'gneqq': '≩', +'gnsim': '⋧', +'gopf': '𝕘', +'grave': r'`', +'gscr': 'ℊ', +'gsim': '≳', +'gsime': '⪎', +'gsiml': '⪐', +'gstrok': 'ǥ', +'gt': r'>', +'gtcc': '⪧', +'gtcir': '⩺', +'gtdot': '⋗', +'gtlPar': '⦕', +'gtquest': '⩼', +'gtrapprox': '⪆', +'gtrarr': '⥸', +'gtrdot': '⋗', +'gtreqless': '⋛', +'gtreqqless': '⪌', +'gtrless': '≷', +'gtrsim': '≳', +'gvertneqq': '≩︀', +'gvnE': '≩︀', +'hArr': '⇔', +'hairsp': ' ', +'half': r'\xbd', +'hamilt': 'ℋ', +'hardcy': 'ъ', +'hardsign': 'ʺ', +'harr': '↔', +'harrcir': '⥈', +'harrw': '↭', +'hbar': 'ℏ', +'hbreveb': 'ḫ', +'hcaron': 'ȟ', +'hcedil': 'ḩ', +'hcirc': 'ĥ', +'hdot': 'ḣ', +'hdotb': 'ḥ', +'hearts': '♥', +'heartsuit': '♥', +'hellip': '…', +'hercon': '⊹', +'hfr': '𝔥', +'hksearow': '⤥', +'hkswarow': '⤦', +'hlowline': 'ẖ', +'hoarr': '⇿', +'homtht': '∻', +'hooka': '̉', +'hookleftarrow': '↩', +'hookrightarrow': '↪', +'hopf': '𝕙', +'horbar': '―', +'hscr': '𝒽', +'hslash': 'ℏ', +'hstrok': 'ħ', +'hstroke': 'ħ', +'huml': 'ḧ', +'hybull': '⁃', +'hyphen': '‐', +'iacgr': 'ί', +'iacute': r'\xed', +'ibreve': 'ĭ', +'ic': '⁣', +'icaron': 'ǐ', +'icirc': r'\xee', +'icy': 'и', +'idiagr': 'ΐ', +'idigr': 'ϊ', +'idotb': 'ị', +'iecy': 'е', +'iexcl': r'\xa1', +'iff': '⇔', +'ifr': '𝔦', +'igr': 'ι', +'igrave': r'\xec', +'ihooka': 'ỉ', +'ii': 'ⅈ', +'iiiint': '⨌', +'iiint': '∭', +'iinfin': '⧜', +'iiota': '℩', +'ijlig': 'ij', +'imacr': 'ī', +'image': 'ℑ', +'imagline': 'ℐ', +'imagpart': 'ℑ', +'imath': 'ı', +'imof': '⊷', +'imped': 'Ƶ', +'in': '∈', +'incare': '℅', +'infin': '∞', +'infintie': '⧝', +'inodot': 'ı', +'int': '∫', +'intcal': '⊺', +'integers': 'ℤ', +'intercal': '⊺', +'intlarhk': '⨗', +'intprod': '⨼', +'iocy': 'ё', +'iogon': 'į', +'iopf': '𝕚', +'iota': 'ι', +'iprod': '⨼', +'iquest': r'\xbf', +'iscr': '𝒾', +'isin': '∈', +'isinE': '⋹', +'isindot': '⋵', +'isins': '⋴', +'isinsv': '⋳', +'isinv': '∈', +'it': '⁢', +'itilde': 'ĩ', +'iukcy': 'і', +'iuml': r'\xef', +'jcaron': 'ǰ', +'jcirc': 'ĵ', +'jcy': 'й', +'jfr': '𝔧', +'jmath': 'ȷ', +'jopf': '𝕛', +'jscr': '𝒿', +'jsercy': 'ј', +'jukcy': 'є', +'kacute': 'ḱ', +'kappa': 'κ', +'kappav': 'ϰ', +'kcedil': 'ķ', +'kcirc': 'ǩ', +'kcy': 'к', +'kdotb': 'ḳ', +'kfr': '𝔨', +'kgr': 'κ', +'kgreen': 'ĸ', +'khcy': 'х', +'khgr': 'χ', +'kjcy': 'ќ', +'kmacrb': 'ḵ', +'kopf': '𝕜', +'kscr': '𝓀', +'lAarr': '⇚', +'lArr': '⇐', +'lAtail': '⤛', +'lBarr': '⤎', +'lE': '≦', +'lEg': '⪋', +'lHar': '⥢', +'lacute': 'ĺ', +'laemptyv': '⦴', +'lagran': 'ℒ', +'lambda': 'λ', +'lang': '⟨', +'langd': '⦑', +'langle': '⟨', +'lap': '⪅', +'laquo': r'\xab', +'larr': '←', +'larrb': '⇤', +'larrbfs': '⤟', +'larrfs': '⤝', +'larrhk': '↩', +'larrlp': '↫', +'larrpl': '⤹', +'larrsim': '⥳', +'larrtl': '↢', +'lat': '⪫', +'latail': '⤙', +'late': '⪭', +'lates': '⪭︀', +'lbarr': '⤌', +'lbbrk': '❲', +'lbrace': r'{', +'lbrack': r'[', +'lbrke': '⦋', +'lbrksld': '⦏', +'lbrkslu': '⦍', +'lcaron': 'ľ', +'lcedil': 'ļ', +'lceil': '⌈', +'lcirc': 'ḽ', +'lcub': r'{', +'lcy': 'л', +'ldbltil': '︢', +'ldca': '⤶', +'ldotb': 'ḷ', +'ldotbma': 'ḹ', +'ldquo': '“', +'ldquor': '„', +'ldrdhar': '⥧', +'ldrushar': '⥋', +'ldsh': '↲', +'le': '≤', +'leftarrow': '←', +'leftarrowtail': '↢', +'leftharpoondown': '↽', +'leftharpoonup': '↼', +'leftleftarrows': '⇇', +'leftrightarrow': '↔', +'leftrightarrows': '⇆', +'leftrightharpoons': '⇋', +'leftrightsquigarrow': '↭', +'leftthreetimes': '⋋', +'leg': '⋚', +'leq': '≤', +'leqq': '≦', +'leqslant': '⩽', +'les': '⩽', +'lescc': '⪨', +'lesdot': '⩿', +'lesdoto': '⪁', +'lesdotor': '⪃', +'lesg': '⋚︀', +'lesges': '⪓', +'lessapprox': '⪅', +'lessdot': '⋖', +'lesseqgtr': '⋚', +'lesseqqgtr': '⪋', +'lessgtr': '≶', +'lesssim': '≲', +'lfisht': '⥼', +'lfloor': '⌊', +'lfr': '𝔩', +'lg': '≶', +'lgE': '⪑', +'lgr': 'λ', +'lhard': '↽', +'lharu': '↼', +'lharul': '⥪', +'lhblk': '▄', +'ljcy': 'љ', +'ll': '≪', +'llarr': '⇇', +'llcorner': '⌞', +'llhard': '⥫', +'llig': '︠', +'lltri': '◺', +'lmacrb': 'ḻ', +'lmidot': 'ŀ', +'lmoust': '⎰', +'lmoustache': '⎰', +'lnE': '≨', +'lnap': '⪉', +'lnapprox': '⪉', +'lne': '⪇', +'lneq': '⪇', +'lneqq': '≨', +'lnsim': '⋦', +'loang': '⟬', +'loarr': '⇽', +'lobrk': '⟦', +'longleftarrow': '⟵', +'longleftrightarrow': '⟷', +'longmapsto': '⟼', +'longrightarrow': '⟶', +'looparrowleft': '↫', +'looparrowright': '↬', +'lopar': '⦅', +'lopf': '𝕝', +'loplus': '⨭', +'lotimes': '⨴', +'lowast': '∗', +'lowbar': r'_', +'loz': '◊', +'lozenge': '◊', +'lozf': '⧫', +'lpar': r'(', +'lparlt': '⦓', +'lrarr': '⇆', +'lrcorner': '⌟', +'lrhar': '⇋', +'lrhard': '⥭', +'lrm': '‎', +'lrtri': '⊿', +'lsaquo': '‹', +'lscr': '𝓁', +'lsh': '↰', +'lsim': '≲', +'lsime': '⪍', +'lsimg': '⪏', +'lsqb': r'[', +'lsquo': '‘', +'lsquor': '‚', +'lstrok': 'ł', +'lt': r'<', +'ltcc': '⪦', +'ltcir': '⩹', +'ltdot': '⋖', +'lthree': '⋋', +'ltimes': '⋉', +'ltlarr': '⥶', +'ltquest': '⩻', +'ltrPar': '⦖', +'ltri': '◃', +'ltrie': '⊴', +'ltrif': '◂', +'lurdshar': '⥊', +'luruhar': '⥦', +'lvertneqq': '≨︀', +'lvnE': '≨︀', +'mDDot': '∺', +'macr': r'\xaf', +'macute': 'ḿ', +'male': '♂', +'malt': '✠', +'maltese': '✠', +'map': '↦', +'mapsto': '↦', +'mapstodown': '↧', +'mapstoleft': '↤', +'mapstoup': '↥', +'marker': '▮', +'mcomma': '⨩', +'mcy': 'м', +'mdash': '—', +'mdot': 'ṁ', +'mdotb': 'ṃ', +'measuredangle': '∡', +'mfr': '𝔪', +'mgr': 'μ', +'mho': '℧', +'micro': r'\xb5', +'mid': '∣', +'midast': r'*', +'midcir': '⫰', +'middot': r'\xb7', +'minus': '−', +'minusb': '⊟', +'minusd': '∸', +'minusdu': '⨪', +'mlcp': '⫛', +'mldr': '…', +'mllhring': 'ʿ', +'mlrhring': 'ʾ', +'mnplus': '∓', +'models': '⊧', +'mopf': '𝕞', +'mp': '∓', +'mscr': '𝓂', +'mstpos': '∾', +'mu': 'μ', +'multimap': '⊸', +'mumap': '⊸', +'nGg': '⋙̸', +'nGt': '≫⃒', +'nGtv': '≫̸', +'nLeftarrow': '⇍', +'nLeftrightarrow': '⇎', +'nLl': '⋘̸', +'nLt': '≪⃒', +'nLtv': '≪̸', +'nRightarrow': '⇏', +'nVDash': '⊯', +'nVdash': '⊮', +'nabla': '∇', +'nacute': 'ń', +'nang': '∠⃒', +'nap': '≉', +'napE': '⩰̸', +'napid': '≋̸', +'napos': 'ʼn', +'napprox': '≉', +'natur': '♮', +'natural': '♮', +'naturals': 'ℕ', +'nbsp': r'\xa0', +'nbump': '≎̸', +'nbumpe': '≏̸', +'ncap': '⩃', +'ncaron': 'ň', +'ncedil': 'ņ', +'ncong': '≇', +'ncongdot': '⩭̸', +'ncup': '⩂', +'ncy': 'н', +'ndash': '–', +'ndot': 'ṅ', +'ndotb': 'ṇ', +'ne': '≠', +'neArr': '⇗', +'nearhk': '⤤', +'nearr': '↗', +'nearrow': '↗', +'nedot': '≐̸', +'nequiv': '≢', +'nesear': '⤨', +'nesim': '≂̸', +'nexist': '∄', +'nexists': '∄', +'nfr': '𝔫', +'ngE': '≧̸', +'nge': '≱', +'ngeq': '≱', +'ngeqq': '≧̸', +'ngeqslant': '⩾̸', +'nges': '⩾̸', +'ngr': 'ν', +'ngrave': 'ǹ', +'ngsim': '≵', +'ngt': '≯', +'ngtr': '≯', +'nhArr': '⇎', +'nharr': '↮', +'nhpar': '⫲', +'ni': '∋', +'nis': '⋼', +'nisd': '⋺', +'niv': '∋', +'njcy': 'њ', +'nlArr': '⇍', +'nlE': '≦̸', +'nlarr': '↚', +'nldr': '‥', +'nle': '≰', +'nleftarrow': '↚', +'nleftrightarrow': '↮', +'nleq': '≰', +'nleqq': '≦̸', +'nleqslant': '⩽̸', +'nles': '⩽̸', +'nless': '≮', +'nlsim': '≴', +'nlt': '≮', +'nltri': '⋪', +'nltrie': '⋬', +'nmacrb': 'ṉ', +'nmid': '∤', +'nopf': '𝕟', +'not': r'\xac', +'notin': '∉', +'notinE': '⋹̸', +'notindot': '⋵̸', +'notinva': '∉', +'notinvb': '⋷', +'notinvc': '⋶', +'notni': '∌', +'notniva': '∌', +'notnivb': '⋾', +'notnivc': '⋽', +'npar': '∦', +'nparallel': '∦', +'nparsl': '⫽⃥', +'npart': '∂̸', +'npolint': '⨔', +'npr': '⊀', +'nprcue': '⋠', +'npre': '⪯̸', +'nprec': '⊀', +'npreceq': '⪯̸', +'nrArr': '⇏', +'nrarr': '↛', +'nrarrc': '⤳̸', +'nrarrw': '↝̸', +'nrightarrow': '↛', +'nrtri': '⋫', +'nrtrie': '⋭', +'nsc': '⊁', +'nsccue': '⋡', +'nsce': '⪰̸', +'nscr': '𝓃', +'nshortmid': '∤', +'nshortparallel': '∦', +'nsim': '≁', +'nsime': '≄', +'nsimeq': '≄', +'nsmid': '∤', +'nspar': '∦', +'nsqsube': '⋢', +'nsqsupe': '⋣', +'nsub': '⊄', +'nsubE': '⫅̸', +'nsube': '⊈', +'nsubset': '⊂⃒', +'nsubseteq': '⊈', +'nsubseteqq': '⫅̸', +'nsucc': '⊁', +'nsucceq': '⪰̸', +'nsup': '⊅', +'nsupE': '⫆̸', +'nsupe': '⊉', +'nsupset': '⊃⃒', +'nsupseteq': '⊉', +'nsupseteqq': '⫆̸', +'ntgl': '≹', +'ntilde': r'\xf1', +'ntlg': '≸', +'ntriangleleft': '⋪', +'ntrianglelefteq': '⋬', +'ntriangleright': '⋫', +'ntrianglerighteq': '⋭', +'nu': 'ν', +'num': r'#', +'numero': '№', +'numsp': ' ', +'nvDash': '⊭', +'nvHarr': '⤄', +'nvap': '≍⃒', +'nvdash': '⊬', +'nvge': '≥⃒', +'nvgt': r'>⃒', +'nvinfin': '⧞', +'nvlArr': '⤂', +'nvle': '≤⃒', +'nvlt': r'<⃒', +'nvltrie': '⊴⃒', +'nvrArr': '⤃', +'nvrtrie': '⊵⃒', +'nvsim': '∼⃒', +'nwArr': '⇖', +'nwarhk': '⤣', +'nwarr': '↖', +'nwarrow': '↖', +'nwnear': '⤧', +'oS': 'Ⓢ', +'oacgr': 'ό', +'oacute': r'\xf3', +'oast': '⊛', +'obreve': 'ŏ', +'ocaron': 'ǒ', +'ocir': '⊚', +'ocirc': r'\xf4', +'ocy': 'о', +'odash': '⊝', +'odblac': 'ő', +'odiv': '⨸', +'odot': '⊙', +'odota': 'ȯ', +'odotama': 'ȱ', +'odotb': 'ọ', +'odsold': '⦼', +'oelig': 'œ', +'ofcir': '⦿', +'ofr': '𝔬', +'ogon': '˛', +'ogr': 'ο', +'ograve': r'\xf2', +'ogt': '⧁', +'ohacgr': 'ώ', +'ohbar': '⦵', +'ohgr': 'ω', +'ohm': 'Ω', +'ohooka': 'ỏ', +'ohorn': 'ơ', +'ohornac': 'ớ', +'ohorndb': 'ợ', +'ohorngr': 'ờ', +'ohornha': 'ở', +'ohornti': 'ỡ', +'oint': '∮', +'olarr': '↺', +'olcir': '⦾', +'olcross': '⦻', +'oline': '‾', +'olt': '⧀', +'omacr': 'ō', +'omacrac': 'ṓ', +'omacrgr': 'ṑ', +'omega': 'ω', +'omicron': 'ο', +'omid': '⦶', +'ominus': '⊖', +'oogon': 'ǫ', +'oogonma': 'ǭ', +'oopf': '𝕠', +'opar': '⦷', +'operp': '⦹', +'oplus': '⊕', +'or': '∨', +'orarr': '↻', +'ord': '⩝', +'order': 'ℴ', +'orderof': 'ℴ', +'ordf': r'\xaa', +'ordm': r'\xba', +'origof': '⊶', +'oror': '⩖', +'orslope': '⩗', +'orv': '⩛', +'oscr': 'ℴ', +'oslash': r'\xf8', +'osol': '⊘', +'otilde': r'\xf5', +'otimes': '⊗', +'otimesas': '⨶', +'ouml': r'\xf6', +'ovbar': '⌽', +'pacute': 'ṕ', +'par': '∥', +'para': r'\xb6', +'parallel': '∥', +'parsim': '⫳', +'parsl': '⫽', +'part': '∂', +'pcy': 'п', +'pdota': 'ṗ', +'percnt': '%', +'period': r'.', +'permil': '‰', +'perp': '⊥', +'pertenk': '‱', +'pfr': '𝔭', +'pgr': 'π', +'phgr': 'φ', +'phi': 'φ', +'phiv': 'ϕ', +'phmmat': 'ℳ', +'phone': '☎', +'pi': 'π', +'pitchfork': '⋔', +'piv': 'ϖ', +'planck': 'ℏ', +'planckh': 'ℎ', +'plankv': 'ℏ', +'plus': r'+', +'plusacir': '⨣', +'plusb': '⊞', +'pluscir': '⨢', +'plusdo': '∔', +'plusdu': '⨥', +'pluse': '⩲', +'plusmn': r'\xb1', +'plussim': '⨦', +'plustwo': '⨧', +'pm': r'\xb1', +'pointint': '⨕', +'popf': '𝕡', +'pound': r'\xa3', +'pr': '≺', +'prE': '⪳', +'prap': '⪷', +'prcue': '≼', +'pre': '⪯', +'prec': '≺', +'precapprox': '⪷', +'preccurlyeq': '≼', +'preceq': '⪯', +'precnapprox': '⪹', +'precneqq': '⪵', +'precnsim': '⋨', +'precsim': '≾', +'prime': '′', +'primes': 'ℙ', +'prnE': '⪵', +'prnap': '⪹', +'prnsim': '⋨', +'prod': '∏', +'profalar': '⌮', +'profline': '⌒', +'profsurf': '⌓', +'prop': '∝', +'propto': '∝', +'prsim': '≾', +'prurel': '⊰', +'pscr': '𝓅', +'psgr': 'ψ', +'psi': 'ψ', +'puncsp': ' ', +'qfr': '𝔮', +'qint': '⨌', +'qopf': '𝕢', +'qprime': '⁗', +'qscr': '𝓆', +'quaternions': 'ℍ', +'quatint': '⨖', +'quest': r'?', +'questeq': '≟', +'rAarr': '⇛', +'rArr': '⇒', +'rAtail': '⤜', +'rBarr': '⤏', +'rHar': '⥤', +'race': '∽̱', +'racute': 'ŕ', +'radic': '√', +'raemptyv': '⦳', +'rang': '⟩', +'rangd': '⦒', +'range': '⦥', +'rangle': '⟩', +'raquo': r'\xbb', +'rarr': '→', +'rarrap': '⥵', +'rarrb': '⇥', +'rarrbfs': '⤠', +'rarrc': '⤳', +'rarrfs': '⤞', +'rarrhk': '↪', +'rarrlp': '↬', +'rarrpl': '⥅', +'rarrsim': '⥴', +'rarrtl': '↣', +'rarrw': '↝', +'ratail': '⤚', +'ratio': '∶', +'rationals': 'ℚ', +'rbarr': '⤍', +'rbbrk': '❳', +'rbrace': r'}', +'rbrack': r']', +'rbrke': '⦌', +'rbrksld': '⦎', +'rbrkslu': '⦐', +'rcaron': 'ř', +'rcedil': 'ŗ', +'rceil': '⌉', +'rcommaa': '̕', +'rcub': r'}', +'rcy': 'р', +'rdbltil': '︣', +'rdca': '⤷', +'rdldhar': '⥩', +'rdota': 'ṙ', +'rdotb': 'ṛ', +'rdquo': '”', +'rdquor': '”', +'rdsh': '↳', +'real': 'ℜ', +'realine': 'ℛ', +'realpart': 'ℜ', +'reals': 'ℝ', +'rect': '▭', +'reg': r'\xae', +'rfisht': '⥽', +'rfloor': '⌋', +'rfr': '𝔯', +'rgr': 'ρ', +'rhard': '⇁', +'rharu': '⇀', +'rharul': '⥬', +'rho': 'ρ', +'rhov': 'ϱ', +'rightarrow': '→', +'rightarrowtail': '↣', +'rightharpoondown': '⇁', +'rightharpoonup': '⇀', +'rightleftarrows': '⇄', +'rightleftharpoons': '⇌', +'rightrightarrows': '⇉', +'rightsquigarrow': '↝', +'rightthreetimes': '⋌', +'ring': '˚', +'ringb': '̥', +'risingdotseq': '≓', +'rlarr': '⇄', +'rlhar': '⇌', +'rlig': '︡', +'rlm': '‏', +'rmacrb': 'ṟ', +'rmoust': '⎱', +'rmoustache': '⎱', +'rnmid': '⫮', +'roang': '⟭', +'roarr': '⇾', +'robrk': '⟧', +'ropar': '⦆', +'ropf': '𝕣', +'roplus': '⨮', +'rotimes': '⨵', +'rpar': r')', +'rpargt': '⦔', +'rppolint': '⨒', +'rrarr': '⇉', +'rsaquo': '›', +'rscr': '𝓇', +'rsh': '↱', +'rsqb': r']', +'rsquo': '’', +'rsquor': '’', +'rthree': '⋌', +'rtimes': '⋊', +'rtri': '▹', +'rtrie': '⊵', +'rtrif': '▸', +'rtriltri': '⧎', +'ruluhar': '⥨', +'rx': '℞', +'sacute': 'ś', +'sacuteda': 'ṥ', +'sbquo': '‚', +'sc': '≻', +'scE': '⪴', +'scap': '⪸', +'scaron': 'š', +'scaronda': 'ṧ', +'sccue': '≽', +'sce': '⪰', +'scedil': 'ş', +'scirc': 'ŝ', +'scnE': '⪶', +'scnap': '⪺', +'scnsim': '⋩', +'scommab': 'ș', +'scpolint': '⨓', +'scriptl': 'ℓ', +'scsim': '≿', +'scy': 'с', +'sdot': '⋅', +'sdota': 'ṡ', +'sdotb': '⊡', +'sdotbda': 'ṩ', +'sdote': '⩦', +'seArr': '⇘', +'searhk': '⤥', +'searr': '↘', +'searrow': '↘', +'sect': r'\xa7', +'semi': r';', +'seswar': '⤩', +'setminus': '∖', +'setmn': '∖', +'sext': '✶', +'sfgr': 'ς', +'sfr': '𝔰', +'sfrown': '⌢', +'sgr': 'σ', +'sharp': '♯', +'shchcy': 'щ', +'shcy': 'ш', +'shortmid': '∣', +'shortparallel': '∥', +'shy': r'\xad', +'sigma': 'σ', +'sigmaf': 'ς', +'sigmav': 'ς', +'sim': '∼', +'simdot': '⩪', +'sime': '≃', +'simeq': '≃', +'simg': '⪞', +'simgE': '⪠', +'siml': '⪝', +'simlE': '⪟', +'simne': '≆', +'simplus': '⨤', +'simrarr': '⥲', +'slarr': '←', +'smallsetminus': '∖', +'smashp': '⨳', +'smeparsl': '⧤', +'smid': '∣', +'smile': '⌣', +'smt': '⪪', +'smte': '⪬', +'smtes': '⪬︀', +'softcy': 'ь', +'softsign': 'ʹ', +'sol': r'/', +'solb': '⧄', +'solbar': '⌿', +'sopf': '𝕤', +'spades': '♠', +'spadesuit': '♠', +'spar': '∥', +'sqcap': '⊓', +'sqcaps': '⊓︀', +'sqcup': '⊔', +'sqcups': '⊔︀', +'sqsub': '⊏', +'sqsube': '⊑', +'sqsubset': '⊏', +'sqsubseteq': '⊑', +'sqsup': '⊐', +'sqsupe': '⊒', +'sqsupset': '⊐', +'sqsupseteq': '⊒', +'squ': '□', +'square': '□', +'squarf': '▪', +'squf': '▪', +'srarr': '→', +'sscr': '𝓈', +'ssetmn': '∖', +'ssmile': '⌣', +'sstarf': '⋆', +'star': '☆', +'starf': '★', +'straightepsilon': 'ϵ', +'straightphi': 'ϕ', +'strns': r'\xaf', +'sub': '⊂', +'sub0': '₀', +'sub1': '₁', +'sub2': '₂', +'sub3': '₃', +'sub4': '₄', +'sub5': '₅', +'sub6': '₆', +'sub7': '₇', +'sub8': '₈', +'sub9': '₉', +'subE': '⫅', +'subdot': '⪽', +'sube': '⊆', +'subedot': '⫃', +'sublpar': '₍', +'subminus': '₋', +'submult': '⫁', +'subnE': '⫋', +'subne': '⊊', +'subplus': '⪿', +'subrarr': '⥹', +'subrpar': '₎', +'subset': '⊂', +'subseteq': '⊆', +'subseteqq': '⫅', +'subsetneq': '⊊', +'subsetneqq': '⫋', +'subsim': '⫇', +'subsub': '⫕', +'subsup': '⫓', +'succ': '≻', +'succapprox': '⪸', +'succcurlyeq': '≽', +'succeq': '⪰', +'succnapprox': '⪺', +'succneqq': '⪶', +'succnsim': '⋩', +'succsim': '≿', +'sum': '∑', +'sung': '♪', +'sup': '⊃', +'sup0': '⁰', +'sup1': r'\xb9', +'sup2': r'\xb2', +'sup3': r'\xb3', +'sup4': '⁴', +'sup5': '⁵', +'sup6': '⁶', +'sup7': '⁷', +'sup8': '⁸', +'sup9': '⁹', +'supE': '⫆', +'supdot': '⪾', +'supdsub': '⫘', +'supe': '⊇', +'supedot': '⫄', +'suphsol': '⟉', +'suphsub': '⫗', +'suplarr': '⥻', +'suplpar': '⁽', +'supminus': '⁻', +'supmult': '⫂', +'supnE': '⫌', +'supne': '⊋', +'supplus': '⫀', +'suprpar': '⁾', +'supset': '⊃', +'supseteq': '⊇', +'supseteqq': '⫆', +'supsetneq': '⊋', +'supsetneqq': '⫌', +'supsim': '⫈', +'supsub': '⫔', +'supsup': '⫖', +'swArr': '⇙', +'swarhk': '⤦', +'swarr': '↙', +'swarrow': '↙', +'swnwar': '⤪', +'szlig': r'\xdf', +'target': '⌖', +'tau': 'τ', +'tbrk': '⎴', +'tcaron': 'ť', +'tcedil': 'ţ', +'tcircti': 'ễ', +'tcommab': 'ț', +'tcy': 'т', +'tdot': '⃛', +'tdotb': 'ṭ', +'telrec': '⌕', +'tfr': '𝔱', +'tgr': 'τ', +'there4': '∴', +'therefore': '∴', +'theta': 'θ', +'thetasym': 'ϑ', +'thetav': 'ϑ', +'thgr': 'θ', +'thickapprox': '≈', +'thicksim': '∼', +'thinsp': ' ', +'thkap': '≈', +'thksim': '∼', +'thorn': r'\xfe', +'tilde': '˜', +'times': r'\xd7', +'timesb': '⊠', +'timesbar': '⨱', +'timesd': '⨰', +'tint': '∭', +'tmacrb': 'ṯ', +'toea': '⤨', +'top': '⊤', +'topbot': '⌶', +'topcir': '⫱', +'topf': '𝕥', +'topfork': '⫚', +'tosa': '⤩', +'tprime': '‴', +'trade': '™', +'triangle': '▵', +'triangledown': '▿', +'triangleleft': '◃', +'trianglelefteq': '⊴', +'triangleq': '≜', +'triangleright': '▹', +'trianglerighteq': '⊵', +'tridot': '◬', +'trie': '≜', +'triminus': '⨺', +'triplus': '⨹', +'trisb': '⧍', +'tritime': '⨻', +'trpezium': '⏢', +'tscr': '𝓉', +'tscy': 'ц', +'tshcy': 'ћ', +'tstrok': 'ŧ', +'tuml': 'ẗ', +'twixt': '≬', +'twoheadleftarrow': '↞', +'twoheadrightarrow': '↠', +'uArr': '⇑', +'uHar': '⥣', +'uacgr': 'ύ', +'uacute': r'\xfa', +'uarr': '↑', +'ubrcy': 'ў', +'ubreve': 'ŭ', +'ucaron': 'ǔ', +'ucirc': r'\xfb', +'ucy': 'у', +'udarr': '⇅', +'udblac': 'ű', +'udbldb': 'ṳ', +'udhar': '⥮', +'udiagr': 'ΰ', +'udigr': 'ϋ', +'udotb': 'ụ', +'ufisht': '⥾', +'ufr': '𝔲', +'ugr': 'υ', +'ugrave': r'\xf9', +'uharl': '↿', +'uharr': '↾', +'uhblk': '▀', +'uhooka': 'ủ', +'uhorn': 'ư', +'uhornac': 'ứ', +'uhorndb': 'ự', +'uhorngr': 'ừ', +'uhornha': 'ử', +'uhornti': 'ữ', +'ulcorn': '⌜', +'ulcorner': '⌜', +'ulcrop': '⌏', +'ultri': '◸', +'umacr': 'ū', +'umacrum': 'ṻ', +'uml': r'\xa8', +'under': '̲', +'uogon': 'ų', +'uopf': '𝕦', +'uparrow': '↑', +'updownarrow': '↕', +'upharpoonleft': '↿', +'upharpoonright': '↾', +'uplus': '⊎', +'upsi': 'υ', +'upsih': 'ϒ', +'upsilon': 'υ', +'upuparrows': '⇈', +'urcorn': '⌝', +'urcorner': '⌝', +'urcrop': '⌎', +'uring': 'ů', +'urtri': '◹', +'uscr': '𝓊', +'utdot': '⋰', +'utilde': 'ũ', +'utildeac': 'ṹ', +'utri': '▵', +'utrif': '▴', +'uuarr': '⇈', +'uuml': r'\xfc', +'uwangle': '⦧', +'vArr': '⇕', +'vBar': '⫨', +'vBarv': '⫩', +'vDash': '⊨', +'vangrt': '⦜', +'varepsilon': 'ϵ', +'varkappa': 'ϰ', +'varnothing': '∅', +'varphi': 'ϕ', +'varpi': 'ϖ', +'varpropto': '∝', +'varr': '↕', +'varrho': 'ϱ', +'varsigma': 'ς', +'varsubsetneq': '⊊︀', +'varsubsetneqq': '⫋︀', +'varsupsetneq': '⊋︀', +'varsupsetneqq': '⫌︀', +'vartheta': 'ϑ', +'vartriangleleft': '⊲', +'vartriangleright': '⊳', +'vcy': 'в', +'vdash': '⊢', +'vdotb': 'ṿ', +'vee': '∨', +'veebar': '⊻', +'veeeq': '≚', +'vellip': '⋮', +'verbar': r'|', +'vert': r'|', +'vfr': '𝔳', +'vltri': '⊲', +'vnsub': '⊂⃒', +'vnsup': '⊃⃒', +'vopf': '𝕧', +'vprop': '∝', +'vrtri': '⊳', +'vscr': '𝓋', +'vsubnE': '⫋︀', +'vsubne': '⊊︀', +'vsupnE': '⫌︀', +'vsupne': '⊋︀', +'vtilde': 'ṽ', +'vzigzag': '⦚', +'wacute': 'ẃ', +'wcirc': 'ŵ', +'wdot': 'ẇ', +'wdotb': 'ẉ', +'wedbar': '⩟', +'wedge': '∧', +'wedgeq': '≙', +'weierp': '℘', +'wfr': '𝔴', +'wgrave': 'ẁ', +'wopf': '𝕨', +'wp': '℘', +'wr': '≀', +'wreath': '≀', +'wring': 'ẘ', +'wscr': '𝓌', +'wuml': 'ẅ', +'xcap': '⋂', +'xcirc': '◯', +'xcup': '⋃', +'xdot': 'ẋ', +'xdtri': '▽', +'xfr': '𝔵', +'xgr': 'ξ', +'xhArr': '⟺', +'xharr': '⟷', +'xi': 'ξ', +'xlArr': '⟸', +'xlarr': '⟵', +'xmap': '⟼', +'xnis': '⋻', +'xodot': '⨀', +'xopf': '𝕩', +'xoplus': '⨁', +'xotime': '⨂', +'xrArr': '⟹', +'xrarr': '⟶', +'xscr': '𝓍', +'xsqcup': '⨆', +'xuml': 'ẍ', +'xuplus': '⨄', +'xutri': '△', +'xvee': '⋁', +'xwedge': '⋀', +'yacute': r'\xfd', +'yacy': 'я', +'ycirc': 'ŷ', +'ycy': 'ы', +'ydot': 'ẏ', +'ydotb': 'ỵ', +'yen': r'\xa5', +'yfr': '𝔶', +'ygrave': 'ỳ', +'yhooka': 'ỷ', +'yicy': 'ї', +'ymacr': 'ȳ', +'yopf': '𝕪', +'yring': 'ẙ', +'yscr': '𝓎', +'ytilde': 'ỹ', +'yucy': 'ю', +'yuml': r'\xff', +'zacute': 'ź', +'zcaron': 'ž', +'zcirc': 'ẑ', +'zcy': 'з', +'zdot': 'ż', +'zdotb': 'ẓ', +'zeetrf': 'ℨ', +'zeta': 'ζ', +'zfr': '𝔷', +'zgr': 'ζ', +'zhcy': 'ж', +'zigrarr': '⇝', +'zlowline': 'ẕ', +'zopf': '𝕫', +'zscr': '𝓏', +'zwj': '‍', +'zwnj': '‌', +} diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/inoutparsing.py b/interactive-mining-3rdparty-madis/madis/src/lib/inoutparsing.py new file mode 100644 index 0000000..15a37ed --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/inoutparsing.py @@ -0,0 +1,121 @@ +import urllib2 +import tempfile +import csv +import re +import os +from lib.boolops import xor + +# Set maximum field size to 20MB +csv.field_size_limit(20000000) + +class defaultcsv(csv.Dialect): + def __init__(self): + self.delimiter=',' + self.doublequote=True + self.quotechar='"' + self.quoting=csv.QUOTE_MINIMAL + self.lineterminator='\n' + +class tsv(csv.Dialect): + def __init__(self): + self.delimiter='\t' + self.doublequote=True + self.quotechar='"' + self.quoting=csv.QUOTE_MINIMAL + self.lineterminator='\n' + + +class line(csv.Dialect): + def __init__(self): + self.delimiter='\n' + self.doublequote=False + self.quotechar='"' + self.quoting=csv.QUOTE_NONE + self.lineterminator='\n' + +urllike=re.compile('^((?:http(?:s)?|ftp)://)(?:(?:[A-Z0-9]+(?:-*[A-Z0-9]+)*\.)+[A-Z]{2,6}|localhost|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?::\d+)?(?:/?|/\S+)$', re.IGNORECASE) +urlstart=re.compile('^(http(?:s)?|ftp)', re.IGNORECASE) + +boolargs = ['skipinitialspace', 'doublequote'] +nonstringargs = {'quoting':{'QUOTE_ALL':csv.QUOTE_ALL, 'QUOTE_NONE':csv.QUOTE_NONE, 'QUOTE_MINIMAL':csv.QUOTE_MINIMAL, 'QUOTE_NONNUMERIC':csv.QUOTE_NONNUMERIC}, 'dialect':{'line':line(),'tsv':tsv(),'csv':defaultcsv(), 'json':'json'}} +needsescape=['delimiter','quotechar','lineterminator'] + +class InputsError(Exception): + pass + + +def inoutargsparse(args,kargs): + returnvals= {'url':False,'header':False , 'compression':False, 'compressiontype':None, 'filename':None} + where=None #This gets registered with the Connection + if not xor((len(args)>0),('file' in kargs),('url' in kargs),('http' in kargs),('ftp' in kargs),('https' in kargs)): + raise InputsError() + if 'http' in kargs: + kargs['url']='http:'+kargs['http'] + del kargs['http'] + elif 'ftp' in kargs: + kargs['url']='ftp:'+kargs['ftp'] + del kargs['ftp'] + elif 'https' in kargs: + kargs['url']='https:'+kargs['https'] + del kargs['https'] + returnvals['url']=False + if len(args)>0: + where=args[0] + elif 'file' in kargs: + where=kargs['file'] + del kargs['file'] + else: #url + returnvals['url']=True + where=kargs['url'] + v=urllike.match(where) + if v : + if not v.groups()[0] or v.groups()[0]=='': + where="http://"+where + del kargs['url'] + if 'header' in kargs: + returnvals['header']=kargs['header'] + del kargs['header'] + + ######################################################### + if where.endswith('.zip'): + returnvals['compression']=True + returnvals['compressiontype']='zip' + + if where.endswith('.gz') or where.endswith('.gzip'): + returnvals['compression']=True + returnvals['compressiontype']='gz' + + ######################################################### + if 'compression' in kargs : + returnvals['compression']=kargs['compression'] + del kargs['compression'] + elif 'compressiontype' in kargs: + returnvals['compression']=True + + if 'compressiontype' not in kargs: + returnvals['compressiontype']='zip' + if where.endswith('.gz') or where.endswith('.gzip'): + returnvals['compressiontype']='gz' + else: + returnvals['compressiontype']=kargs['compressiontype'] + del kargs['compressiontype'] + + returnvals['filename']=where + return returnvals + + + + + +def cacheurl(url,extraheaders): + fd , fname =tempfile.mkstemp(suffix="kill.urlfetch") + os.close(fd) + req=urllib2.Request(url,None,extraheaders) + #urliter=urllib2.urlopen(url) + urliter=urllib2.urlopen(req) + tmp=open(fname,"wb") + for line in urliter: + tmp.write(line) + tmp.close() + urliter.close() + return fname diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/ipaddr.py b/interactive-mining-3rdparty-madis/madis/src/lib/ipaddr.py new file mode 100644 index 0000000..8ed4bd1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/ipaddr.py @@ -0,0 +1,1820 @@ +#!/usr/bin/python +# +# Copyright 2007 Google Inc. +# Licensed to PSF under a Contributor Agreement. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. + +"""A fast, lightweight IPv4/IPv6 manipulation library in Python. + +This library is used to create/poke/manipulate IPv4 and IPv6 addresses +and networks. + +""" + +__version__ = '2.0.0' + +import struct + +class Error(Exception): + + """Base class for exceptions.""" + + +class IPTypeError(Error): + + """Tried to perform a v4 action on v6 object or vice versa.""" + + +class IPAddressExclusionError(Error): + + """An Error we should never see occurred in address exclusion.""" + + +class IPAddressIPValidationError(Error): + + """Raised when a single address (v4 or v6) was given a network.""" + + def __init__(self, ip): + Error.__init__(self) + self._ip = ip + + def __str__(self): + return "%s is not a valid address (hint, it's probably a network)" % ( + repr(self._ip)) + +class IPv4IpValidationError(Error): + + """Raised when an IPv4 address is invalid.""" + + def __init__(self, ip): + Error.__init__(self) + self._ip = ip + + def __str__(self): + return repr(self._ip) + ' is not a valid IPv4 address' + +class IPv4NetmaskValidationError(Error): + + """Raised when a netmask is invalid.""" + + def __init__(self, netmask): + Error.__init__(self) + self.netmask = netmask + + def __str__(self): + return repr(self.netmask) + ' is not a valid IPv4 netmask' + + +class IPv6IpValidationError(Error): + + """Raised when an IPv6 address is invalid.""" + + def __init__(self, ip): + Error.__init__(self) + self._ip = ip + + def __str__(self): + return repr(self._ip) + ' is not a valid IPv6 network' + + +class IPv6NetmaskValidationError(Error): + + """Raised when an IPv6 netmask is invalid.""" + + def __init__(self, netmask): + Error.__init__(self) + self.netmask = netmask + + def __str__(self): + return repr(self.netmask) + ' is not a valid IPv6 netmask' + + +class PrefixlenDiffInvalidError(Error): + + """Raised when Sub/Supernets is called with a bad prefixlen_diff.""" + + def __init__(self, error_str): + Error.__init__(self) + self.error_str = error_str + + +def IPAddress(address, version=None): + """Take an IP string/int and return an object of the correct type. + + Args: + address: A string or integer, the IP address. Either IPv4 or + IPv6 addresses may be supplied; integers less than 2**32 will + be considered to be IPv4 by default. + version: An Integer, 4 or 6. If set, don't try to automatically + determine what the IP address type is. important for things + like IPAddress(1), which could be IPv4, '0.0.0.0.1', or IPv6, + '::1'. + + Returns: + An IPv4Address or IPv6Address object. + + Raises: + ValueError: if the string passed isn't either a v4 or a v6 + address. + + """ + if version: + if version == 4: + return IPv4Address(address) + elif version == 6: + return IPv6Address(address) + + try: + return IPv4Address(address) + except (IPv4IpValidationError, IPv6NetmaskValidationError): + pass + + try: + return IPv6Address(address) + except (IPv6ValidationError, IPv6NetmaskValidationError): + pass + + raise ValueError('%r does not appear to be an IPv4 or IPv6 address' % + address) + + +def IPNetwork(address, version=None): + """Take an IP string/int and return an object of the correct type. + + Args: + address: A string or integer, the IP address. Either IPv4 or + IPv6 addresses may be supplied; integers less than 2**32 will + be considered to be IPv4 by default. + version: An Integer, if set, don't try to automatically + determine what the IP address type is. important for things + like IPNetwork(1), which could be IPv4, '0.0.0.1/32', or IPv6, + '::1/128'. + + Returns: + An IPv4Network or IPv6Network object. + + Raises: + ValueError: if the string passed isn't either a v4 or a v6 + address. + + """ + if version: + if version == 4: + return IPv4Network(address) + elif version == 6: + return IPv6Network(address) + + try: + return IPv4Network(address) + except (IPv4IpValidationError, IPv4NetmaskValidationError): + pass + + try: + return IPv6Network(address) + except (IPv6IpValidationError, IPv6NetmaskValidationError): + pass + + raise ValueError('%r does not appear to be an IPv4 or IPv6 network' % + address) + + +def _find_address_range(addresses): + """Find a sequence of addresses. + + Args: + addresses: a list of IPv4 or IPv6 addresses. + + Returns: + A tuple containing the first and last IP addresses in the sequence. + + """ + first = last = addresses[0] + for ip in addresses[1:]: + if ip._ip == last._ip + 1: + last = ip + else: + break + return (first, last) + +def _get_prefix_length(number1, number2, bits): + """Get the number of leading bits that are same for two numbers. + + Args: + number1: an integer. + number2: another integer. + bits: the maximum number of bits to compare. + + Returns: + The number of leading bits that are the same for two numbers. + + """ + for i in range(bits): + if number1 >> i == number2 >> i: + return bits - i + return 0 + +def _count_righthand_zero_bits(number, bits): + """Count the number of zero bits on the right hand side. + + Args: + number: an integer. + bits: maximum number of bits to count. + + Returns: + The number of zero bits on the right hand side of the number. + + """ + if number == 0: + return bits + for i in range(bits): + if (number >> i) % 2: + return i + +def summarize_address_range(first, last): + """Summarize a network range given the first and last IP addresses. + + Example: + >>> summarize_address_range(IPv4Address('1.1.1.0'), + IPv4Address('1.1.1.130')) + [IPv4Network('1.1.1.0/25'), IPv4Network('1.1.1.128/31'), + IPv4Network('1.1.1.130/32')] + + Args: + first: the first IPv4Address or IPv6Address in the range. + last: the last IPv4Address or IPv6Address in the range. + + Returns: + The address range collapsed to a list of IPv4Network's or + IPv6Network's. + + Raise: + IPTypeError: + If the first and last objects are not IP addresses. + If the first and last objects are not the same version. + ValueError: + If the last object is not greater than the first. + If the version is not 4 or 6. + + """ + if not (isinstance(first, BaseIP) and isinstance(last, BaseIP)): + raise IPTypeError('first and last must be IP addresses, not networks') + if first.version != last.version: + raise IPTypeError('IP addresses must be same version') + if first > last: + raise ValueError('last IP address must be greater than first') + + networks = [] + + if first.version == 4: + ip = IPv4Network + elif first.version == 6: + ip = IPv6Network + else: + raise ValueError('unknown IP version') + + ip_bits = first._max_prefixlen + first_int = first._ip + last_int = last._ip + while first_int <= last_int: + nbits = _count_righthand_zero_bits(first_int, ip_bits) + current = None + while nbits >= 0: + addend = 2**nbits - 1 + current = first_int + addend + nbits -= 1 + if current <= last_int: + break + prefix = _get_prefix_length(first_int, current, ip_bits) + net = ip('%s/%d' % (str(first), prefix)) + networks.append(net) + if current == ip._ALL_ONES: + break + first_int = current + 1 + first = IPAddress(first_int, version=first._version) + return networks + +def _collapse_address_list_recursive(addresses): + """Loops through the addresses, collapsing concurrent netblocks. + + Example: + + ip1 = IPv4Network'1.1.0.0/24') + ip2 = IPv4Network'1.1.1.0/24') + ip3 = IPv4Network'1.1.2.0/24') + ip4 = IPv4Network'1.1.3.0/24') + ip5 = IPv4Network'1.1.4.0/24') + ip6 = IPv4Network'1.1.0.1/22') + + _collapse_address_list_recursive([ip1, ip2, ip3, ip4, ip5, ip6]) -> + [IPv4Network('1.1.0.0/22'), IPv4Network('1.1.4.0/24')] + + This shouldn't be called directly; it is called via + collapse_address_list([]). + + Args: + addresses: A list of IPv4Network's or IPv6Network's + + Returns: + A list of IPv4Network's or IPv6Network's depending on what we were + passed. + + """ + ret_array = [] + optimized = False + + for cur_addr in addresses: + if not ret_array: + ret_array.append(cur_addr) + continue + if cur_addr in ret_array[-1]: + optimized = True + elif cur_addr == ret_array[-1].supernet().subnet()[1]: + ret_array.append(ret_array.pop().supernet()) + optimized = True + else: + ret_array.append(cur_addr) + + if optimized: + return _collapse_address_list_recursive(ret_array) + + return ret_array + + +def collapse_address_list(addresses): + """Collapse a list of IP objects. + + Example: + collapse_address_list([IPv4('1.1.0.0/24'), IPv4('1.1.1.0/24')]) -> + [IPv4('1.1.0.0/23')] + + Args: + addresses: A list of IPv4Network or IPv6Network objects. + + Returns: + A list of IPv4Network or IPv6Network objects depending on what we + were passed. + + Raises: + IPTypeError: If passed a list of mixed version objects. + + """ + i = 0 + addrs = [] + ips = [] + nets = [] + + # split IP addresses and networks + for ip in addresses: + if isinstance(ip, BaseIP): + if ips and ips[-1]._version != ip._version: + raise IPTypeError('Can only collapse like-versioned objects -' + ' v%d: %s, v%d %s' % (ips[-1]._version, + str(ips[-1]), + ip._version, str(ip))) + ips.append(ip) + elif ip._prefixlen == ip._max_prefixlen: + if ips and ips[-1]._version != ip._version: + raise IPTypeError('Can only collapse like-versioned objects -' + ' v%d: %s, v%d %s' % (ips[-1]._version, + str(ips[-1]), + ip._version, str(ip))) + ips.append(ip.ip) + else: + if nets and nets[-1]._version != ip._version: + raise IPTypeError('Can only collapse like-versioned objects -' + ' v%d: %s, v%d %s' % (ips[-1]._version, + str(ips[-1]), + ip._version, str(ip))) + nets.append(ip) + + # sort and dedup + ips = sorted(set(ips)) + nets = sorted(set(nets)) + + while i < len(ips): + (first, last) = _find_address_range(ips[i:]) + i = ips.index(last) + 1 + addrs.extend(summarize_address_range(first, last)) + + return _collapse_address_list_recursive(sorted( + addrs + nets, key=BaseNet._get_networks_key)) + +# backwards compatibility +CollapseAddrList = collapse_address_list + +# Test whether this Python implementation supports byte objects that +# are not identical to str ones. +# We need to exclude platforms where bytes == str so that we can +# distinguish between packed representations and strings, for example +# b'12::' (the IPv4 address 49.50.58.58) and '12::' (an IPv6 address). +try: + _compat_has_real_bytes = bytes is not str +except NameError: # other._version + if self._ip != other._ip: + return self._ip > other._ip + return False + + def __repr__(self): + return '%s(%r)' % (self.__class__.__name__, str(self)) + + def __str__(self): + return '%s' % self._string_from_ip_int(self._ip) + + def __hash__(self): + return hash(self._ip) + + @property + def version(self): + raise NotImplementedError('BaseIP has no version') + + +class BaseNet(IPAddrBase): + + """A generic IP object. + + This IP class contains the version independent methods which are + used by networks. + + """ + + def __init__(self, address): + self._cache = {} + + def __repr__(self): + return '%s(%r)' % (self.__class__.__name__, str(self)) + + def iterhosts(self): + """Generate Iterator over usable hosts in a network. + + This is like __iter__ except it doesn't return the network + or broadcast addresses. + + """ + cur = int(self.network) + 1 + bcast = int(self.broadcast) - 1 + while cur <= bcast: + cur += 1 + yield IPAddress(cur - 1, version=self._version) + + def __iter__(self): + cur = int(self.network) + bcast = int(self.broadcast) + while cur <= bcast: + cur += 1 + yield IPAddress(cur - 1, version=self._version) + + def __getitem__(self, n): + network = int(self.network) + broadcast = int(self.broadcast) + if n >= 0: + if network + n > broadcast: + raise IndexError + return IPAddress(network + n, version=self._version) + else: + n += 1 + if broadcast + n < network: + raise IndexError + return IPAddress(broadcast + n, version=self._version) + + def __lt__(self, other): + try: + if self._version != other._version: + return self._version < other._version + if self._ip != other._ip: + return self._ip < other._ip + if self.netmask != other.netmask: + return self.netmask < other.netmask + return False + except AttributeError: + return NotImplemented + + def __gt__(self, other): + try: + if self._version != other._version: + return self._version > other._version + if self._ip != other._ip: + return self._ip > other._ip + if self.netmask != other.netmask: + return self.netmask > other.netmask + return False + except AttributeError: + return NotImplemented + + def __le__(self, other): + gt = self.__gt__(other) + if gt is NotImplemented: + return NotImplemented + return not gt + + def __ge__(self, other): + lt = self.__lt__(other) + if lt is NotImplemented: + return NotImplemented + return not lt + + def __eq__(self, other): + try: + return (self._version == other._version + and self._ip == other._ip + and int(self.netmask) == int(other.netmask)) + except AttributeError: + return NotImplemented + + def __ne__(self, other): + eq = self.__eq__(other) + if eq is NotImplemented: + return NotImplemented + return not eq + + def __str__(self): + return '%s/%s' % (str(self.ip), + str(self._prefixlen)) + + def __hash__(self): + return hash(self._ip ^ int(self.netmask)) + + def __contains__(self, other): + # Easy case, dealing with networks. + if isinstance(other, BaseNet): + return (int(self.network) <= int(other._ip) and + int(self.broadcast) >= int(other.broadcast)) + elif isinstance(other, BaseIP): + # Check if we've got an Address + return (int(self.network) <= int(other._ip) <= + int(self.broadcast)) + else: + return IPNetwork(other) in self + + @property + def network(self): + x = self._cache.get('network') + if x is None: + x = IPAddress(self._ip & int(self.netmask), version=self._version) + self._cache['network'] = x + return x + + @property + def broadcast(self): + x = self._cache.get('broadcast') + if x is None: + x = IPAddress(self._ip | int(self.hostmask), version=self._version) + self._cache['broadcast'] = x + return x + + @property + def hostmask(self): + x = self._cache.get('hostmask') + if x is None: + x = IPAddress(int(self.netmask) ^ self._ALL_ONES, + version=self._version) + self._cache['hostmask'] = x + return x + + @property + def with_prefixlen(self): + return '%s/%d' % (str(self.ip), self._prefixlen) + + @property + def with_netmask(self): + return '%s/%s' % (str(self.ip), str(self.netmask)) + + @property + def with_hostmask(self): + return '%s/%s' % (str(self.ip), str(self.hostmask)) + + @property + def numhosts(self): + """Number of hosts in the current subnet.""" + return int(self.broadcast) - int(self.network) + 1 + + @property + def version(self): + raise NotImplementedError('BaseNet has no version') + + @property + def prefixlen(self): + return self._prefixlen + + def address_exclude(self, other): + """Remove an address from a larger block. + + For example: + + addr1 = IP('10.1.1.0/24') + addr2 = IP('10.1.1.0/26') + addr1.address_exclude(addr2) = + [IP('10.1.1.64/26'), IP('10.1.1.128/25')] + + or IPv6: + + addr1 = IP('::1/32') + addr2 = IP('::1/128') + addr1.address_exclude(addr2) = [IP('::0/128'), + IP('::2/127'), + IP('::4/126'), + IP('::8/125'), + ... + IP('0:0:8000::/33')] + + Args: + other: An IP object of the same type. + + Returns: + A sorted list of IP objects addresses which is self minus + other. + + Raises: + IPTypeError: If self and other are of difffering address + versions. + IPAddressExclusionError: There was some unknown error in the + address exclusion process. This likely points to a bug + elsewhere in this code. + ValueError: If other is not completely contained by self. + + """ + if not self._version == other._version: + raise IPTypeError("%s and %s aren't of the same version" % ( + str(self), str(other))) + + if other not in self: + raise ValueError('%s not contained in %s' % (str(other), + str(self))) + ret_addrs = [] + + # Make sure we're comparing the network of other. + other = IPNetwork('%s/%s' % (str(other.network), str(other.prefixlen)), + version=other._version) + + s1, s2 = self.subnet() + while s1 != other and s2 != other: + if other in s1: + ret_addrs.append(s2) + s1, s2 = s1.subnet() + elif other in s2: + ret_addrs.append(s1) + s1, s2 = s2.subnet() + else: + # If we got here, there's a bug somewhere. + raise IPAddressExclusionError('Error performing exclusion: ' + 's1: %s s2: %s other: %s' % + (str(s1), str(s2), str(other))) + if s1 == other: + ret_addrs.append(s2) + elif s2 == other: + ret_addrs.append(s1) + else: + # If we got here, there's a bug somewhere. + raise IPAddressExclusionError('Error performing exclusion: ' + 's1: %s s2: %s other: %s' % + (str(s1), str(s2), str(other))) + + return sorted(ret_addrs, key=BaseNet._get_networks_key) + + def compare_networks(self, other): + """Compare two IP objects. + + This is only concerned about the comparison of the integer + representation of the network addresses. This means that the + host bits aren't considered at all in this method. If you want + to compare host bits, you can easily enough do a + 'HostA._ip < HostB._ip' + + Args: + other: An IP object. + + Returns: + If the IP versions of self and other are the same, returns: + + -1 if self < other: + eg: IPv4('1.1.1.0/24') < IPv4('1.1.2.0/24') + IPv6('1080::200C:417A') < IPv6('1080::200B:417B') + 0 if self == other + eg: IPv4('1.1.1.1/24') == IPv4('1.1.1.2/24') + IPv6('1080::200C:417A/96') == IPv6('1080::200C:417B/96') + 1 if self > other + eg: IPv4('1.1.1.0/24') > IPv4('1.1.0.0/24') + IPv6('1080::1:200C:417A/112') > + IPv6('1080::0:200C:417A/112') + + If the IP versions of self and other are different, returns: + + -1 if self._version < other._version + eg: IPv4('10.0.0.1/24') < IPv6('::1/128') + 1 if self._version > other._version + eg: IPv6('::1/128') > IPv4('255.255.255.0/24') + + """ + if self._version < other._version: + return -1 + if self._version > other._version: + return 1 + # self._version == other._version below here: + if self.network < other.network: + return -1 + if self.network > other.network: + return 1 + # self.network == other.network below here: + if self.netmask < other.netmask: + return -1 + if self.netmask > other.netmask: + return 1 + # self.network == other.network and self.netmask == other.netmask + return 0 + + def _get_networks_key(self): + """Network-only key function. + + Returns an object that identifies this address' network and + netmask. This function is a suitable "key" argument for sorted() + and list.sort(). + + """ + return (self._version, self.network, self.netmask) + + def _ip_int_from_prefix(self, prefixlen=None): + """Turn the prefix length netmask into a int for comparison. + + Args: + prefixlen: An integer, the prefix length. + + Returns: + An integer. + + """ + if not prefixlen and prefixlen != 0: + prefixlen = self._prefixlen + return self._ALL_ONES ^ (self._ALL_ONES >> prefixlen) + + def _prefix_from_ip_int(self, ip_int, mask=32): + """Return prefix length from the decimal netmask. + + Args: + ip_int: An integer, the IP address. + mask: The netmask. Defaults to 32. + + Returns: + An integer, the prefix length. + + """ + while mask: + if ip_int & 1 == 1: + break + ip_int >>= 1 + mask -= 1 + + return mask + + def _ip_string_from_prefix(self, prefixlen=None): + """Turn a prefix length into a dotted decimal string. + + Args: + prefixlen: An integer, the netmask prefix length. + + Returns: + A string, the dotted decimal netmask string. + + """ + if not prefixlen: + prefixlen = self._prefixlen + return self._string_from_ip_int(self._ip_int_from_prefix(prefixlen)) + + def subnet(self, prefixlen_diff=1, new_prefix=None): + """The subnets which join to make the current subnet. + + In the case that self contains only one IP + (self._prefixlen == 32), return a list with just ourself. + + Args: + prefixlen_diff: An integer, the amount the prefix length + should be increased by. This should not be set if + new_prefix is also set. + new_prefix: The desired new prefix length. This must be a + larger number (smaller prefix) than the existing prefix. + This should not be set if prefixlen_diff is also set. + + Returns: + A list of IPv6 objects. + + Raises: + PrefixlenDiffInvalidError: The prefixlen_diff is too small + or too large. + ValueError: prefixlen_diff and new_prefix are both set or + new_prefix is a smaller number than the current prefix + (smaller number means a larger network) + + """ + if self._prefixlen == self._max_prefixlen: + return [self] + + if new_prefix is not None: + if new_prefix < self._prefixlen: + raise ValueError('new prefix must be longer') + if prefixlen_diff != 1: + raise ValueError('cannot set prefixlen_diff and new_prefix') + prefixlen_diff = new_prefix - self._prefixlen + + if prefixlen_diff < 0: + raise PrefixlenDiffInvalidError('prefix length diff must be > 0') + new_prefixlen = self._prefixlen + prefixlen_diff + + if not self._is_valid_netmask(str(new_prefixlen)): + raise PrefixlenDiffInvalidError( + 'prefix length diff %d is invalid for netblock %s' % ( + new_prefixlen, str(self))) + + first = IPNetwork('%s/%s' % (str(self.network), + str(self._prefixlen + prefixlen_diff)), + version=self._version) + subnets = [first] + current = first + while True: + broadcast = current.broadcast + if broadcast == self.broadcast: + break + new_addr = IPAddress(int(broadcast) + 1, version=self._version) + current = IPNetwork('%s/%s' % (str(new_addr), str(new_prefixlen)), + version=self._version) + subnets.append(current) + + return subnets + + def supernet(self, prefixlen_diff=1, new_prefix=None): + """The supernet containing the current network. + + Args: + prefixlen_diff: An integer, the amount the prefix length of + the network should be decreased by. For example, given a + /24 network and a prefixlen_diff of 3, a supernet with a + /21 netmask is returned. + + Returns: + An IPv4 network object. + + Raises: + PrefixlenDiffInvalidError: If + self.prefixlen - prefixlen_diff < 0. I.e., you have a + negative prefix length. + ValueError: prefixlen_diff and new_prefix are both set or + new_prefix is a larger number than the current prefix + (larger number means a smaller network) + + """ + if self._prefixlen == 0: + return self + + if new_prefix is not None: + if new_prefix > self._prefixlen: + raise ValueError('new prefix must be shorter') + if prefixlen_diff != 1: + raise ValueError('cannot set prefixlen_diff and new_prefix') + prefixlen_diff = self._prefixlen - new_prefix + + + if self.prefixlen - prefixlen_diff < 0: + raise PrefixlenDiffInvalidError( + 'current prefixlen is %d, cannot have a prefixlen_diff of %d' % + (self.prefixlen, prefixlen_diff)) + return IPNetwork('%s/%s' % (str(self.network), + str(self.prefixlen - prefixlen_diff)), + version=self._version) + + # backwards compatibility + Subnet = subnet + Supernet = supernet + AddressExclude = address_exclude + CompareNetworks = compare_networks + Contains = __contains__ + + +class BaseV4(object): + + """Base IPv4 object. + + The following methods are used by IPv4 objects in both single IP + addresses and networks. + + """ + + # Equivalent to 255.255.255.255 or 32 bits of 1's. + _ALL_ONES = (2**32) - 1 + + def __init__(self, address): + self._version = 4 + self._max_prefixlen = 32 + + def _explode_shorthand_ip_string(self, ip_str=None): + if not ip_str: + ip_str = str(self) + return ip_str + + def _ip_int_from_string(self, ip_str): + """Turn the given IP string into an integer for comparison. + + Args: + ip_str: A string, the IP ip_str. + + Returns: + The IP ip_str as an integer. + + """ + packed_ip = 0 + for oc in ip_str.split('.'): + packed_ip = (packed_ip << 8) | int(oc) + return packed_ip + + def _string_from_ip_int(self, ip_int): + """Turns a 32-bit integer into dotted decimal notation. + + Args: + ip_int: An integer, the IP address. + + Returns: + The IP address as a string in dotted decimal notation. + + """ + octets = [] + for _ in xrange(4): + octets.insert(0, str(ip_int & 0xFF)) + ip_int >>= 8 + return '.'.join(octets) + + def _is_valid_ip(self, ip_str): + """Validate the dotted decimal notation IP/netmask string. + + Args: + ip_str: A string, the IP ip_str. + + Returns: + A boolean, True if the string is a valid dotted decimal IP + string. + + """ + octets = ip_str.split('.') + if len(octets) == 1: + # We have an integer rather than a dotted decimal IP. + try: + return int(ip_str) >= 0 and int(ip_str) <= self._ALL_ONES + except ValueError: + return False + + if len(octets) != 4: + return False + + for octet in octets: + try: + if not 0 <= int(octet) <= 255: + return False + except ValueError: + return False + return True + + @property + def max_prefixlen(self): + return self._max_prefixlen + + @property + def packed(self): + """The binary representation of this address.""" + return struct.pack('!I', self._ip) + + @property + def version(self): + return self._version + + @property + def is_reserved(self): + """Test if the address is otherwise IETF reserved. + + Returns: + A boolean, True if the address is within the + reserved IPv4 Network range. + + """ + return self in IPv4Network('240.0.0.0/4') + + @property + def is_private(self): + """Test if this address is allocated for private networks. + + Returns: + A boolean, True if the address is reserved per RFC 1918. + + """ + return (self in IPv4Network('10.0.0.0/8') or + self in IPv4Network('172.16.0.0/12') or + self in IPv4Network('192.168.0.0/16')) + + @property + def is_multicast(self): + """Test if the address is reserved for multicast use. + + Returns: + A boolean, True if the address is multicast. + See RFC 3171 for details. + + """ + return self in IPv4Network('224.0.0.0/4') + + @property + def is_loopback(self): + """Test if the address is a loopback adddress. + + Returns: + A boolean, True if the address is a loopback per RFC 3330. + + """ + return self in IPv4Network('127.0.0.0/8') + + @property + def is_link_local(self): + """Test if the address is reserved for link-local. + + Returns: + A boolean, True if the address is link-local per RFC 3927. + + """ + return self in IPv4Network('169.254.0.0/16') + + +class IPv4Address(BaseV4, BaseIP): + + """Represent and manipulate single IPv4 Addresses.""" + + def __init__(self, address): + + """ + Args: + address: A string or integer representing the IP + '192.168.1.1' + + Additionally, an integer can be passed, so + IPv4Address('192.168.1.1') == IPv4Address(3232235777). + or, more generally + IPv4Address(int(IPv4Address('192.168.1.1'))) == + IPv4Address('192.168.1.1') + + Raises: + IPv4IpValidationError: If ipaddr isn't a valid IPv4 address. + IPv4NetmaskValidationError: If the netmask isn't valid for + an IPv4 address. + + """ + BaseIP.__init__(self, address) + BaseV4.__init__(self, address) + + # Efficient constructor from integer. + if isinstance(address, (int, long)): + self._ip = address + if address < 0 or address > self._ALL_ONES: + raise IPv4IpValidationError(address) + return + + # Constructing from a packed address + if _compat_has_real_bytes: + if isinstance(address, bytes) and len(address) == 4: + self._ip = struct.unpack('!I', address)[0] + return + + # Assume input argument to be string or any object representation + # which converts into a formatted IP string. + addr_str = str(address) + if not self._is_valid_ip(addr_str): + raise IPv4IpValidationError(addr_str) + + self._ip = self._ip_int_from_string(addr_str) + + +class IPv4Network(BaseV4, BaseNet): + + """This class represents and manipulates 32-bit IPv4 networks. + + Attributes: [examples for IPv4Network('1.2.3.4/27')] + ._ip: 16909060 + .ip: IPv4Address('1.2.3.4') + .network: IPv4Address('1.2.3.0') + .hostmask: IPv4Address('0.0.0.31') + .broadcast: IPv4Address('1.2.3.31') + .netmask: IPv4Address('255.255.255.224') + .prefixlen: 27 + + """ + + def __init__(self, address): + """Instantiate a new IPv4 network object. + + Args: + address: A string or integer representing the IP [& network]. + '192.168.1.1/32' + '192.168.1.1/255.255.255.255' + '192.168.1.1/0.0.0.255' + '192.168.1.1' + are all functionally the same in IPv4. That is to say, + failing to provide a subnetmask will create an object with + a mask of /32. A netmask of '255.255.255.255' is assumed + to be /32 and '0.0.0.0' is assumed to be /0, even though + other netmasks can be expressed both as host- and + net-masks. (255.0.0.0 == 0.255.255.255) + + Additionally, an integer can be passed, so + IPv4Network('192.168.1.1') == IPv4Network(3232235777). + or, more generally + IPv4Network(int(IPv4Network('192.168.1.1'))) == + IPv4Network('192.168.1.1') + + Raises: + IPv4IpValidationError: If ipaddr isn't a valid IPv4 address. + IPv4NetmaskValidationError: If the netmask isn't valid for + an IPv4 address. + + """ + BaseNet.__init__(self, address) + BaseV4.__init__(self, address) + + # Efficient constructor from integer. + if isinstance(address, (int, long)): + self._ip = address + self.ip = IPv4Address(self._ip) + self._prefixlen = 32 + self.netmask = IPv4Address(self._ALL_ONES) + if address < 0 or address > self._ALL_ONES: + raise IPv4IpValidationError(address) + return + + # Constructing from a packed address + if _compat_has_real_bytes: + if isinstance(address, bytes) and len(address) == 4: + self._ip = struct.unpack('!I', address)[0] + self.ip = IPv4Address(self._ip) + self._prefixlen = 32 + self.netmask = IPv4Address(self._ALL_ONES) + return + + # Assume input argument to be string or any object representation + # which converts into a formatted IP prefix string. + addr = str(address).split('/') + + if len(addr) > 2: + raise IPv4IpValidationError(address) + + if not self._is_valid_ip(addr[0]): + raise IPv4IpValidationError(addr[0]) + + self._ip = self._ip_int_from_string(addr[0]) + self.ip = IPv4Address(self._ip) + + if len(addr) == 2: + mask = addr[1].split('.') + if len(mask) == 4: + # We have dotted decimal netmask. + if not self._is_valid_netmask(addr[1]): + raise IPv4NetmaskValidationError(addr[1]) + if self._is_hostmask(addr[1]): + self.netmask = IPv4Address( + self._ip_int_from_string(addr[1]) ^ self._ALL_ONES) + else: + self.netmask = IPv4Address(self._ip_int_from_string( + addr[1])) + + self._prefixlen = self._prefix_from_ip_int(int(self.netmask)) + else: + # We have a netmask in prefix length form. + if not self._is_valid_netmask(addr[1]): + raise IPv4NetmaskValidationError(addr[1]) + self._prefixlen = int(addr[1]) + self.netmask = IPv4Address(self._ip_int_from_prefix( + self._prefixlen)) + else: + self._prefixlen = 32 + self.netmask = IPv4Address(self._ip_int_from_prefix( + self._prefixlen)) + + def _is_hostmask(self, ip_str): + """Test if the IP string is a hostmask (rather than a netmask). + + Args: + ip_str: A string, the potential hostmask. + + Returns: + A boolean, True if the IP string is a hostmask. + + """ + parts = [int(x) for x in ip_str.split('.')] + if parts[0] < parts[-1]: + return True + return False + + def _is_valid_netmask(self, netmask): + """Verify that the netmask is valid. + + Args: + netmask: A string, either a prefix or dotted decimal + netmask. + + Returns: + A boolean, True if the prefix represents a valid IPv4 + netmask. + + """ + if len(netmask.split('.')) == 4: + return self._is_valid_ip(netmask) + try: + netmask = int(netmask) + except ValueError: + return False + return 0 <= netmask <= 32 + + # backwards compatibility + IsRFC1918 = lambda self: self.is_private + IsMulticast = lambda self: self.is_multicast + IsLoopback = lambda self: self.is_loopback + IsLinkLocal = lambda self: self.is_link_local + + +class BaseV6(object): + + """Base IPv6 object. + + The following methods are used by IPv6 objects in both single IP + addresses and networks. + + """ + + _ALL_ONES = (2**128) - 1 + + def __init__(self, address): + self._version = 6 + self._max_prefixlen = 128 + + def _ip_int_from_string(self, ip_str=None): + """Turn an IPv6 ip_str into an integer. + + Args: + ip_str: A string, the IPv6 ip_str. + + Returns: + A long, the IPv6 ip_str. + + """ + if not ip_str: + ip_str = str(self.ip) + + ip_int = 0 + + fields = self._explode_shorthand_ip_string(ip_str).split(':') + + # Do we have an IPv4 mapped (::ffff:a.b.c.d) or compact (::a.b.c.d) + # ip_str? + if fields[-1].count('.') == 3: + ipv4_string = fields.pop() + ipv4_int = IPv4Network(ipv4_string)._ip + octets = [] + for _ in xrange(2): + octets.append(hex(ipv4_int & 0xFFFF).lstrip('0x').rstrip('L')) + ipv4_int >>= 16 + fields.extend(reversed(octets)) + + for field in fields: + ip_int = (ip_int << 16) + int(field, 16) + + return ip_int + + def _compress_hextets(self, hextets): + """Compresses a list of hextets. + + Compresses a list of strings, replacing the longest continuous + sequence of "0" in the list with "" and adding empty strings at + the beginning or at the end of the string such that subsequently + calling ":".join(hextets) will produce the compressed version of + the IPv6 address. + + Args: + hextets: A list of strings, the hextets to compress. + + Returns: + A list of strings. + + """ + best_doublecolon_start = -1 + best_doublecolon_len = 0 + doublecolon_start = -1 + doublecolon_len = 0 + for index in range(len(hextets)): + if hextets[index] == '0': + doublecolon_len += 1 + if doublecolon_start == -1: + # Start of a sequence of zeros. + doublecolon_start = index + if doublecolon_len > best_doublecolon_len: + # This is the longest sequence of zeros so far. + best_doublecolon_len = doublecolon_len + best_doublecolon_start = doublecolon_start + else: + doublecolon_len = 0 + doublecolon_start = -1 + + if best_doublecolon_len > 1: + best_doublecolon_end = (best_doublecolon_start + + best_doublecolon_len) + # For zeros at the end of the address. + if best_doublecolon_end == len(hextets): + hextets += [''] + hextets[best_doublecolon_start:best_doublecolon_end] = [''] + # For zeros at the beginning of the address. + if best_doublecolon_start == 0: + hextets = [''] + hextets + + return hextets + + def _string_from_ip_int(self, ip_int=None): + """Turns a 128-bit integer into hexadecimal notation. + + Args: + ip_int: An integer, the IP address. + + Returns: + A string, the hexadecimal representation of the address. + + Raises: + ValueError: The address is bigger than 128 bits of all ones. + + """ + if not ip_int and ip_int != 0: + ip_int = int(self._ip) + + if ip_int > self._ALL_ONES: + raise ValueError('IPv6 address is too large') + + hex_str = '%032x' % ip_int + hextets = [] + for x in range(0, 32, 4): + hextets.append('%x' % int(hex_str[x:x+4], 16)) + + hextets = self._compress_hextets(hextets) + return ':'.join(hextets) + + def _explode_shorthand_ip_string(self, ip_str=None): + """Expand a shortened IPv6 address. + + Args: + ip_str: A string, the IPv6 address. + + Returns: + A string, the expanded IPv6 address. + + """ + if not ip_str: + ip_str = str(self) + + if self._is_shorthand_ip(ip_str): + new_ip = [] + hextet = ip_str.split('::') + sep = len(hextet[0].split(':')) + len(hextet[1].split(':')) + new_ip = hextet[0].split(':') + + for _ in xrange(8 - sep): + new_ip.append('0000') + new_ip += hextet[1].split(':') + + # Now need to make sure every hextet is 4 lower case characters. + # If a hextet is < 4 characters, we've got missing leading 0's. + ret_ip = [] + for hextet in new_ip: + ret_ip.append(('0' * (4 - len(hextet)) + hextet).lower()) + return ':'.join(ret_ip) + # We've already got a longhand ip_str. + return ip_str + + def _is_valid_ip(self, ip_str): + """Ensure we have a valid IPv6 address. + + Probably not as exhaustive as it should be. + + Args: + ip_str: A string, the IPv6 address. + + Returns: + A boolean, True if this is a valid IPv6 address. + + """ + # We need to have at least one ':'. + if ':' not in ip_str: + return False + + # We can only have one '::' shortener. + if ip_str.count('::') > 1: + return False + + # '::' should be encompassed by start, digits or end. + if ':::' in ip_str: + return False + + # A single colon can neither start nor end an address. + if ((ip_str.startswith(':') and not ip_str.startswith('::')) or + (ip_str.endswith(':') and not ip_str.endswith('::'))): + return False + + # If we have no concatenation, we need to have 8 fields with 7 ':'. + if '::' not in ip_str and ip_str.count(':') != 7: + # We might have an IPv4 mapped address. + if ip_str.count('.') != 3: + return False + + ip_str = self._explode_shorthand_ip_string(ip_str) + + # Now that we have that all squared away, let's check that each of the + # hextets are between 0x0 and 0xFFFF. + for hextet in ip_str.split(':'): + if hextet.count('.') == 3: + # If we have an IPv4 mapped address, the IPv4 portion has to be + # at the end of the IPv6 portion. + if not ip_str.split(':')[-1] == hextet: + return False + try: + IPv4Network(hextet) + except IPv4IpValidationError: + return False + elif int(hextet, 16) < 0x0 or int(hextet, 16) > 0xFFFF: + return False + return True + + def _is_shorthand_ip(self, ip_str=None): + """Determine if the address is shortened. + + Args: + ip_str: A string, the IPv6 address. + + Returns: + A boolean, True if the address is shortened. + + """ + if ip_str.count('::') == 1: + return True + return False + + @property + def max_prefixlen(self): + return self._max_prefixlen + + @property + def packed(self): + """The binary representation of this address.""" + return struct.pack('!QQ', self._ip >> 64, self._ip & (2**64 - 1)) + + @property + def version(self): + return self._version + + @property + def is_multicast(self): + """Test if the address is reserved for multicast use. + + Returns: + A boolean, True if the address is a multicast address. + See RFC 2373 2.7 for details. + + """ + return self in IPv6Network('ff00::/8') + + @property + def is_reserved(self): + """Test if the address is otherwise IETF reserved. + + Returns: + A boolean, True if the address is within one of the + reserved IPv6 Network ranges. + + """ + return (self in IPv6Network('::/8') or + self in IPv6Network('100::/8') or + self in IPv6Network('200::/7') or + self in IPv6Network('400::/6') or + self in IPv6Network('800::/5') or + self in IPv6Network('1000::/4') or + self in IPv6Network('4000::/3') or + self in IPv6Network('6000::/3') or + self in IPv6Network('8000::/3') or + self in IPv6Network('A000::/3') or + self in IPv6Network('C000::/3') or + self in IPv6Network('E000::/4') or + self in IPv6Network('F000::/5') or + self in IPv6Network('F800::/6') or + self in IPv6Network('FE00::/9')) + + @property + def is_unspecified(self): + """Test if the address is unspecified. + + Returns: + A boolean, True if this is the unspecified address as defined in + RFC 2373 2.5.2. + + """ + return self == IPv6Network('::') + + @property + def is_loopback(self): + """Test if the address is a loopback adddress. + + Returns: + A boolean, True if the address is a loopback address as defined in + RFC 2373 2.5.3. + + """ + return self == IPv6Network('::1') + + @property + def is_link_local(self): + """Test if the address is reserved for link-local. + + Returns: + A boolean, True if the address is reserved per RFC 4291. + + """ + return self in IPv6Network('fe80::/10') + + @property + def is_site_local(self): + """Test if the address is reserved for site-local. + + Note that the site-local address space has been deprecated by RFC 3879. + Use is_private to test if this address is in the space of unique local + addresses as defined by RFC 4193. + + Returns: + A boolean, True if the address is reserved per RFC 3513 2.5.6. + + """ + return self in IPv6Network('fec0::/10') + + @property + def is_private(self): + """Test if this address is allocated for private networks. + + Returns: + A boolean, True if the address is reserved per RFC 4193. + + """ + return self in IPv6Network('fc00::/7') + + @property + def ipv4_mapped(self): + """Return the IPv4 mapped address. + + Returns: + If the IPv6 address is a v4 mapped address, return the + IPv4 mapped address. Return None otherwise. + + """ + hextets = self._explode_shorthand_ip_string().split(':') + if hextets[-3] != 'ffff': + return None + try: + return IPv4Address(int('%s%s' % (hextets[-2], hextets[-1]), 16)) + except IPv4IpvalidationError: + return None + + +class IPv6Address(BaseV6, BaseIP): + + """Represent and manipulate single IPv6 Addresses. + """ + + def __init__(self, address): + """Instantiate a new IPv6 address object. + + Args: + address: A string or integer representing the IP + + Additionally, an integer can be passed, so + IPv6Address('2001:4860::') == + IPv6Address(42541956101370907050197289607612071936L). + or, more generally + IPv6Address(IPv6Address('2001:4860::')._ip) == + IPv6Address('2001:4860::') + + + Raises: + IPv6IpValidationError: If address isn't a valid IPv6 address. + IPv6NetmaskValidationError: If the netmask isn't valid for + an IPv6 address. + + """ + BaseIP.__init__(self, address) + BaseV6.__init__(self, address) + + # Efficient constructor from integer. + if isinstance(address, (int, long)): + self._ip = address + if address < 0 or address > self._ALL_ONES: + raise IPv6IpValidationError(address) + return + + # Constructing from a packed address + if _compat_has_real_bytes: + if isinstance(address, bytes) and len(address) == 16: + tmp = struct.unpack('!QQ', address) + self._ip = (tmp[0] << 64) | tmp[1] + return + + # Assume input argument to be string or any object representation + # which converts into a formatted IP string. + addr_str = str(address) + if not addr_str: + raise IPv6IpValidationError('') + + self._ip = self._ip_int_from_string(addr_str) + + +class IPv6Network(BaseV6, BaseNet): + + """This class represents and manipulates 128-bit IPv6 networks. + + Attributes: [examples for IPv6('2001:658:22A:CAFE:200::1/64')] + .ip: IPv6Address('2001:658:22a:cafe:200::1') + .network: IPv6Address('2001:658:22a:cafe::') + .hostmask: IPv6Address('::ffff:ffff:ffff:ffff') + .broadcast: IPv6Address('2001:658:22a:cafe:ffff:ffff:ffff:ffff') + .netmask: IPv6Address('ffff:ffff:ffff:ffff::') + .prefixlen: 64 + + """ + + + def __init__(self, address): + """Instantiate a new IPv6 Network object. + + Args: + address: A string or integer representing the IPv6 network or the IP + and prefix/netmask. + '2001:4860::/128' + '2001:4860:0000:0000:0000:0000:0000:0000/128' + '2001:4860::' + are all functionally the same in IPv6. That is to say, + failing to provide a subnetmask will create an object with + a mask of /128. + + Additionally, an integer can be passed, so + IPv6Network('2001:4860::') == + IPv6Network(42541956101370907050197289607612071936L). + or, more generally + IPv6Network(IPv6Network('2001:4860::')._ip) == + IPv6Network('2001:4860::') + + Raises: + IPv6IpValidationError: If address isn't a valid IPv6 address. + IPv6NetmaskValidationError: If the netmask isn't valid for + an IPv6 address. + + """ + BaseNet.__init__(self, address) + BaseV6.__init__(self, address) + + # Efficient constructor from integer. + if isinstance(address, (int, long)): + self._ip = address + self.ip = IPv6Address(self._ip) + self._prefixlen = 128 + self.netmask = IPv6Address(self._ALL_ONES) + if address < 0 or address > self._ALL_ONES: + raise IPv6IpValidationError(address) + return + + # Constructing from a packed address + if _compat_has_real_bytes: + if isinstance(address, bytes) and len(address) == 16: + tmp = struct.unpack('!QQ', address) + self._ip = (tmp[0] << 64) | tmp[1] + self.ip = IPv6Address(self._ip) + self._prefixlen = 128 + self.netmask = IPv6Address(self._ALL_ONES) + return + + # Assume input argument to be string or any object representation + # which converts into a formatted IP prefix string. + addr = str(address).split('/') + + if len(addr) > 2: + raise IPv6IpValidationError(ipaddr) + + if not self._is_valid_ip(addr[0]): + raise IPv6IpValidationError(addr[0]) + + if len(addr) == 2: + if self._is_valid_netmask(addr[1]): + self._prefixlen = int(addr[1]) + else: + raise IPv6NetmaskValidationError(addr[1]) + else: + self._prefixlen = 128 + + self.netmask = IPv6Address(self._ip_int_from_prefix(self._prefixlen)) + + if not self._is_valid_ip(addr[0]): + raise IPv6IpValidationError(addr[0]) + + self._ip = self._ip_int_from_string(addr[0]) + self.ip = IPv6Address(self._ip) + + + def _is_valid_netmask(self, prefixlen): + """Verify that the netmask/prefixlen is valid. + + Args: + prefixlen: A string, the netmask in prefix length format. + + Returns: + A boolean, True if the prefix represents a valid IPv6 + netmask. + + """ + try: + prefixlen = int(prefixlen) + except ValueError: + return False + return 0 <= prefixlen <= 128 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/iso8601.py b/interactive-mining-3rdparty-madis/madis/src/lib/iso8601.py new file mode 100755 index 0000000..d1dfa19 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/iso8601.py @@ -0,0 +1,150 @@ +#Based on iso8601 from Michael Twomey +# +#Copyright (c) 2007 Michael Twomey +# +#Permission is hereby granted, free of charge, to any person obtaining a +#copy of this software and associated documentation files (the +#"Software"), to deal in the Software without restriction, including +#without limitation the rights to use, copy, modify, merge, publish, +#distribute, sublicense, and/or sell copies of the Software, and to +#permit persons to whom the Software is furnished to do so, subject to +#the following conditions: +# +#The above copyright notice and this permission notice shall be included +#in all copies or substantial portions of the Software. +# +#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +#OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +#MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +#IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +#CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +#TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +#SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +"""ISO 8601 date time string parsing + +Basic usage: +>>> import iso8601 +>>> iso8601.parse_date("2007-01-25T12:00:00Z") +datetime.datetime(2007, 1, 25, 12, 0, tzinfo=) +>>> + +""" + +from datetime import datetime, timedelta, tzinfo +import re + +__all__ = ["parse_date", "ParseError"] + +# Adapted from http://delete.me.uk/2005/03/iso8601.html +ISO8601_REGEX = re.compile(r"((?P[0-9]{4})(-(?P[0-9]{1,2})(-(?P[0-9]{1,2}))?|W(?P[0-9]{1,2}))?)?" + r"(.?(?P[0-9]{2}):(?P[0-9]{2})(:(?P[0-9]{2})(\.(?P[0-9]+))?)?" + r"(?PZ|(([-+])([0-9]{2}):([0-9]{2})))?)?" +) + +TIMEZONE_REGEX = re.compile("(?P[+-])(?P[0-9]{2}).(?P[0-9]{2})") + +class ParseError(Exception): + """Raised when there is a problem parsing a date string""" + +# Yoinked from python docs +ZERO = timedelta(0) +class Utc(tzinfo): + """UTC + + """ + def utcoffset(self, dt): + return ZERO + + def tzname(self, dt): + return "UTC" + + def dst(self, dt): + return ZERO +UTC = Utc() + +class FixedOffset(tzinfo): + """Fixed offset in hours and minutes from UTC + + """ + def __init__(self, offset_hours, offset_minutes, name): + self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes) + self.__name = name + + def utcoffset(self, dt): + return self.__offset + + def tzname(self, dt): + return self.__name + + def dst(self, dt): + return ZERO + + def __repr__(self): + return "" % self.__name + +def parse_timezone(tzstring, default_timezone=UTC): + """Parses ISO 8601 time zone specs into tzinfo offsets + + """ + if tzstring == "Z": + return default_timezone + # This isn't strictly correct, but it's common to encounter dates without + # timezones so I'll assume the default (which defaults to UTC). + # Addresses issue 4. + if tzstring is None: + return default_timezone + m = TIMEZONE_REGEX.match(tzstring) + prefix, hours, minutes = m.groups() + hours, minutes = int(hours), int(minutes) + if prefix == "-": + hours = -hours + minutes = -minutes + return FixedOffset(hours, minutes, tzstring) + +def parse_date(datestring, default_timezone=UTC): + """Parses ISO 8601 dates into datetime objects + + The timezone is parsed from the date string. However it is quite common to + have dates without a timezone (not strictly correct). In this case the + default timezone specified in default_timezone is used. This is UTC by + default. + """ + if not isinstance(datestring, basestring): + raise ParseError("Expecting a string %r" % datestring) + m = ISO8601_REGEX.match(datestring) + if not m: + raise ParseError("Unable to parse date string %r" % datestring) + groups = m.groupdict() + + if default_timezone!=None: + tz = parse_timezone(groups["timezone"], default_timezone=default_timezone) + else: + tz=None + + if not groups["year"]: + raise ParseError("Unable to parse date string %r" % datestring) + if not groups["month"]: + groups["month"]=1 + if not groups["day"]: + groups["day"]=1 + if not groups["hour"]: + groups["hour"]=0 + if not groups["minute"]: + groups["minute"]=0 + if not groups["second"]: + groups["second"]=0 + if not groups["fraction"]: + groups["fraction"] = 0 + else: + groups["fraction"] = int(float("0.%s" % groups["fraction"]) * 1e6) + + if groups["week"]: + return datetime(int(groups["year"]), 1, 1, + int(groups["hour"]), int(groups["minute"]), int(groups["second"]), + int(groups["fraction"]), tz) + timedelta(weeks=(max(int(groups["week"])-1, 0))) + else: + return datetime(int(groups["year"]), int(groups["month"]), int(groups["day"]), + int(groups["hour"]), int(groups["minute"]), int(groups["second"]), + int(groups["fraction"]), tz) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/iterutils.py b/interactive-mining-3rdparty-madis/madis/src/lib/iterutils.py new file mode 100644 index 0000000..452ab7c --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/iterutils.py @@ -0,0 +1,51 @@ +import itertools + +class peekable(): + """ An iterator that supports a peek operation. Example usage: + >>> p = peekable(range(4)) + >>> p.peek( ) + 0 + >>> p.next() + 0 + >>> p.peek() + 1 + >>> p.next() + 1 + >>> p.peek() + 2 + >>> p.peek() + 2 + >>> p.next() + 2 + >>> p.peek() + 3 + >>> p.next() + 3 + >>> p.peek() + Traceback (most recent call last): + ... + StopIteration + """ + + def __init__(self, iterable): + self._srciter = iter(iterable) + self._iter = self._srciter + self.next=self._iter.next + + def __iter__(self): + return self + + def peek(self): + tmp=self._iter.next() + self._iter=itertools.chain([tmp], self._srciter) + self.next=self._iter.next + return tmp + +if not ('.' in __name__): + """ + This is needed to be able to test the function, put it at the end of every + new function you create + """ + if __name__ == "__main__": + import doctest + doctest.testmod() \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/jaydebeapi/COPYING.LESSER b/interactive-mining-3rdparty-madis/madis/src/lib/jaydebeapi/COPYING.LESSER new file mode 100644 index 0000000..65c5ca8 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/jaydebeapi/COPYING.LESSER @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/jaydebeapi/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/jaydebeapi/__init__.py new file mode 100644 index 0000000..2e4ba3a --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/jaydebeapi/__init__.py @@ -0,0 +1 @@ +from dbapi2 import * diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/jaydebeapi/dbapi2.py b/interactive-mining-3rdparty-madis/madis/src/lib/jaydebeapi/dbapi2.py new file mode 100644 index 0000000..457c466 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/jaydebeapi/dbapi2.py @@ -0,0 +1,504 @@ +#-*- coding: utf-8 -*- + +# Copyright 2010, 2011, 2012, 2013 Bastian Bowe +# +# This file is part of JayDeBeApi. +# JayDeBeApi is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# JayDeBeApi 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with JayDeBeApi. If not, see +# . + +import datetime +import exceptions +import glob +import os +import time +import re +import sys +from types import NoneType + +_jdbc_connect = None + +_java_array_byte = None + +_java_BigDecimal = None + +def _jdbc_connect_jython(jclassname, jars, libs, *args): + if _converters is None: + from java.sql import Types + types = Types + types_map = {} + const_re = re.compile('[A-Z][A-Z_]*$') + for i in dir(types): + if const_re.match(i): + types_map[i] = getattr(types, i) + _init_converters(types_map) + global _java_array_byte + if _java_array_byte is None: + import jarray + def _java_array_byte(data): + return jarray.array(data, 'b') + # register driver for DriverManager + jpackage = jclassname[:jclassname.rfind('.')] + dclassname = jclassname[jclassname.rfind('.') + 1:] + # print jpackage + # print dclassname + # print jpackage + from java.lang import Class + from java.lang import ClassNotFoundException + try: + Class.forName(jclassname).newInstance() + except ClassNotFoundException: + if not jars: + raise + _jython_set_classpath(jars) + Class.forName(jclassname).newInstance() + from java.sql import DriverManager + return DriverManager.getConnection(*args) + +def _jython_set_classpath(jars): + ''' + import a jar at runtime (needed for JDBC [Class.forName]) + + adapted by Bastian Bowe from + http://stackoverflow.com/questions/3015059/jython-classpath-sys-path-and-jdbc-drivers + ''' + from java.net import URL, URLClassLoader + from java.lang import ClassLoader + from java.io import File + m = URLClassLoader.getDeclaredMethod("addURL", [URL]) + m.accessible = 1 + urls = [File(i).toURL() for i in jars] + m.invoke(ClassLoader.getSystemClassLoader(), urls) + +def _prepare_jython(): + global _jdbc_connect + _jdbc_connect = _jdbc_connect_jython + +def _jdbc_connect_jpype(jclassname, jars, libs, *driver_args): + global _java_BigDecimal + + import jpype + + if not jpype.isJVMStarted(): + args = [] + class_path = [] + if jars: + class_path.extend(jars) + class_path.extend(_get_classpath()) + if class_path: + args.append('-Djava.class.path=%s' % + os.path.pathsep.join(class_path)) + if libs: + # path to shared libraries + libs_path = os.path.pathsep.join(libs) + args.append('-Djava.library.path=%s' % libs_path) + # jvm_path = ('/usr/lib/jvm/java-6-openjdk' + # '/jre/lib/i386/client/libjvm.so') + jvm_path = jpype.getDefaultJVMPath() + jpype.startJVM(jvm_path, *args) + + if not jpype.isThreadAttachedToJVM(): + jpype.attachThreadToJVM() + if _converters is None: + types = jpype.java.sql.Types + _java_BigDecimal = jpype.JClass('java.math.BigDecimal') + types_map = {} + for i in types.__javaclass__.getClassFields(): + types_map[i.getName()] = i.getStaticAttribute() + _init_converters(types_map) + global _java_array_byte + if _java_array_byte is None: + def _java_array_byte(data): + return jpype.JArray(jpype.JByte, 1)(data) + # register driver for DriverManager + jpype.JClass(jclassname) + return jpype.java.sql.DriverManager.getConnection(*driver_args) + +def _get_classpath(): + """Extract CLASSPATH from system environment as JPype doesn't seem + to respect that variable. + """ + try: + orig_cp = os.environ['CLASSPATH'] + except KeyError: + return [] + expanded_cp = [] + for i in orig_cp.split(os.path.pathsep): + expanded_cp.extend(_jar_glob(i)) + return expanded_cp + +def _jar_glob(item): + if item.endswith('*'): + return glob.glob('%s.[jJ][aA][rR]' % item) + else: + return [item] + +def _prepare_jpype(): + global _jdbc_connect + _jdbc_connect = _jdbc_connect_jpype + +if sys.platform.lower().startswith('java'): + _prepare_jython() +else: + _prepare_jpype() + +apilevel = '2.0' +threadsafety = 1 +paramstyle = 'qmark' + +class DBAPITypeObject(object): + def __init__(self,*values): + self.values = values + def __cmp__(self,other): + if other in self.values: + return 0 + if other < self.values: + return 1 + else: + return -1 + +STRING = DBAPITypeObject("CHARACTER", "CHAR", "VARCHAR", + "CHARACTER VARYING", "CHAR VARYING", "STRING",) + +TEXT = DBAPITypeObject("CLOB", "CHARACTER LARGE OBJECT", + "CHAR LARGE OBJECT", "XML",) + +BINARY = DBAPITypeObject("BLOB", "BINARY LARGE OBJECT",) + +NUMBER = DBAPITypeObject("INTEGER", "INT", "SMALLINT", "BIGINT",) + +FLOAT = DBAPITypeObject("FLOAT", "REAL", "DOUBLE", "DECFLOAT") + +DECIMAL = DBAPITypeObject("DECIMAL", "DEC", "NUMERIC", "NUM",) + +DATE = DBAPITypeObject("DATE",) + +TIME = DBAPITypeObject("TIME",) + +DATETIME = DBAPITypeObject("TIMESTAMP",) + +ROWID = DBAPITypeObject(()) + +# DB-API 2.0 Module Interface Exceptions +class Error(exceptions.StandardError): + pass + +class Warning(exceptions.StandardError): + pass + +class InterfaceError(Error): + pass + +class DatabaseError(Error): + pass + +class InternalError(DatabaseError): + pass + +class OperationalError(DatabaseError): + pass + +class ProgrammingError(DatabaseError): + pass + +class IntegrityError(DatabaseError): + pass + +class DataError(DatabaseError): + pass + +class NotSupportedError(DatabaseError): + pass + +# DB-API 2.0 Type Objects and Constructors + +def _java_sql_blob(data): + return _java_array_byte(data) + +Binary = _java_sql_blob + +def _str_func(func): + def to_str(*parms): + return str(func(*parms)) + return to_str + +Date = _str_func(datetime.date) + +Time = _str_func(datetime.time) + +Timestamp = _str_func(datetime.datetime) + +def DateFromTicks(ticks): + return apply(Date, time.localtime(ticks)[:3]) + +def TimeFromTicks(ticks): + return apply(Time, time.localtime(ticks)[3:6]) + +def TimestampFromTicks(ticks): + return apply(Timestamp, time.localtime(ticks)[:6]) + +# DB-API 2.0 Module Interface connect constructor +def connect(jclassname, driver_args, jars=None, libs=None): + """Open a connection to a database using a JDBC driver and return + a Connection instance. + + jclassname: Full qualified Java class name of the JDBC driver. + driver_args: Argument or sequence of arguments to be passed to the + Java DriverManager.getConnection method. Usually the + database URL. See + http://docs.oracle.com/javase/6/docs/api/java/sql/DriverManager.html + for more details + jars: Jar filename or sequence of filenames for the JDBC driver + libs: Dll/so filenames or sequence of dlls/sos used as shared + library by the JDBC driver + """ + if isinstance(driver_args, basestring): + driver_args = [ driver_args ] + if jars: + if isinstance(jars, basestring): + jars = [ jars ] + else: + jars = [] + if libs: + if isinstance(libs, basestring): + libs = [ libs ] + else: + libs = [] + jconn = _jdbc_connect(jclassname, jars, libs, *driver_args) + return Connection(jconn, _converters) + +# DB-API 2.0 Connection Object +class Connection(object): + + jconn = None + + def __init__(self, jconn, converters): + self.jconn = jconn + self._converters = converters + + def close(self): + self.jconn.close() + + def commit(self): + self.jconn.commit() + + def rollback(self): + self.jconn.rollback() + + def cursor(self): + return Cursor(self, self._converters) + +# DB-API 2.0 Cursor Object +class Cursor(object): + + rowcount = -1 + _meta = None + _prep = None + _rs = None + _next = None + _getObject = None + _description = None + + def __init__(self, connection, converters): + self._connection = connection + self._converters = converters + + @property + def description(self): + if self._description: + return self._description + m = self._meta + if m: + count = m.getColumnCount() + self._count = count + self._description = [] + self._coltypes = [None] + for col in range(1, count + 1): + size = m.getColumnDisplaySize(col) + col_desc = ( m.getColumnName(col), + m.getColumnTypeName(col), + size, + size, + m.getPrecision(col), + m.getScale(col), + m.isNullable(col), + ) + self._description.append(col_desc) + self._coltypes.append(m.getColumnType(col)) + self._coltypes = tuple(self._coltypes) + self._row = [None] * count + return self._description + +# optional callproc(self, procname, *parameters) unsupported + + def close(self): + self._close_last() + self._connection = None + + def _close_last(self): + """Close the resultset and reset collected meta data. + """ + if self._rs: + self._rs.close() + self._rs = None + if self._prep: + self._prep.close() + self._prep = None + self._meta = None + self._description = None + + # TODO: this is a possible way to close the open result sets + # but I'm not sure when __del__ will be called + __del__ = _close_last + + def _set_stmt_parms(self, prep_stmt, parameters): + for i in range(len(parameters)): + # print (i, parameters[i], type(parameters[i])) + prep_stmt.setObject(i + 1, parameters[i]) + + def execute(self, operation, parameters=None): + if not parameters: + parameters = () + self._close_last() + self._prep = self._connection.jconn.prepareStatement(operation) + self._set_stmt_parms(self._prep, parameters) + is_rs = self._prep.execute() + if is_rs: + self._rs = self._prep.getResultSet() + self._next = self._rs.next + self._getObject = self._rs.getObject + self._meta = self._rs.getMetaData() + self.rowcount = -1 + else: + self.rowcount = self._prep.getUpdateCount() + # self._prep.getWarnings() ??? + + def executemany(self, operation, seq_of_parameters): + self._close_last() + self._prep = self._connection.jconn.prepareStatement(operation) + for parameters in seq_of_parameters: + self._set_stmt_parms(self._prep, parameters) + self._prep.addBatch() + update_counts = self._prep.executeBatch() + # self._prep.getWarnings() ??? + self.rowcount = sum(update_counts) + self._close_last() + + def fetchone(self): + global _java_BigDecimal + #raise if not rs + if self._next(): + lgetObject = self._getObject + lconverters = self._converters + lrow = self._row + for col in xrange(self._count): + # print sqltype + # TODO: Oracle 11 will read a oracle.sql.TIMESTAMP + # which can't be converted to string easily + v = lgetObject(col + 1) + if not isinstance(v, (_java_BigDecimal, basestring, int, long, float, bool, NoneType)): + converter = lconverters.get(self._coltypes[col]) + if converter: + v = converter(v) + lrow[col] = v + return lrow + return None + + def fetchmany(self, size=None): + if size is None: + size = self.arraysize + # TODO: handle SQLException if not supported by db + self._rs.setFetchSize(size) + rows = [] + row = None + for i in xrange(size): + row = self.fetchone() + if row is None: + break + else: + rows.append(row) + # reset fetch size + if row: + # TODO: handle SQLException if not supported by db + self._rs.setFetchSize(0) + return rows + + def fetchall(self): + rows = [] + while True: + row = self.fetchone() + if row is None: + break + else: + rows.append(row) + return rows + + # optional nextset() unsupported + + arraysize = 1 + + def setinputsizes(self, sizes): + pass + + def setoutputsize(self, size, column=None): + pass + +def _to_datetime(java_val): + d = datetime.datetime.strptime(str(java_val)[:19], "%Y-%m-%d %H:%M:%S") + if not isinstance(java_val, basestring): + d = d.replace(microsecond=int(str(java_val.getNanos())[:6])) + return str(d) + # return str(java_val) + +def _to_date(java_val): + d = datetime.datetime.strptime(str(java_val)[:10], "%Y-%m-%d") + return d.strftime("%Y-%m-%d") + # return str(java_val) + +def _java_to_py(java_method): + def to_py(java_val): + return getattr(java_val, java_method)() + return to_py + +_to_double = lambda x: getattr(x, 'doubleValue', lambda: x)() +_to_int = lambda x: getattr(x, 'intValue')() + +def _init_converters(types_map): + """Prepares the converters for conversion of java types to python + objects. + types_map: Mapping of java.sql.Types field name to java.sql.Types + field constant value""" + global _converters + _converters = {} + for i in _DEFAULT_CONVERTERS: + const_val = types_map[i] + _converters[const_val] = _DEFAULT_CONVERTERS[i] + +# Mapping from java.sql.Types field to converter method +_converters = None + +_DEFAULT_CONVERTERS = { + # see + # http://download.oracle.com/javase/1.4.2/docs/api/java/sql/Types.html + # for possible keys + 'TIMESTAMP': _to_datetime, + 'DATE': _to_date, + 'BINARY': str, + 'DECIMAL': _to_double, + 'NUMERIC': _to_double, + 'DOUBLE': _to_double, + 'FLOAT': _to_double, + 'INTEGER': _to_int, + 'SMALLINT': _to_int, + 'BOOLEAN': _java_to_py('booleanValue'), +} diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/jdbc/readme.txt b/interactive-mining-3rdparty-madis/madis/src/lib/jdbc/readme.txt new file mode 100644 index 0000000..5e9afb0 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/jdbc/readme.txt @@ -0,0 +1 @@ +This directory contains JDBC JAR files. diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/jopts.py b/interactive-mining-3rdparty-madis/madis/src/lib/jopts.py new file mode 100644 index 0000000..1d2de90 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/jopts.py @@ -0,0 +1,202 @@ +""" +This is the jgroup module + +It features conversion to and from jlists + +>>> toj(3) +3 +>>> toj('3') +'3' +>>> toj('test') +'test' +>>> toj(u'test') +u'test' +>>> toj('[testjsonlike]') +'["[testjsonlike]"]' +>>> toj('[testjsonlike') +'[testjsonlike' +>>> toj([3]) +3 +>>> toj(['test']) +'test' +>>> toj(['test',3]) +'["test",3]' +>>> toj([3,'test']) +'[3,"test"]' +>>> toj(['[test']) +'[test' +>>> toj(None) + +>>> toj('') +u'' +>>> toj([]) +u'[]' +>>> tojstrict('asdf') +'["asdf"]' +>>> tojstrict(['a',3]) +'["a",3]' +>>> fromj('["a", 3]') +[u'a', 3] +>>> fromj(3) +[3] +>>> fromj('a') +['a'] +>>> fromj('["a", 3]') +[u'a', 3] +>>> fromj('[null]') +[None] +>>> fromj('[asdf]') +['[asdf]'] +>>> fromj('') +[u''] +>>> fromj('[]') +[] +>>> elemfromj(1,2,3) +[1, 2, 3] +>>> elemfromj(1,None,3) +[1, None, 3] +>>> fromjsingle("[1,2]") +[1, 2] +""" + +import json +try: + from collections import OrderedDict +except ImportError: + # Python 2.6 + from lib.collections26 import OrderedDict + +def toj(l): + if l==None: + return l + typel=type(l) + if typel==str or typel==unicode: + if l=='': + return u'' + elif l[0]!='[' or l[-1]!=']': + return l + else: + return json.dumps([l], separators=(',',':'), ensure_ascii=False) + if typel==int or typel==float: + return l + if typel==list or typel==tuple: + lenl=len(l) + if lenl==1: + typel=type(l[0]) + if typel==str or typel==unicode: + if l[0]=='': + return u'' + elif l[0][0]!='[' or l[0][-1]!=']': + return l[0] + if typel==int or typel==float: + return l[0] + if lenl==0: + return u'[]' + return json.dumps(l, separators=(',',':'), ensure_ascii=False) + return json.dumps(l, separators=(',',':'), ensure_ascii=False) + +def tojstrict(l): + if type(l)==list: + return json.dumps(l, separators=(',',':'), ensure_ascii=False) + return json.dumps([l], separators=(',',':'), ensure_ascii=False) + +def fromjsingle(j): + typej=type(j) + if typej == int or typej == float: + return j + if typej == str or typej == unicode: + if j == '': + return u'' + if (j[0] == '[' and j[-1] == ']') or (j[0]=='{' and j[-1]=='}'): + try: + return json.loads(j, object_pairs_hook = OrderedDict) + except KeyboardInterrupt: + raise + except: + return j + return j + +def fromj(*jargs): + fj=[] + for j in jargs: + typej=type(j) + if typej==int or typej==float: + fj+= [j] + continue + if typej==str or typej==unicode: + if j=='': + fj+= [u''] + continue + if (j[0]=='[' and j[-1]==']'): + try: + fj+=json.loads(j) + continue + except KeyboardInterrupt: + raise + except: + fj+= [j] + continue + if (j[0]=='{' and j[-1]=='}'): + try: + fj+=list(json.loads(j, object_pairs_hook = OrderedDict)) + continue + except KeyboardInterrupt: + raise + except: + fj+= [j] + continue + fj+= [j] + return fj + +def elemfromj(*jargs): + fj=[] + for j in jargs: + if j is None: + fj+=[None] + continue + typej=type(j) + if typej==int or typej==float: + fj+= [j] + continue + if typej==str or typej==unicode: + if j=='': + fj+= [u''] + continue + if j[0]=='[' and j[-1]==']': + try: + fj+=[json.loads(j)] + continue + except KeyboardInterrupt: + raise + except: + fj+= [j] + continue + if (j[0]=='{' and j[-1]=='}'): + try: + fj+=[json.loads(j, object_pairs_hook = OrderedDict)] + continue + except KeyboardInterrupt: + raise + except: + fj+= [j] + continue + fj+= [j] + return fj + +#Flatten based on BasicTypes for Python +# Copyright (c) 2002-2003, Michael C. Fletcher +# All rights reserved. +def flatten(inlist, type=type, ltype=(list,tuple)): + try: + ind=0 + while True: + while isinstance( inlist[ind], ltype): + inlist[ind:ind+1] = list(inlist[ind]) + ind+=1 + except IndexError: + pass + return inlist + +if __name__ == "__main__": + import doctest + doctest.testmod() diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/jsonpath.py b/interactive-mining-3rdparty-madis/madis/src/lib/jsonpath.py new file mode 100644 index 0000000..ca5266c --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/jsonpath.py @@ -0,0 +1,342 @@ +""" +An XPath for JSON + +A port of the Perl, and JavaScript versions of JSONPath +see http://goessner.net/articles/JsonPath/ + +Based on on JavaScript version by Stefan Goessner at: + http://code.google.com/p/jsonpath/ +and Perl version by Kate Rhodes at: + http://github.com/masukomi/jsonpath-perl/tree/master +""" + +__author__ = "Phil Budne" +__revision__ = "$Revision: 1.13 $" +__version__ = '0.54' + +# Copyright (c) 2007 Stefan Goessner (goessner.net) +# Copyright (c) 2008 Kate Rhodes (masukomi.org) +# Copyright (c) 2008-2012 Philip Budne (ultimate.com) +# Licensed under the MIT licence: +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. + +import re +import sys + +# XXX BUGS: +# evalx is generally a crock: +# handle !@.name.name??? +# there are probably myriad unexpected ways to get an exception: +# wrap initial "trace" call in jsonpath body in a try/except?? + +# XXX TODO: +# internally keep paths as lists to preserve integer types +# (instead of as ';' delimited strings) + +__all__ = [ 'jsonpath' ] + +# XXX precompile RE objects on load??? +# re_1 = re.compile(.....) +# re_2 = re.compile(.....) + +def normalize(x): + """normalize the path expression; outside jsonpath to allow testing""" + subx = [] + + # replace index/filter expressions with placeholders + # Python anonymous functions (lambdas) are cryptic, hard to debug + def f1(m): + n = len(subx) # before append + g1 = m.group(1) + subx.append(g1) + ret = "[#%d]" % n +# print "f1:", g1, ret + return ret + x = re.sub(r"[\['](\??\(.*?\))[\]']", f1, x) + + # added the negative lookbehind -krhodes + x = re.sub(r"'?(? 1: print "\tf03", key, loc, expr, path + trace(s(key, expr), obj, path) + walk(loc, x, obj, path, f03) + elif loc == "..": + trace(x, obj, path) + def f04(key, loc, expr, obj, path): + if debug > 1: print "\tf04", key, loc, expr, path + if isinstance(obj, dict): + if key in obj: + trace(s('..', expr), obj[key], s(path, key)) + else: + if key < len(obj): + trace(s('..', expr), obj[key], s(path, key)) + walk(loc, x, obj, path, f04) + elif loc == "!": + # Perl jsonpath extension: return keys + def f06(key, loc, expr, obj, path): + if isinstance(obj, dict): + trace(expr, key, path) + walk(loc, x, obj, path, f06) + elif isinstance(obj, dict) and loc in obj: + trace(x, obj[loc], s(path, loc)) + elif isinstance(obj, list) and isint(loc): + iloc = int(loc) + if len(obj) >= iloc: + trace(x, obj[iloc], s(path, loc)) + else: + # [(index_expression)] + if loc.startswith("(") and loc.endswith(")"): + if debug > 1: print "index", loc + e = evalx(loc, obj) + trace(s(e,x), obj, path) + return + + # ?(filter_expression) + if loc.startswith("?(") and loc.endswith(")"): + if debug > 1: print "filter", loc + def f05(key, loc, expr, obj, path): + if debug > 1: print "f05", key, loc, expr, path + if isinstance(obj, dict): + eval_result = evalx(loc, obj[key]) + else: + eval_result = evalx(loc, obj[int(key)]) + if eval_result: + trace(s(key, expr), obj, path) + + loc = loc[2:-1] + walk(loc, x, obj, path, f05) + return + + m = re.match(r'(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$', loc) + if m: + if isinstance(obj, (dict, list)): + def max(x,y): + if x > y: + return x + return y + + def min(x,y): + if x < y: + return x + return y + + objlen = len(obj) + s0 = m.group(1) + s1 = m.group(2) + s2 = m.group(3) + + # XXX int("badstr") raises exception + start = int(s0) if s0 else 0 + end = int(s1) if s1 else objlen + step = int(s2) if s2 else 1 + + if start < 0: + start = max(0, start+objlen) + else: + start = min(objlen, start) + if end < 0: + end = max(0, end+objlen) + else: + end = min(objlen, end) + + for i in xrange(start, end, step): + trace(s(i, x), obj, path) + return + + # after (expr) & ?(expr) + if loc.find(",") >= 0: + # [index,index....] + for piece in re.split(r"'?,'?", loc): + if debug > 1: print "piece", piece + trace(s(piece, x), obj, path) + else: + store(path, obj) + + def walk(loc, expr, obj, path, funct): + if isinstance(obj, list): + for i in xrange(0, len(obj)): + funct(i, loc, expr, obj, path) + elif isinstance(obj, dict): + for key in obj: + funct(key, loc, expr, obj, path) + + def evalx(loc, obj): + """eval expression""" + + if debug: print "evalx", loc + + # a nod to JavaScript. doesn't work for @.name.name.length + # Write len(@.name.name) instead!!! + loc = loc.replace("@.length", "len(__obj)") + + loc = loc.replace("&&", " and ").replace("||", " or ") + + # replace !@.name with 'name' not in obj + # XXX handle !@.name.name.name.... + def notvar(m): + return "'%s' not in __obj" % m.group(1) + loc = re.sub("!@\.([a-zA-Z@_]+)", notvar, loc) + + # replace @.name.... with __obj['name'].... + # handle @.name[.name...].length + def varmatch(m): + def brackets(elts): + ret = "__obj" + for e in elts: + if isint(e): + ret += "[%s]" % e # ain't necessarily so + else: + ret += "['%s']" % e # XXX beware quotes!!!! + return ret + g1 = m.group(1) + elts = g1.split('.') + if elts[-1] == "length": + return "len(%s)" % brackets(elts[1:-1]) + return brackets(elts[1:]) + + loc = re.sub(r'(? == translation + # causes problems if a string contains = + + # replace @ w/ "__obj", but \@ means a literal @ + loc = re.sub(r'(?", v + return v + + # body of jsonpath() + + # Get caller globals so eval can pick up user functions!!! + result = [] + if expr and obj: + cleaned_expr = normalize(expr) + if cleaned_expr.startswith("$;"): + cleaned_expr = cleaned_expr[2:] + + # XXX wrap this in a try?? + trace(cleaned_expr, obj, '$') + + if len(result) > 0: + return result + return False + +if __name__ == '__main__': + try: + import json # v2.6 + except ImportError: + import simplejson as json + + import sys + + # XXX take options for output format, output file, debug level + + if len(sys.argv) < 3 or len(sys.argv) > 4: + sys.stdout.write("Usage: jsonpath.py FILE PATH [OUTPUT_TYPE]\n") + sys.exit(1) + + object = json.load(file(sys.argv[1])) + path = sys.argv[2] + format = 'VALUE' + + if len(sys.argv) > 3: + # XXX verify? + format = sys.argv[3] + + value = jsonpath(object, path, format) + + if not value: + sys.exit(1) + + f = sys.stdout + json.dump(value, f, sort_keys=True, indent=1) + f.write("\n") + + sys.exit(0) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/kdtree.py b/interactive-mining-3rdparty-madis/madis/src/lib/kdtree.py new file mode 100644 index 0000000..9a56f21 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/kdtree.py @@ -0,0 +1,218 @@ +import operator +import itertools +from collections import deque +import math + +CONSTRAINT_EQ = 2 +CONSTRAINT_GT = 4 +CONSTRAINT_LE = 8 +CONSTRAINT_LT = 16 +CONSTRAINT_GE = 32 +LEFT = 0 +RIGHT = 1 +EXCLUSIVE =0 +SMALLEST = -1 +BIGGEST = 1 +NORMAL=0 +ENTIRERANGE = [(SMALLEST, None, LEFT), (BIGGEST, None, RIGHT)] +EMPTYRANGE= None +INFPOS=(BIGGEST, None, RIGHT) +INFNEG=(SMALLEST, None, LEFT) + +class Tree:pass + +def kdtree(data,cols=None): + if not data: + return + + if not cols: + try: + cols=range(len(data[0])) + except KeyboardInterrupt: + raise + except: + cols=[0] + k = len(cols) + if k==1: + data = sorted(data, key=operator.itemgetter(cols[0])) + + treedata=[None]*(2**int(math.ceil(math.log(len(data),2))+1)) + + kdtreerec(data,treedata,cols,0,0) + tree=Tree() + tree.columns=cols + tree.data=treedata + tree.numberofdata=len(data) + return tree + +def kdtreerec(data, treedata, cols, axis, index): + lendata= len(data) + median = lendata>>1 # choose median + k=len(cols) + if k!=1: + data = sorted(data, key=operator.itemgetter(cols[axis])) + + treedata[index]=data[median] + axis=axis+1 + if axis==k: + axis=0 + + if lendata!=1: + left=data[:median] + right=data[median:] + + del(data) + + kdtreerec(left, treedata, cols, axis, (index<<1)+1) + kdtreerec(right, treedata, cols, axis, (index+1)<<1) + return + +def query(tree, constraints=None, consargs=None): + if tree == None: + return + + columns=tree.columns + treedata=tree.data + numberofdata=tree.numberofdata + + k=len(columns) + cc={} + if constraints!=None and consargs!=None: + cc=compineconstraints(constraints, consargs) + ranges=[] + for c in columns: + if c not in cc: + ranges.append(ENTIRERANGE) + else: + ranges.append(cc[c]) + if cc==None: + return + + to_visit=deque() + treedatalen=len(treedata) + direct=True + index=axis=0 + while direct or len(to_visit)!=0: + if not direct: + index,axis = to_visit.pop() + else: + direct=False + row=treedata[index] + leftindex=(index<<1)+1 + + if leftindex>treedatalen or (leftindex>=numberofdata and leftindex(NORMAL, middle,0): + index=leftindex+1 + direct=True + if ranges[axis][0]<=(NORMAL, middle,0): + if direct: + to_visit.append((index , newaxis)) + else: + direct=True + index=leftindex + axis=newaxis + +def compineconstraints(constraints, consargs): + consdict={} + i=0 + ri=None + for c in constraints: + consaxis, constype = c + if consaxis not in consdict: + consdict[consaxis]=constrainttorange(constype, consargs[i]) + else: + ri=intersectranges(consdict[consaxis], constrainttorange(constype, consargs[i])) + if ri==None: + return None + consdict[consaxis]=ri + i=i+1 + + return consdict + +def intersectranges(range1, range2): + if EMPTYRANGE in range1 or EMPTYRANGE in range2 or range1[0] >= range1[1] or range2[0] >= range2[1]: + return EMPTYRANGE + maxofmin = max(range1[0], range2[0]) + minofmax = min(range1[1], range2[1]) + if maxofmin>=minofmax: + return EMPTYRANGE + return [maxofmin, minofmax] + +def constrainttorange(constype, consarg): + if constype<=CONSTRAINT_LE: + if constype==CONSTRAINT_LE: + return [INFNEG, (NORMAL, consarg, RIGHT)] + if constype==CONSTRAINT_EQ: + return [(NORMAL,consarg, LEFT), (NORMAL,consarg, RIGHT)] + else: #if constype==CONSTRAINT_GT: + return [(NORMAL,consarg, RIGHT), INFPOS] + else: + if constype==CONSTRAINT_GE: + return [(NORMAL,consarg, LEFT), INFPOS] + else: #if constype==CONSTRAINT_LT: + return [INFNEG, (NORMAL, consarg, LEFT)] + +if __name__ == "__main__": + print intersectranges([(NORMAL,5,LEFT),INFPOS], [(NORMAL,5,RIGHT), INFPOS]) + print intersectranges([(NORMAL,5,LEFT),INFPOS], [(NORMAL,2,RIGHT), (NORMAL,7,RIGHT)]) + print intersectranges([INFNEG,(NORMAL,5,LEFT)], [(NORMAL,2,RIGHT), (NORMAL,7,RIGHT)]) + print intersectranges([INFNEG,(NORMAL,5,RIGHT)], [(NORMAL,5,LEFT), INFPOS]) + print intersectranges([INFNEG,(NORMAL,'a',RIGHT)], [(NORMAL,'a',LEFT), INFPOS]) + print intersectranges([INFNEG,(NORMAL,'a',LEFT)], [(NORMAL,'a',RIGHT), INFPOS]) + print intersectranges([INFNEG,(NORMAL,'a',LEFT)], ENTIRERANGE) + print intersectranges([INFNEG,(NORMAL,0,LEFT)], ENTIRERANGE) + + print constrainttorange(CONSTRAINT_EQ, 2) + print constrainttorange(CONSTRAINT_LE, 0) + print constrainttorange(CONSTRAINT_GE, 0) + r1=intersectranges(constrainttorange(CONSTRAINT_LE, 0), ENTIRERANGE) + print intersectranges(r1, constrainttorange(CONSTRAINT_GE, 0)) + + print "----------------------" + data=[[3],[2],[1],[4],[5],[5]] + print "DATA:",data + ks1=kdtree(data) + print ks1.data + + print list(query(ks1)) +# print query(ks1,[(0,CONSTRAINT_GE),(0,CONSTRAINT_LT)], [3,5]) ] +# print [data[i] for i in query(ks1,[(0,CONSTRAINT_GE),(0,CONSTRAINT_LE)], [3,5]) ] +# print [data[i] for i in query(ks1,[(0,CONSTRAINT_GT),(0,CONSTRAINT_LT)], [3,3]) ] +# print 'q',[data[i] for i in query(ks1,[(0,CONSTRAINT_EQ)], [3]) ] + + data=[(5, 3), (5, 2), (5, 1), (2, 3), (2, 2), (2, 1)] + print "DATA:",data + ks1=kdtree(data,[1]) + print "TREE:",ks1.data + print list(query(ks1)) +# print [data[i] for i in query(ks1,[(0,CONSTRAINT_GE), (0,CONSTRAINT_LT)], [3,4])] +# print [data[i] for i in query(ks1,[(0,CONSTRAINT_GE), (1,CONSTRAINT_LT)], [3,4])] +# print [data[i] for i in query(ks1,[(0,CONSTRAINT_GE), (1,CONSTRAINT_LT)], [3,5])] + + #print list(query(ks1,[ (0,CONSTRAINT_GE),(1,CONSTRAINT_LE)], [3,4])) + print list(query(ks1,[ (1,CONSTRAINT_GE)], [2])) + + data=[[5]] + print "DATA:",data + ks1=kdtree(data) + print "TREE:",ks1.data + print list(query(ks1)) +# print [data[i] for i in query(ks1,[(0,CONSTRAINT_GE), (0,CONSTRAINT_LT)], [3,4])] +# print [data[i] for i in query(ks1,[(0,CONSTRAINT_GE), (1,CONSTRAINT_LT)], [3,4])] +# print [data[i] for i in query(ks1,[(0,CONSTRAINT_GE), (1,CONSTRAINT_LT)], [3,5])] + + #print list(query(ks1,[ (0,CONSTRAINT_GE),(1,CONSTRAINT_LE)], [3,4])) + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/listser.py b/interactive-mining-3rdparty-madis/madis/src/lib/listser.py new file mode 100644 index 0000000..3a4f23e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/listser.py @@ -0,0 +1,64 @@ +from types import IntType, TupleType, StringType, FloatType, LongType, ListType, DictType, NoneType, BooleanType, UnicodeType, ComplexType +SetType = type(set()) + +from struct import pack, unpack, unpack_from +from itertools import groupby + +stypes = { + LongType:"q", + IntType:"i", + FloatType:"d", + StringType:'', + NoneType:"f", + BooleanType:"?", + UnicodeType:'', +} + +NAN = pack('f',float('nan')) + +def dumps(l): + if type(l) != list: + raise ValueError, "Type not supported" + + st = ['='] + stappend = st.append + l1 = [] + l1extend = l1.extend + l1append = l1.append + for t,v in groupby(l, type): + if t is str: + for x in v: + l1append(x) + stappend(str(len(x))+'s') + elif t is unicode: + for x in v: + v1=x.encode('utf8') + l1append(v1) + stappend(str(len(v1))+'s') + elif t is NoneType: + lenv = 0 + for _ in v: + l1append(NAN) + lenv += 1 + stappend( str(lenv)+'f' if lenv>1 else 'f') + else: + lenv = 0 + f = stypes[t] + for x in v: + l1append(pack(f,x)) + lenv += 1 + stappend( str(lenv)+f if lenv>1 else f ) + + st = ''.join(st) + return pack('!I', len(st)) + st + ''.join(l1) + +def loads(s): + stp = unpack('!I', s[:4])[0] + 4 + return [None if x!=x else x for x in unpack_from(s[4:stp], s, stp)] + +if __name__ == "__main__": + #l1 = [1,3,4,"lala", "gaga", 5, "as" , None,None,u'asfdasdf', u'qwerqewr', 3,4,5,None, None, "LALAKIS"] + l1 = ['lal',3] + print l1 + a=dumps(l1) + print loads(a) \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/madcomp.py b/interactive-mining-3rdparty-madis/madis/src/lib/madcomp.py new file mode 100644 index 0000000..5924574 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/madcomp.py @@ -0,0 +1,306 @@ +import sys +from itertools import repeat, imap +import cPickle +import cStringIO +import struct +import zlib +import apsw +from array import array +import marshal +from itertools import izip , imap +import itertools +import cPickle as cPickle +import struct +import gc +import StringIO as StringIO +import cStringIO as cStringIO +import marshal +import zlib +from array import array +BLOCK_SIZE = 65536000 + +registered=True + +class Decompression: + + def __init__ (self): + self.blocknumber = 0 + + def decompressblock(self,inputblock): + import bz2 + try: + import msgpack + except ImportError: + import marshal as msgpack + serializer = msgpack + self.blocknumber += 1 + input = cStringIO.StringIO(inputblock) + if self.blocknumber == 1 : + # schema block + + b = struct.unpack('!B',input.read(1)) + if not b[0]: + self.schema = cPickle.load(input) + else : + raise error('Not a schema block!') + yield self.schema + + + colnum = len(self.schema) + while True: + try: + b = struct.unpack('!B', input.read(1)) + except: + break + if b[0]: + decompression = struct.unpack('!B', input.read(1)) + if decompression[0] : + decompress = zlib.decompress + else: + decompress = bz2.decompress + + type = '!'+'i'*(colnum*2+1) + ind = list(struct.unpack(type, input.read(4*(colnum*2+1)))) + if sum(ind)==0: # rowstore + s = serializer.loads(input.read()) + for rec in s: + yield rec + else: + cols = [None]*colnum + for c in xrange(colnum): + s = serializer.loads(decompress(input.read(ind[c*2]))) + if (len(s)>1 and ind[c*2+1]==0 and ind[colnum*2]>1): + cols[c] = s + else: + if len(s)==1: + tmp = s[0] + cols[c] = repeat(tmp, ind[colnum*2]) + elif len(s)<256: + cols[c] = imap(s.__getitem__, array('B', decompress(input.read(ind[c*2+1])))) + else: + cols[c] = imap(s.__getitem__, array('H', decompress(input.read(ind[c*2+1])))) + + iterators = tuple(map(iter, cols)) + ilen = len(cols) + res = [None] * ilen + + while True: + ci = 0 + try: + while ci < ilen: + res[ci] = iterators[ci].next() + ci += 1 + yield res + except: + break + elif not b[0]: + cPickle.load(input) + + + +class Compression: + + def __init__ (self,schema): + import bz2 + self.schema = schema + self.paxcols = [] + self.currentalgorithm = 'sdicc' + self.blocknumber = 0 + self.comprblocknumber = 0 + self.maxlevel = 7 + self.lencols = 0 + self.compressiondict = { + 0:('row',zlib.compress,0), + 1:('sdicc',zlib.compress,0), + 2:('sdicc',zlib.compress,1), + 3:('sdicc',zlib.compress,4), + 4:('sdicc',zlib.compress,5), + 5:('sdicc',zlib.compress,6), + 6:('sdicc',bz2.compress,1), + 7:('sdicc',bz2.compress,9) + } + + def getmaxlevel(self): + return self.maxlevel + + def reset(self,schema): + self.schema = schema + self.paxcols = [] + self.currentalgorithm = 'sdicc' + self.blocknumber = 0 + self.comprblocknumber = 0 + self.lencols = 0 + + + def setlevel(self,formatArgs): + + if formatArgs is not None and 'level' in formatArgs: + level = formatArgs['level'] + self.compress = self.compressiondict[level][1] + self.level = self.compressiondict[level][2] + if self.compressiondict[level][0] != self.currentalgorithm: + self.comprblocknumber = 0 + self.currentalgorithm = self.compressiondict[level][0] + else : + self.compress = zlib.compress + self.level = 1 + if self.currentalgorithm != 'sdicc': + self.currentalgorithm = 'sdicc' + self.currentalgorithm = 0 + + def getSize(self,v): + t = type(v) + + if t == unicode: + return 52 + 4*len(v) + + if t in (int, float, None): + return 24 + + return 37 + len(v) + + + def compress(self): + + output = StringIO.StringIO() + output.write(struct.pack('!B', 0)) + cPickle.dump(self.schema,output,1) + + formatArgs = {} + formatArgs = (yield) + exitGen = False + while not exitGen: + self.setlevel(formatArgs) + count = 0 + bsize = 0 + rows = [] + while bsize 0 : + formatArgs = yield self.sdicc(rows, count) + else : + formatArgs = yield output.getvalue()+self.sdicc(rows, count) + elif self.currentalgorithm == "row" : + if self.blocknumber > 0 : + formatArgs = yield self.row(rows, count) + else : + formatArgs = yield output.getvalue()+self.row(rows, count) + + + def row(self, diter, lencols): + try: + import msgpack + except ImportError: + import marshal as msgpack + import bz2 + serializer = msgpack + output = StringIO.StringIO() + colnum = len(self.schema) + output.truncate(0) + + output.write(struct.pack('!B', 1)) + output.write(struct.pack('!B', 0)) + headindex = [0 for _ in xrange((colnum*2)+1)] + type = '!'+'i'*len(headindex) + output.write(struct.pack(type, *headindex)) + output.write(serializer.dumps(diter)) + + return output.getvalue() + + + def sdicc(self, diter, lencols): + try: + import msgpack + except ImportError: + import marshal as msgpack + import bz2 + serializer = msgpack + output = StringIO.StringIO() + colnum = len(self.schema) + output.truncate(0) + + output.write(struct.pack('!B', 1)) + if self.compress == bz2.compress: + output.write(struct.pack('!B', 0)) + else: + output.write(struct.pack('!B', 1)) + + headindex = [0 for _ in xrange((colnum*2)+1)] + type = '!'+'i'*len(headindex) + output.write(struct.pack(type, *headindex)) + + for i, col in enumerate(([x[c] for x in diter] for c in xrange(colnum))): + + if self.blocknumber==0: + s = sorted(set(col)) + lens = len(s) + if lens>50*1.0*lencols/100: + self.paxcols.append(i) + l = output.tell() +# tempio.truncate(0) +# fastPickler.dump(col) + output.write(self.compress(serializer.dumps(col),self.level)) + headindex[i*2] = output.tell() - l + else: + coldict = dict(((x,y) for y,x in enumerate(s))) + l = output.tell() +# tempio.truncate(0) +# fastPickler.dump(s) + output.write(self.compress(serializer.dumps(s),self.level)) + headindex[i*2] = output.tell()-l + if lens>1: + if lens<256: + output.write(self.compress(array('B',[coldict[y] for y in col]).tostring(),self.level)) + else: + output.write(self.compress(array('H',[coldict[y] for y in col]).tostring(),self.level)) + headindex[i*2+1] = output.tell()-l-headindex[i*2] + else: + if i in self.paxcols: + l = output.tell() +# tempio.truncate(0) +# fastPickler.dump(col) + output.write(self.compress(serializer.dumps(col),self.level)) + headindex[i*2] = output.tell() - l + else: + s = sorted(set(col)) + lens = len(s) + coldict = dict(((x,y) for y,x in enumerate(s))) + l = output.tell() +# tempio.truncate(0) +# fastPickler.dump(s) + output.write(self.compress(serializer.dumps(s),self.level)) + headindex[i*2] = output.tell()-l + if lens>1: + if lens<256: + output.write(self.compress(array('B',[coldict[y] for y in col]).tostring(),self.level)) + else: + output.write(self.compress(array('H',[coldict[y] for y in col]).tostring(),self.level)) + headindex[i*2+1] = output.tell()-l-headindex[i*2] + + self.blocknumber=1 + headindex[colnum*2] = lencols + output.seek(0) + type = '!'+'i'*len(headindex) + output.write(struct.pack('!B', 1)) + if self.compress == bz2.compress: + output.write(struct.pack('!B', 0)) + else: + output.write(struct.pack('!B', 1)) + output.write(struct.pack(type, *headindex)) + return output.getvalue() + + + + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/memoize.py b/interactive-mining-3rdparty-madis/madis/src/lib/memoize.py new file mode 100644 index 0000000..beafee6 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/memoize.py @@ -0,0 +1,30 @@ +class memoize: + def __init__ (self, f): + self.f = f + self.cache = {} + def __call__ (self, *args, **kwargs): + if (args, str(kwargs)) in self.cache: + return self.cache[args, str(kwargs)] + else: + tmp = self.f(*args, **kwargs) + self.cache[args, str(kwargs)] = tmp + return tmp + def reset(self): + self.cache={} + +if __name__ == "__main__": + @memoize + def lala(a): + return a+5 + + lala(5) + print lala.cache + lala(15) + print lala.cache + lala(20) + print lala.cache + lala.reset() + print lala.cache + lala(5) + print lala.cache + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/__init__.py new file mode 100644 index 0000000..57de8e8 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/__init__.py @@ -0,0 +1,37 @@ +# vim: sw=4:expandtab:foldmethod=marker +# +# Copyright (c) 2007-2009, Mathieu Fenniak +# All rights reserved. +# +# 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. +# * The name of the author may not 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. + +__author__ = "Mathieu Fenniak" + +import dbapi as DBAPI +pg8000_dbapi = DBAPI + +from interface import * +from types import Bytea + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/dbapi.py b/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/dbapi.py new file mode 100644 index 0000000..401740d --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/dbapi.py @@ -0,0 +1,789 @@ +# vim: sw=4:expandtab:foldmethod=marker +# +# Copyright (c) 2007-2009, Mathieu Fenniak +# All rights reserved. +# +# 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. +# * The name of the author may not 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. + +__author__ = "Mathieu Fenniak" + +import datetime +import time +import interface +import types +import threading +from errors import * + +from warnings import warn + +## +# The DBAPI level supported. Currently 2.0. This property is part of the +# DBAPI 2.0 specification. +apilevel = "2.0" + +## +# Integer constant stating the level of thread safety the DBAPI interface +# supports. This DBAPI interface supports sharing of the module, connections, +# and cursors. This property is part of the DBAPI 2.0 specification. +threadsafety = 3 + +## +# String property stating the type of parameter marker formatting expected by +# the interface. This value defaults to "format". This property is part of +# the DBAPI 2.0 specification. +#

+# Unlike the DBAPI specification, this value is not constant. It can be +# changed to any standard paramstyle value (ie. qmark, numeric, named, format, +# and pyformat). +paramstyle = 'format' # paramstyle can be changed to any DB-API paramstyle + +def convert_paramstyle(src_style, query, args): + # I don't see any way to avoid scanning the query string char by char, + # so we might as well take that careful approach and create a + # state-based scanner. We'll use int variables for the state. + # 0 -- outside quoted string + # 1 -- inside single-quote string '...' + # 2 -- inside quoted identifier "..." + # 3 -- inside escaped single-quote string, E'...' + state = 0 + output_query = "" + output_args = [] + if src_style == "numeric": + output_args = args + elif src_style in ("pyformat", "named"): + mapping_to_idx = {} + i = 0 + while 1: + if i == len(query): + break + c = query[i] + # print "begin loop", repr(i), repr(c), repr(state) + if state == 0: + if c == "'": + i += 1 + output_query += c + state = 1 + elif c == '"': + i += 1 + output_query += c + state = 2 + elif c == 'E': + # check for escaped single-quote string + i += 1 + if i < len(query) and i > 1 and query[i] == "'": + i += 1 + output_query += "E'" + state = 3 + else: + output_query += c + elif src_style == "qmark" and c == "?": + i += 1 + param_idx = len(output_args) + if param_idx == len(args): + raise QueryParameterIndexError("too many parameter fields, not enough parameters") + output_args.append(args[param_idx]) + output_query += "$" + str(param_idx + 1) + elif src_style == "numeric" and c == ":": + i += 1 + if i < len(query) and i > 1 and query[i].isdigit(): + output_query += "$" + query[i] + i += 1 + else: + raise QueryParameterParseError("numeric parameter : does not have numeric arg") + elif src_style == "named" and c == ":": + name = "" + while 1: + i += 1 + if i == len(query): + break + c = query[i] + if c.isalnum() or c == '_': + name += c + else: + break + if name == "": + raise QueryParameterParseError("empty name of named parameter") + idx = mapping_to_idx.get(name) + if idx == None: + idx = len(output_args) + output_args.append(args[name]) + idx += 1 + mapping_to_idx[name] = idx + output_query += "$" + str(idx) + elif src_style == "format" and c == "%": + i += 1 + if i < len(query) and i > 1: + if query[i] == "s": + param_idx = len(output_args) + if param_idx == len(args): + raise QueryParameterIndexError("too many parameter fields, not enough parameters") + output_args.append(args[param_idx]) + output_query += "$" + str(param_idx + 1) + elif query[i] == "%": + output_query += "%" + else: + raise QueryParameterParseError("Only %s and %% are supported") + i += 1 + else: + raise QueryParameterParseError("format parameter % does not have format code") + elif src_style == "pyformat" and c == "%": + i += 1 + if i < len(query) and i > 1: + if query[i] == "(": + i += 1 + # begin mapping name + end_idx = query.find(')', i) + if end_idx == -1: + raise QueryParameterParseError("began pyformat dict read, but couldn't find end of name") + else: + name = query[i:end_idx] + i = end_idx + 1 + if i < len(query) and query[i] == "s": + i += 1 + idx = mapping_to_idx.get(name) + if idx == None: + idx = len(output_args) + output_args.append(args[name]) + idx += 1 + mapping_to_idx[name] = idx + output_query += "$" + str(idx) + else: + raise QueryParameterParseError("format not specified or not supported (only %(...)s supported)") + elif query[i] == "%": + output_query += "%" + elif query[i] == "s": + # we have a %s in a pyformat query string. Assume + # support for format instead. + i -= 1 + src_style = "format" + else: + raise QueryParameterParseError("Only %(name)s, %s and %% are supported") + else: + i += 1 + output_query += c + elif state == 1: + output_query += c + i += 1 + if c == "'": + # Could be a double '' + if i < len(query) and query[i] == "'": + # is a double quote. + output_query += query[i] + i += 1 + else: + state = 0 + elif src_style in ("pyformat","format") and c == "%": + # hm... we're only going to support an escaped percent sign + if i < len(query): + if query[i] == "%": + # good. We already output the first percent sign. + i += 1 + else: + raise QueryParameterParseError("'%" + query[i] + "' not supported in quoted string") + elif state == 2: + output_query += c + i += 1 + if c == '"': + state = 0 + elif src_style in ("pyformat","format") and c == "%": + # hm... we're only going to support an escaped percent sign + if i < len(query): + if query[i] == "%": + # good. We already output the first percent sign. + i += 1 + else: + raise QueryParameterParseError("'%" + query[i] + "' not supported in quoted string") + elif state == 3: + output_query += c + i += 1 + if c == "\\": + # check for escaped single-quote + if i < len(query) and query[i] == "'": + output_query += "'" + i += 1 + elif c == "'": + state = 0 + elif src_style in ("pyformat","format") and c == "%": + # hm... we're only going to support an escaped percent sign + if i < len(query): + if query[i] == "%": + # good. We already output the first percent sign. + i += 1 + else: + raise QueryParameterParseError("'%" + query[i] + "' not supported in quoted string") + + return output_query, tuple(output_args) + +def require_open_cursor(fn): + def _fn(self, *args, **kwargs): + if self.cursor == None: + raise CursorClosedError() + return fn(self, *args, **kwargs) + return _fn + +## +# The class of object returned by the {@link #ConnectionWrapper.cursor cursor method}. +class CursorWrapper(object): + def __init__(self, conn, connection): + self.cursor = interface.Cursor(conn) + self.arraysize = 1 + self._connection = connection + self._override_rowcount = None + + ## + # This read-only attribute returns a reference to the connection object on + # which the cursor was created. + #

+ # Stability: Part of a DBAPI 2.0 extension. A warning "DB-API extension + # cursor.connection used" will be fired. + connection = property(lambda self: self._getConnection()) + + def _getConnection(self): + warn("DB-API extension cursor.connection used", stacklevel=3) + return self._connection + + ## + # This read-only attribute specifies the number of rows that the last + # .execute*() produced (for DQL statements like 'select') or affected (for + # DML statements like 'update' or 'insert'). + #

+ # The attribute is -1 in case no .execute*() has been performed on the + # cursor or the rowcount of the last operation is cannot be determined by + # the interface. + #

+ # Stability: Part of the DBAPI 2.0 specification. + rowcount = property(lambda self: self._getRowCount()) + + @require_open_cursor + def _getRowCount(self): + if self._override_rowcount != None: + return self._override_rowcount + return self.cursor.row_count + + ## + # This read-only attribute is a sequence of 7-item sequences. Each value + # contains information describing one result column. The 7 items returned + # for each column are (name, type_code, display_size, internal_size, + # precision, scale, null_ok). Only the first two values are provided by + # this interface implementation. + #

+ # Stability: Part of the DBAPI 2.0 specification. + description = property(lambda self: self._getDescription()) + + @require_open_cursor + def _getDescription(self): + if self.cursor.row_description == None: + return None + columns = [] + for col in self.cursor.row_description: + columns.append((col["name"], col["type_oid"], None, None, None, None, None)) + return columns + + ## + # Executes a database operation. Parameters may be provided as a sequence + # or mapping and will be bound to variables in the operation. + #

+ # Stability: Part of the DBAPI 2.0 specification. + @require_open_cursor + def execute(self, operation, args=()): + if not self._connection.in_transaction: + self._connection.begin() + self._override_rowcount = None + self._execute(operation, args) + + def _execute(self, operation, args=()): + new_query, new_args = convert_paramstyle(paramstyle, operation, args) + try: + self.cursor.execute(new_query, *new_args) + except ConnectionClosedError: + # can't rollback in this case + raise + except: + # any error will rollback the transaction to-date + self._connection.rollback() + raise + + def copy_from(self, fileobj, table=None, sep='\t', null=None, query=None): + if query == None: + if table == None: + raise CopyQueryOrTableRequiredError() + query = "COPY %s FROM stdout DELIMITER '%s'" % (table, sep) + if null is not None: + query += " NULL '%s'" % (null,) + self.copy_execute(fileobj, query) + + def copy_to(self, fileobj, table=None, sep='\t', null=None, query=None): + if query == None: + if table == None: + raise CopyQueryOrTableRequiredError() + query = "COPY %s TO stdout DELIMITER '%s'" % (table, sep) + if null is not None: + query += " NULL '%s'" % (null,) + self.copy_execute(fileobj, query) + + @require_open_cursor + def copy_execute(self, fileobj, query): + try: + self.cursor.execute(query, stream=fileobj) + except ConnectionClosedError: + # can't rollback in this case + raise + except: + # any error will rollback the transaction to-date + import traceback; traceback.print_exc() + self._connection.rollback() + raise + + ## + # Prepare a database operation and then execute it against all parameter + # sequences or mappings provided. + #

+ # Stability: Part of the DBAPI 2.0 specification. + @require_open_cursor + def executemany(self, operation, parameter_sets): + if not self._connection.in_transaction: + self._connection.begin() + self._override_rowcount = 0 + for parameters in parameter_sets: + self._execute(operation, parameters) + if self.cursor.row_count == -1 or self._override_rowcount == -1: + self._override_rowcount = -1 + else: + self._override_rowcount += self.cursor.row_count + + ## + # Fetch the next row of a query result set, returning a single sequence, or + # None when no more data is available. + #

+ # Stability: Part of the DBAPI 2.0 specification. + @require_open_cursor + def fetchone(self): + return self.cursor.read_tuple() + + ## + # Fetch the next set of rows of a query result, returning a sequence of + # sequences. An empty sequence is returned when no more rows are + # available. + #

+ # Stability: Part of the DBAPI 2.0 specification. + # @param size The number of rows to fetch when called. If not provided, + # the arraysize property value is used instead. + def fetchmany(self, size=None): + if size == None: + size = self.arraysize + rows = [] + for i in range(size): + value = self.fetchone() + if value == None: + break + rows.append(value) + return rows + + ## + # Fetch all remaining rows of a query result, returning them as a sequence + # of sequences. + #

+ # Stability: Part of the DBAPI 2.0 specification. + @require_open_cursor + def fetchall(self): + return tuple(self.cursor.iterate_tuple()) + + ## + # Close the cursor. + #

+ # Stability: Part of the DBAPI 2.0 specification. + @require_open_cursor + def close(self): + self.cursor.close() + self.cursor = None + self._override_rowcount = None + + def next(self): + warn("DB-API extension cursor.next() used", stacklevel=2) + retval = self.fetchone() + if retval == None: + raise StopIteration() + return retval + + def __iter__(self): + warn("DB-API extension cursor.__iter__() used", stacklevel=2) + return self + + def setinputsizes(self, sizes): + pass + + def setoutputsize(self, size, column=None): + pass + + @require_open_cursor + def fileno(self): + return self.cursor.fileno() + + @require_open_cursor + def isready(self): + return self.cursor.isready() + +def require_open_connection(fn): + def _fn(self, *args, **kwargs): + if self.conn == None: + raise ConnectionClosedError() + return fn(self, *args, **kwargs) + return _fn + +## +# The class of object returned by the {@link #connect connect method}. +class ConnectionWrapper(object): + # DBAPI Extension: supply exceptions as attributes on the connection + Warning = property(lambda self: self._getError(Warning)) + Error = property(lambda self: self._getError(Error)) + InterfaceError = property(lambda self: self._getError(InterfaceError)) + DatabaseError = property(lambda self: self._getError(DatabaseError)) + OperationalError = property(lambda self: self._getError(OperationalError)) + IntegrityError = property(lambda self: self._getError(IntegrityError)) + InternalError = property(lambda self: self._getError(InternalError)) + ProgrammingError = property(lambda self: self._getError(ProgrammingError)) + NotSupportedError = property(lambda self: self._getError(NotSupportedError)) + + def _getError(self, error): + warn("DB-API extension connection.%s used" % error.__name__, stacklevel=3) + return error + + @property + def in_transaction(self): + if self.conn: + return self.conn.in_transaction + return False + + def __init__(self, **kwargs): + self.conn = interface.Connection(**kwargs) + self.notifies = [] + self.notifies_lock = threading.Lock() + self.conn.NotificationReceived += self._notificationReceived + # Two Phase Commit internal attributes: + self.__tpc_xid = None + self.__tpc_prepared = None + + def set_autocommit(self, state): + if self.conn.in_transaction and state and not self.conn.autocommit: + warn("enabling autocommit in an open transaction!") + self.conn.autocommit = state + + def get_autocommit(self): + return self.conn.autocommit + + autocommit = property(get_autocommit, set_autocommit) + + @require_open_connection + def begin(self): + self.conn.begin() + + def _notificationReceived(self, notice): + try: + # psycopg2 compatible notification interface + self.notifies_lock.acquire() + self.notifies.append((notice.backend_pid, notice.condition)) + finally: + self.notifies_lock.release() + + ## + # Creates a {@link #CursorWrapper CursorWrapper} object bound to this + # connection. + #

+ # Stability: Part of the DBAPI 2.0 specification. + @require_open_connection + def cursor(self): + return CursorWrapper(self.conn, self) + + ## + # Commits the current database transaction. + #

+ # Stability: Part of the DBAPI 2.0 specification. + @require_open_connection + def commit(self): + # There's a threading bug here. If a query is sent after the + # commit, but before the begin, it will be executed immediately + # without a surrounding transaction. Like all threading bugs -- it + # sounds unlikely, until it happens every time in one + # application... however, to fix this, we need to lock the + # database connection entirely, so that no cursors can execute + # statements on other threads. Support for that type of lock will + # be done later. + if self.__tpc_xid: + raise ProgrammingError("Cannot do a normal commit() inside a " + "TPC transaction!") + self.conn.commit() + + ## + # Rolls back the current database transaction. + #

+ # Stability: Part of the DBAPI 2.0 specification. + @require_open_connection + def rollback(self): + # see bug description in commit. + if self.__tpc_xid: + raise ProgrammingError("Cannot do a normal rollback() inside a " + "TPC transaction!") + self.conn.rollback() + + ## + # Closes the database connection. + #

+ # Stability: Part of the DBAPI 2.0 specification. + @require_open_connection + def close(self): + self.conn.close() + self.conn = None + + ## + # Returns the "server_version" string provided by the connected server. + #

+ # Stability: Extension of the DBAPI 2.0 specification. + @property + @require_open_connection + def server_version(self): + return self.conn.server_version() + + + def xid(self,format_id, global_transaction_id, branch_qualifier): + """Create a Transaction IDs (only global_transaction_id is used in pg) + format_id and branch_qualifier are not used in postgres + global_transaction_id may be any string identifier supported by postgres + returns a tuple (format_id, global_transaction_id, branch_qualifier)""" + return (format_id, global_transaction_id, branch_qualifier) + + @require_open_connection + def tpc_begin(self,xid): + "Begin a two-phase transaction" + # set auto-commit mode to begin a TPC transaction + self.autocommit = False + # (actually in postgres at this point it is a normal one) + if self.conn.in_transaction: + warn("tpc_begin() should be called outside a transaction block", + stacklevel=3) + self.conn.begin() + # store actual TPC transaction id + self.__tpc_xid = xid + self.__tpc_prepared = False + + @require_open_connection + def tpc_prepare(self): + "Prepare a two-phase transaction" + if not self.__tpc_xid: + raise ProgrammingError("tpc_prepare() outside a TPC transaction " + "is not allowed!") + # Prepare the TPC + curs = self.cursor() + try: + curs.execute("PREPARE TRANSACTION '%s';" % (self.__tpc_xid[1],)) + self.conn.in_transaction = False + self.__tpc_prepared = True + finally: + curs.close() + + @require_open_connection + def tpc_commit(self, xid=None): + "Commit a prepared two-phase transaction" + try: + # save current autocommit status (to be recovered later) + previous_autocommit_mode = self.autocommit + if not xid: + # use current tpc transaction + tpc_xid = self.__tpc_xid + else: + # use a recovered tpc transaction + tpc_xid = xid + if not xid in self.tpc_recover(): + raise ProgrammingError("Requested TPC transaction is not " + "prepared!") + if not tpc_xid: + raise ProgrammingError("Cannot tpc_commit() without a TPC " + "transaction!") + if self.__tpc_prepared or (xid != self.__tpc_xid and xid): + # a two-phase commit: + # set the auto-commit mode for TPC commit + self.autocommit = True + curs = self.cursor() + try: + curs.execute("COMMIT PREPARED '%s';" % (tpc_xid[1],)) + finally: + curs.close() + # return to previous auto-commit mode + self.autocommit = previous_autocommit_mode + else: + try: + # a single-phase commit + self.conn.commit() + finally: + # return to previous auto-commit mode + self.autocommit = previous_autocommit_mode + finally: + # transaction is done, clear xid + self.__tpc_xid = None + + @require_open_connection + def tpc_rollback(self, xid=None): + "Commit a prepared two-phase transaction" + try: + # save current autocommit status (to be recovered later) + previous_autocommit_mode = self.autocommit + if not xid: + # use current tpc transaction + tpc_xid = self.__tpc_xid + else: + # use a recovered tpc transaction + tpc_xid = xid + if not xid in self.tpc_recover(): + raise ProgrammingError("Requested TPC transaction is not prepared!") + if not tpc_xid: + raise ProgrammingError("Cannot tpc_rollback() without a TPC prepared transaction!") + if self.__tpc_prepared or (xid != self.__tpc_xid and xid): + # a two-phase rollback + # set auto-commit for the TPC rollback + self.autocommit = True + curs = self.cursor() + try: + curs.execute("ROLLBACK PREPARED '%s';" % (tpc_xid[1],)) + finally: + curs.close() + # return to previous auto-commit mode + self.autocommit = previous_autocommit_mode + else: + # a single-phase rollback + try: + self.conn.rollback() + finally: + # return to previous auto-commit mode + self.autocommit = previous_autocommit_mode + finally: + # transaction is done, clear xid + self.__tpc_xid = None + + @require_open_connection + def tpc_recover(self): + "Returns a list of pending transaction IDs" + previous_autocommit_mode = self.autocommit + if not self.conn.in_transaction and not self.autocommit: + self.autocommit = True + elif not self.autocommit: + warn("tpc_recover() will open a transaction block", stacklevel=3) + + curs = self.cursor() + xids = [] + try: + # query system view that stores open (prepared) TPC transactions + curs.execute("SELECT gid FROM pg_prepared_xacts;"); + xids.extend([self.xid(0,row[0],'') for row in curs]) + finally: + curs.close() + # return to previous auto-commit mode + self.autocommit = previous_autocommit_mode + # return a list of TPC transaction ids (xid) + return xids + + +## +# Creates a DBAPI 2.0 compatible interface to a PostgreSQL database. +#

+# Stability: Part of the DBAPI 2.0 specification. +# +# @param user The username to connect to the PostgreSQL server with. This +# parameter is required. +# +# @keyparam host The hostname of the PostgreSQL server to connect with. +# Providing this parameter is necessary for TCP/IP connections. One of either +# host, or unix_sock, must be provided. +# +# @keyparam unix_sock The path to the UNIX socket to access the database +# through, for example, '/tmp/.s.PGSQL.5432'. One of either unix_sock or host +# must be provided. The port parameter will have no affect if unix_sock is +# provided. +# +# @keyparam port The TCP/IP port of the PostgreSQL server instance. This +# parameter defaults to 5432, the registered and common port of PostgreSQL +# TCP/IP servers. +# +# @keyparam database The name of the database instance to connect with. This +# parameter is optional, if omitted the PostgreSQL server will assume the +# database name is the same as the username. +# +# @keyparam password The user password to connect to the server with. This +# parameter is optional. If omitted, and the database server requests password +# based authentication, the connection will fail. On the other hand, if this +# parameter is provided and the database does not request password +# authentication, then the password will not be used. +# +# @keyparam socket_timeout Socket connect timeout measured in seconds. +# Defaults to 60 seconds. +# +# @keyparam ssl Use SSL encryption for TCP/IP socket. Defaults to False. +# +# @return An instance of {@link #ConnectionWrapper ConnectionWrapper}. +def connect(user, host=None, unix_sock=None, port=5432, database=None, password=None, socket_timeout=60, ssl=False): + return ConnectionWrapper(user=user, host=host, + unix_sock=unix_sock, port=port, database=database, + password=password, socket_timeout=socket_timeout, ssl=ssl) + +def Date(year, month, day): + return datetime.date(year, month, day) + +def Time(hour, minute, second): + return datetime.time(hour, minute, second) + +def Timestamp(year, month, day, hour, minute, second): + return datetime.datetime(year, month, day, hour, minute, second) + +def DateFromTicks(ticks): + return Date(*time.localtime(ticks)[:3]) + +def TimeFromTicks(ticks): + return Time(*time.localtime(ticks)[3:6]) + +def TimestampFromTicks(ticks): + return Timestamp(*time.localtime(ticks)[:6]) + +## +# Construct an object holding binary data. +def Binary(value): + return types.Bytea(value) + +# I have no idea what this would be used for by a client app. Should it be +# TEXT, VARCHAR, CHAR? It will only compare against row_description's +# type_code if it is this one type. It is the varchar type oid for now, this +# appears to match expectations in the DB API 2.0 compliance test suite. +STRING = 1043 + +# bytea type_oid +BINARY = 17 + +# numeric type_oid +NUMBER = 1700 + +# timestamp type_oid +DATETIME = 1114 + +# oid type_oid +ROWID = 26 + + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/errors.py b/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/errors.py new file mode 100644 index 0000000..b8b5acf --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/errors.py @@ -0,0 +1,115 @@ +# vim: sw=4:expandtab:foldmethod=marker +# +# Copyright (c) 2007-2009, Mathieu Fenniak +# All rights reserved. +# +# 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. +# * The name of the author may not 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. + +__author__ = "Mathieu Fenniak" + +class Warning(StandardError): + pass + +class Error(StandardError): + pass + +class InterfaceError(Error): + pass + +class ConnectionClosedError(InterfaceError): + def __init__(self): + InterfaceError.__init__(self, "connection is closed") + +class CursorClosedError(InterfaceError): + def __init__(self): + InterfaceError.__init__(self, "cursor is closed") + +class DatabaseError(Error): + pass + +class DataError(DatabaseError): + pass + +class OperationalError(DatabaseError): + pass + +class IntegrityError(DatabaseError): + pass + +class InternalError(DatabaseError): + pass + +class ProgrammingError(DatabaseError): + pass + +class NotSupportedError(DatabaseError): + pass + +## +# An exception that is thrown when an internal error occurs trying to +# decode binary array data from the server. +class ArrayDataParseError(InternalError): + pass + +## +# Thrown when attempting to transmit an array of unsupported data types. +class ArrayContentNotSupportedError(NotSupportedError): + pass + +## +# Thrown when attempting to send an array that doesn't contain all the same +# type of objects (eg. some floats, some ints). +class ArrayContentNotHomogenousError(ProgrammingError): + pass + +## +# Attempted to pass an empty array in, but it's not possible to determine the +# data type for an empty array. +class ArrayContentEmptyError(ProgrammingError): + pass + +## +# Attempted to use a multidimensional array with inconsistent array sizes. +class ArrayDimensionsNotConsistentError(ProgrammingError): + pass + +# A cursor's copy_to or copy_from argument was not provided a table or query +# to operate on. +class CopyQueryOrTableRequiredError(ProgrammingError): + pass + +# Raised if a COPY query is executed without using copy_to or copy_from +# functions to provide a data stream. +class CopyQueryWithoutStreamError(ProgrammingError): + pass + +# When query parameters don't match up with query args. +class QueryParameterIndexError(ProgrammingError): + pass + +# Some sort of parse error occured during query parameterization. +class QueryParameterParseError(ProgrammingError): + pass + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/interface.py b/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/interface.py new file mode 100644 index 0000000..7f0bf01 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/interface.py @@ -0,0 +1,552 @@ +# vim: sw=4:expandtab:foldmethod=marker +# +# Copyright (c) 2007-2009, Mathieu Fenniak +# All rights reserved. +# +# 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. +# * The name of the author may not 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. + +__author__ = "Mathieu Fenniak" + +import socket +import protocol +import threading +from errors import * + +class DataIterator(object): + def __init__(self, obj, func): + self.obj = obj + self.func = func + + def __iter__(self): + return self + + def next(self): + retval = self.func(self.obj) + if retval == None: + raise StopIteration() + return retval + +statement_number_lock = threading.Lock() +statement_number = 0 + +## +# This class represents a prepared statement. A prepared statement is +# pre-parsed on the server, which reduces the need to parse the query every +# time it is run. The statement can have parameters in the form of $1, $2, $3, +# etc. When parameters are used, the types of the parameters need to be +# specified when creating the prepared statement. +#

+# As of v1.01, instances of this class are thread-safe. This means that a +# single PreparedStatement can be accessed by multiple threads without the +# internal consistency of the statement being altered. However, the +# responsibility is on the client application to ensure that one thread reading +# from a statement isn't affected by another thread starting a new query with +# the same statement. +#

+# Stability: Added in v1.00, stability guaranteed for v1.xx. +# +# @param connection An instance of {@link Connection Connection}. +# +# @param statement The SQL statement to be represented, often containing +# parameters in the form of $1, $2, $3, etc. +# +# @param types Python type objects for each parameter in the SQL +# statement. For example, int, float, str. +class PreparedStatement(object): + + ## + # Determines the number of rows to read from the database server at once. + # Reading more rows increases performance at the cost of memory. The + # default value is 100 rows. The affect of this parameter is transparent. + # That is, the library reads more rows when the cache is empty + # automatically. + #

+ # Stability: Added in v1.00, stability guaranteed for v1.xx. It is + # possible that implementation changes in the future could cause this + # parameter to be ignored. + row_cache_size = 100 + + def __init__(self, connection, statement, *types, **kwargs): + global statement_number + if connection == None or connection.c == None: + raise InterfaceError("connection not provided") + try: + statement_number_lock.acquire() + self._statement_number = statement_number + statement_number += 1 + finally: + statement_number_lock.release() + self.c = connection.c + self._portal_name = None + self._statement_name = kwargs.get("statement_name", "pg8000_statement_%s" % self._statement_number) + self._row_desc = None + self._cached_rows = [] + self._ongoing_row_count = 0 + self._command_complete = True + self._parse_row_desc = self.c.parse(self._statement_name, statement, types) + self._lock = threading.RLock() + + def close(self): + if self._statement_name != "": # don't close unnamed statement + self.c.close_statement(self._statement_name) + if self._portal_name != None: + self.c.close_portal(self._portal_name) + self._portal_name = None + + row_description = property(lambda self: self._getRowDescription()) + def _getRowDescription(self): + if self._row_desc == None: + return None + return self._row_desc.fields + + ## + # Run the SQL prepared statement with the given parameters. + #

+ # Stability: Added in v1.00, stability guaranteed for v1.xx. + def execute(self, *args, **kwargs): + self._lock.acquire() + try: + if not self._command_complete: + # cleanup last execute + self._cached_rows = [] + self._ongoing_row_count = 0 + if self._portal_name != None: + self.c.close_portal(self._portal_name) + self._command_complete = False + self._portal_name = "pg8000_portal_%s" % self._statement_number + self._row_desc, cmd = self.c.bind(self._portal_name, self._statement_name, args, self._parse_row_desc, kwargs.get("stream")) + if self._row_desc: + # We execute our cursor right away to fill up our cache. This + # prevents the cursor from being destroyed, apparently, by a rogue + # Sync between Bind and Execute. Since it is quite likely that + # data will be read from us right away anyways, this seems a safe + # move for now. + self._fill_cache() + else: + self._command_complete = True + self._ongoing_row_count = -1 + if cmd != None and cmd.rows != None: + self._ongoing_row_count = cmd.rows + finally: + self._lock.release() + + def _fill_cache(self): + self._lock.acquire() + try: + if self._cached_rows: + raise InternalError("attempt to fill cache that isn't empty") + end_of_data, rows = self.c.fetch_rows(self._portal_name, self.row_cache_size, self._row_desc) + self._cached_rows = rows + if end_of_data: + self._command_complete = True + finally: + self._lock.release() + + def _fetch(self): + if not self._row_desc: + raise ProgrammingError("no result set") + self._lock.acquire() + try: + if not self._cached_rows: + if self._command_complete: + return None + self._fill_cache() + if self._command_complete and not self._cached_rows: + # fill cache tells us the command is complete, but yet we have + # no rows after filling our cache. This is a special case when + # a query returns no rows. + return None + row = self._cached_rows.pop(0) + self._ongoing_row_count += 1 + return tuple(row) + finally: + self._lock.release() + + ## + # Return a count of the number of rows relevant to the executed statement. + # For a SELECT, this is the number of rows returned. For UPDATE or DELETE, + # this the number of rows affected. For INSERT, the number of rows + # inserted. This property may have a value of -1 to indicate that there + # was no row count. + #

+ # During a result-set query (eg. SELECT, or INSERT ... RETURNING ...), + # accessing this property requires reading the entire result-set into + # memory, as reading the data to completion is the only way to determine + # the total number of rows. Avoid using this property in with + # result-set queries, as it may cause unexpected memory usage. + #

+ # Stability: Added in v1.03, stability guaranteed for v1.xx. + row_count = property(lambda self: self._get_row_count()) + def _get_row_count(self): + self._lock.acquire() + try: + if not self._command_complete: + end_of_data, rows = self.c.fetch_rows(self._portal_name, 0, self._row_desc) + self._cached_rows += rows + if end_of_data: + self._command_complete = True + else: + raise InternalError("fetch_rows(0) did not hit end of data") + return self._ongoing_row_count + len(self._cached_rows) + finally: + self._lock.release() + + ## + # Read a row from the database server, and return it in a dictionary + # indexed by column name/alias. This method will raise an error if two + # columns have the same name. Returns None after the last row. + #

+ # Stability: Added in v1.00, stability guaranteed for v1.xx. + def read_dict(self): + row = self._fetch() + if row == None: + return row + retval = {} + for i in range(len(self._row_desc.fields)): + col_name = self._row_desc.fields[i]['name'] + if retval.has_key(col_name): + raise InterfaceError("cannot return dict of row when two columns have the same name (%r)" % (col_name,)) + retval[col_name] = row[i] + return retval + + ## + # Read a row from the database server, and return it as a tuple of values. + # Returns None after the last row. + #

+ # Stability: Added in v1.00, stability guaranteed for v1.xx. + def read_tuple(self): + return self._fetch() + + ## + # Return an iterator for the output of this statement. The iterator will + # return a tuple for each row, in the same manner as {@link + # #PreparedStatement.read_tuple read_tuple}. + #

+ # Stability: Added in v1.00, stability guaranteed for v1.xx. + def iterate_tuple(self): + return DataIterator(self, PreparedStatement.read_tuple) + + ## + # Return an iterator for the output of this statement. The iterator will + # return a dict for each row, in the same manner as {@link + # #PreparedStatement.read_dict read_dict}. + #

+ # Stability: Added in v1.00, stability guaranteed for v1.xx. + def iterate_dict(self): + return DataIterator(self, PreparedStatement.read_dict) + +## +# The Cursor class allows multiple queries to be performed concurrently with a +# single PostgreSQL connection. The Cursor object is implemented internally by +# using a {@link PreparedStatement PreparedStatement} object, so if you plan to +# use a statement multiple times, you might as well create a PreparedStatement +# and save a small amount of reparsing time. +#

+# As of v1.01, instances of this class are thread-safe. See {@link +# PreparedStatement PreparedStatement} for more information. +#

+# Stability: Added in v1.00, stability guaranteed for v1.xx. +# +# @param connection An instance of {@link Connection Connection}. +class Cursor(object): + def __init__(self, connection): + self.connection = connection + self._stmt = None + + def require_stmt(func): + def retval(self, *args, **kwargs): + if self._stmt == None: + raise ProgrammingError("attempting to use unexecuted cursor") + return func(self, *args, **kwargs) + return retval + + row_description = property(lambda self: self._getRowDescription()) + def _getRowDescription(self): + if self._stmt == None: + return None + return self._stmt.row_description + + ## + # Run an SQL statement using this cursor. The SQL statement can have + # parameters in the form of $1, $2, $3, etc., which will be filled in by + # the additional arguments passed to this function. + #

+ # Stability: Added in v1.00, stability guaranteed for v1.xx. + # @param query The SQL statement to execute. + def execute(self, query, *args, **kwargs): + if self.connection.is_closed: + raise ConnectionClosedError() + self.connection._unnamed_prepared_statement_lock.acquire() + try: + self._stmt = PreparedStatement(self.connection, query, statement_name="", *[{"type": type(x), "value": x} for x in args]) + self._stmt.execute(*args, **kwargs) + finally: + self.connection._unnamed_prepared_statement_lock.release() + + ## + # Return a count of the number of rows currently being read. If possible, + # please avoid using this function. It requires reading the entire result + # set from the database to determine the number of rows being returned. + #

+ # Stability: Added in v1.03, stability guaranteed for v1.xx. + # Implementation currently requires caching entire result set into memory, + # avoid using this property. + row_count = property(lambda self: self._get_row_count()) + + @require_stmt + def _get_row_count(self): + return self._stmt.row_count + + ## + # Read a row from the database server, and return it in a dictionary + # indexed by column name/alias. This method will raise an error if two + # columns have the same name. Returns None after the last row. + #

+ # Stability: Added in v1.00, stability guaranteed for v1.xx. + @require_stmt + def read_dict(self): + return self._stmt.read_dict() + + ## + # Read a row from the database server, and return it as a tuple of values. + # Returns None after the last row. + #

+ # Stability: Added in v1.00, stability guaranteed for v1.xx. + @require_stmt + def read_tuple(self): + return self._stmt.read_tuple() + + ## + # Return an iterator for the output of this statement. The iterator will + # return a tuple for each row, in the same manner as {@link + # #PreparedStatement.read_tuple read_tuple}. + #

+ # Stability: Added in v1.00, stability guaranteed for v1.xx. + @require_stmt + def iterate_tuple(self): + return self._stmt.iterate_tuple() + + ## + # Return an iterator for the output of this statement. The iterator will + # return a dict for each row, in the same manner as {@link + # #PreparedStatement.read_dict read_dict}. + #

+ # Stability: Added in v1.00, stability guaranteed for v1.xx. + @require_stmt + def iterate_dict(self): + return self._stmt.iterate_dict() + + def close(self): + if self._stmt != None: + self._stmt.close() + self._stmt = None + + + ## + # Return the fileno of the underlying socket for this cursor's connection. + #

+ # Stability: Added in v1.07, stability guaranteed for v1.xx. + def fileno(self): + return self.connection.fileno() + + ## + # Poll the underlying socket for this cursor and sync if there is data waiting + # to be read. This has the effect of flushing asynchronous messages from the + # backend. Returns True if messages were read, False otherwise. + #

+ # Stability: Added in v1.07, stability guaranteed for v1.xx. + def isready(self): + return self.connection.isready() + + +## +# This class represents a connection to a PostgreSQL database. +#

+# The database connection is derived from the {@link #Cursor Cursor} class, +# which provides a default cursor for running queries. It also provides +# transaction control via the 'begin', 'commit', and 'rollback' methods. +# Without beginning a transaction explicitly, all statements will autocommit to +# the database. +#

+# As of v1.01, instances of this class are thread-safe. See {@link +# PreparedStatement PreparedStatement} for more information. +#

+# Stability: Added in v1.00, stability guaranteed for v1.xx. +# +# @param user The username to connect to the PostgreSQL server with. This +# parameter is required. +# +# @keyparam host The hostname of the PostgreSQL server to connect with. +# Providing this parameter is necessary for TCP/IP connections. One of either +# host, or unix_sock, must be provided. +# +# @keyparam unix_sock The path to the UNIX socket to access the database +# through, for example, '/tmp/.s.PGSQL.5432'. One of either unix_sock or host +# must be provided. The port parameter will have no affect if unix_sock is +# provided. +# +# @keyparam port The TCP/IP port of the PostgreSQL server instance. This +# parameter defaults to 5432, the registered and common port of PostgreSQL +# TCP/IP servers. +# +# @keyparam database The name of the database instance to connect with. This +# parameter is optional, if omitted the PostgreSQL server will assume the +# database name is the same as the username. +# +# @keyparam password The user password to connect to the server with. This +# parameter is optional. If omitted, and the database server requests password +# based authentication, the connection will fail. On the other hand, if this +# parameter is provided and the database does not request password +# authentication, then the password will not be used. +# +# @keyparam socket_timeout Socket connect timeout measured in seconds. +# Defaults to 60 seconds. +# +# @keyparam ssl Use SSL encryption for TCP/IP socket. Defaults to False. +class Connection(Cursor): + def __init__(self, user, host=None, unix_sock=None, port=5432, database=None, password=None, socket_timeout=60, ssl=False): + self._row_desc = None + try: + self.c = protocol.Connection(unix_sock=unix_sock, host=host, port=port, socket_timeout=socket_timeout, ssl=ssl) + self.c.authenticate(user, password=password, database=database) + except socket.error, e: + raise InterfaceError("communication error", e) + Cursor.__init__(self, self) + self._begin = PreparedStatement(self, "BEGIN TRANSACTION") + self._commit = PreparedStatement(self, "COMMIT TRANSACTION") + self._rollback = PreparedStatement(self, "ROLLBACK TRANSACTION") + self._unnamed_prepared_statement_lock = threading.RLock() + self.in_transaction = False + self.autocommit = False + + ## + # An event handler that is fired when NOTIFY occurs for a notification that + # has been LISTEN'd for. The value of this property is a + # util.MulticastDelegate. A callback can be added by using + # connection.NotificationReceived += SomeMethod. The method will be called + # with a single argument, an object that has properties: backend_pid, + # condition, and additional_info. Callbacks can be removed with the -= + # operator. + #

+ # Stability: Added in v1.03, stability guaranteed for v1.xx. + NotificationReceived = property( + lambda self: getattr(self.c, "NotificationReceived"), + lambda self, value: setattr(self.c, "NotificationReceived", value) + ) + + ## + # An event handler that is fired when the database server issues a notice. + # The value of this property is a util.MulticastDelegate. A callback can + # be added by using connection.NotificationReceived += SomeMethod. The + # method will be called with a single argument, an object that has + # properties: severity, code, msg, and possibly others (detail, hint, + # position, where, file, line, and routine). Callbacks can be removed with + # the -= operator. + #

+ # Stability: Added in v1.03, stability guaranteed for v1.xx. + NoticeReceived = property( + lambda self: getattr(self.c, "NoticeReceived"), + lambda self, value: setattr(self.c, "NoticeReceived", value) + ) + + ## + # An event handler that is fired when a runtime configuration option is + # changed on the server. The value of this property is a + # util.MulticastDelegate. A callback can be added by using + # connection.NotificationReceived += SomeMethod. Callbacks can be removed + # with the -= operator. The method will be called with a single argument, + # an object that has properties "key" and "value". + #

+ # Stability: Added in v1.03, stability guaranteed for v1.xx. + ParameterStatusReceived = property( + lambda self: getattr(self.c, "ParameterStatusReceived"), + lambda self, value: setattr(self.c, "ParameterStatusReceived", value) + ) + + ## + # Begins a new transaction. + #

+ # Stability: Added in v1.00, stability guaranteed for v1.xx. + def begin(self): + if self.is_closed: + raise ConnectionClosedError() + if self.autocommit: + return + self._begin.execute() + self.in_transaction = True + + + ## + # Commits the running transaction. + #

+ # Stability: Added in v1.00, stability guaranteed for v1.xx. + def commit(self): + if self.is_closed: + raise ConnectionClosedError() + self._commit.execute() + self.in_transaction = False + + ## + # Rolls back the running transaction. + #

+ # Stability: Added in v1.00, stability guaranteed for v1.xx. + def rollback(self): + if self.is_closed: + raise ConnectionClosedError() + self._rollback.execute() + self.in_transaction = False + + ## + # Closes an open connection. + def close(self): + if self.is_closed: + raise ConnectionClosedError() + self.c.close() + self.c = None + + is_closed = property(lambda self: self.c == None) + + ## + # Return the fileno of the underlying socket for this connection. + #

+ # Stability: Added in v1.07, stability guaranteed for v1.xx. + def fileno(self): + return self.c.fileno() + + ## + # Poll the underlying socket for this connection and sync if there is data + # waiting to be read. This has the effect of flushing asynchronous + # messages from the backend. Returns True if messages were read, False + # otherwise. + #

+ # Stability: Added in v1.07, stability guaranteed for v1.xx. + def isready(self): + return self.c.isready() + + ## + # Return the server_version as reported from the connected server. + # Raises InterfaceError if no version has been reported from the server. + def server_version(self): + return self.c.server_version() diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/protocol.py b/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/protocol.py new file mode 100644 index 0000000..6e7660e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/protocol.py @@ -0,0 +1,1323 @@ +# vim: sw=4:expandtab:foldmethod=marker +# +# Copyright (c) 2007-2009, Mathieu Fenniak +# All rights reserved. +# +# 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. +# * The name of the author may not 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. + +__author__ = "Mathieu Fenniak" + +import socket +try: + import ssl as sslmodule +except ImportError: + sslmodule = None +import select +import threading +import struct +import hashlib +from cStringIO import StringIO + +from errors import * +from util import MulticastDelegate +import types + +## +# An SSLRequest message. To initiate an SSL-encrypted connection, an +# SSLRequest message is used rather than a {@link StartupMessage +# StartupMessage}. A StartupMessage is still sent, but only after SSL +# negotiation (if accepted). +#

+# Stability: This is an internal class. No stability guarantee is made. +class SSLRequest(object): + def __init__(self): + pass + + # Int32(8) - Message length, including self.
+ # Int32(80877103) - The SSL request code.
+ def serialize(self): + return struct.pack("!ii", 8, 80877103) + + +## +# A StartupMessage message. Begins a DB session, identifying the user to be +# authenticated as and the database to connect to. +#

+# Stability: This is an internal class. No stability guarantee is made. +class StartupMessage(object): + def __init__(self, user, database=None): + self.user = user + self.database = database + + # Int32 - Message length, including self. + # Int32(196608) - Protocol version number. Version 3.0. + # Any number of key/value pairs, terminated by a zero byte: + # String - A parameter name (user, database, or options) + # String - Parameter value + def serialize(self): + protocol = 196608 + val = struct.pack("!i", protocol) + val += "user\x00" + self.user + "\x00" + if self.database: + val += "database\x00" + self.database + "\x00" + val += "\x00" + val = struct.pack("!i", len(val) + 4) + val + return val + + +## +# Parse message. Creates a prepared statement in the DB session. +#

+# Stability: This is an internal class. No stability guarantee is made. +# +# @param ps Name of the prepared statement to create. +# @param qs Query string. +# @param type_oids An iterable that contains the PostgreSQL type OIDs for +# parameters in the query string. +class Parse(object): + def __init__(self, ps, qs, type_oids): + if isinstance(qs, unicode): + raise TypeError("qs must be encoded byte data") + self.ps = ps + self.qs = qs + self.type_oids = type_oids + + def __repr__(self): + return "" % (self.ps, self.qs) + + # Byte1('P') - Identifies the message as a Parse command. + # Int32 - Message length, including self. + # String - Prepared statement name. An empty string selects the unnamed + # prepared statement. + # String - The query string. + # Int16 - Number of parameter data types specified (can be zero). + # For each parameter: + # Int32 - The OID of the parameter data type. + def serialize(self): + val = self.ps + "\x00" + self.qs + "\x00" + val = val + struct.pack("!h", len(self.type_oids)) + for oid in self.type_oids: + # Parse message doesn't seem to handle the -1 type_oid for NULL + # values that other messages handle. So we'll provide type_oid 705, + # the PG "unknown" type. + if oid == -1: oid = 705 + val = val + struct.pack("!i", oid) + val = struct.pack("!i", len(val) + 4) + val + val = "P" + val + return val + + +## +# Bind message. Readies a prepared statement for execution. +#

+# Stability: This is an internal class. No stability guarantee is made. +# +# @param portal Name of the destination portal. +# @param ps Name of the source prepared statement. +# @param in_fc An iterable containing the format codes for input +# parameters. 0 = Text, 1 = Binary. +# @param params The parameters. +# @param out_fc An iterable containing the format codes for output +# parameters. 0 = Text, 1 = Binary. +# @param kwargs Additional arguments to pass to the type conversion +# methods. +class Bind(object): + def __init__(self, portal, ps, in_fc, params, out_fc, **kwargs): + self.portal = portal + self.ps = ps + self.in_fc = in_fc + self.params = [] + for i in range(len(params)): + if len(self.in_fc) == 0: + fc = 0 + elif len(self.in_fc) == 1: + fc = self.in_fc[0] + else: + fc = self.in_fc[i] + self.params.append(types.pg_value(params[i], fc, **kwargs)) + self.out_fc = out_fc + + def __repr__(self): + return "" % (self.portal, self.ps) + + # Byte1('B') - Identifies the Bind command. + # Int32 - Message length, including self. + # String - Name of the destination portal. + # String - Name of the source prepared statement. + # Int16 - Number of parameter format codes. + # For each parameter format code: + # Int16 - The parameter format code. + # Int16 - Number of parameter values. + # For each parameter value: + # Int32 - The length of the parameter value, in bytes, not including this + # this length. -1 indicates a NULL parameter value, in which no + # value bytes follow. + # Byte[n] - Value of the parameter. + # Int16 - The number of result-column format codes. + # For each result-column format code: + # Int16 - The format code. + def serialize(self): + retval = StringIO() + retval.write(self.portal + "\x00") + retval.write(self.ps + "\x00") + retval.write(struct.pack("!h", len(self.in_fc))) + for fc in self.in_fc: + retval.write(struct.pack("!h", fc)) + retval.write(struct.pack("!h", len(self.params))) + for param in self.params: + if param == None: + # special case, NULL value + retval.write(struct.pack("!i", -1)) + else: + retval.write(struct.pack("!i", len(param))) + retval.write(param) + retval.write(struct.pack("!h", len(self.out_fc))) + for fc in self.out_fc: + retval.write(struct.pack("!h", fc)) + val = retval.getvalue() + val = struct.pack("!i", len(val) + 4) + val + val = "B" + val + return val + + +## +# A Close message, used for closing prepared statements and portals. +#

+# Stability: This is an internal class. No stability guarantee is made. +# +# @param typ 'S' for prepared statement, 'P' for portal. +# @param name The name of the item to close. +class Close(object): + def __init__(self, typ, name): + if len(typ) != 1: + raise InternalError("Close typ must be 1 char") + self.typ = typ + self.name = name + + # Byte1('C') - Identifies the message as a close command. + # Int32 - Message length, including self. + # Byte1 - 'S' for prepared statement, 'P' for portal. + # String - The name of the item to close. + def serialize(self): + val = self.typ + self.name + "\x00" + val = struct.pack("!i", len(val) + 4) + val + val = "C" + val + return val + + +## +# A specialized Close message for a portal. +#

+# Stability: This is an internal class. No stability guarantee is made. +class ClosePortal(Close): + def __init__(self, name): + Close.__init__(self, "P", name) + + +## +# A specialized Close message for a prepared statement. +#

+# Stability: This is an internal class. No stability guarantee is made. +class ClosePreparedStatement(Close): + def __init__(self, name): + Close.__init__(self, "S", name) + + +## +# A Describe message, used for obtaining information on prepared statements +# and portals. +#

+# Stability: This is an internal class. No stability guarantee is made. +# +# @param typ 'S' for prepared statement, 'P' for portal. +# @param name The name of the item to close. +class Describe(object): + def __init__(self, typ, name): + if len(typ) != 1: + raise InternalError("Describe typ must be 1 char") + self.typ = typ + self.name = name + + # Byte1('D') - Identifies the message as a describe command. + # Int32 - Message length, including self. + # Byte1 - 'S' for prepared statement, 'P' for portal. + # String - The name of the item to close. + def serialize(self): + val = self.typ + self.name + "\x00" + val = struct.pack("!i", len(val) + 4) + val + val = "D" + val + return val + + +## +# A specialized Describe message for a portal. +#

+# Stability: This is an internal class. No stability guarantee is made. +class DescribePortal(Describe): + def __init__(self, name): + Describe.__init__(self, "P", name) + + def __repr__(self): + return "" % (self.name) + + +## +# A specialized Describe message for a prepared statement. +#

+# Stability: This is an internal class. No stability guarantee is made. +class DescribePreparedStatement(Describe): + def __init__(self, name): + Describe.__init__(self, "S", name) + + def __repr__(self): + return "" % (self.name) + + +## +# A Flush message forces the backend to deliver any data pending in its +# output buffers. +#

+# Stability: This is an internal class. No stability guarantee is made. +class Flush(object): + # Byte1('H') - Identifies the message as a flush command. + # Int32(4) - Length of message, including self. + def serialize(self): + return 'H\x00\x00\x00\x04' + + def __repr__(self): + return "" + +## +# Causes the backend to close the current transaction (if not in a BEGIN/COMMIT +# block), and issue ReadyForQuery. +#

+# Stability: This is an internal class. No stability guarantee is made. +class Sync(object): + # Byte1('S') - Identifies the message as a sync command. + # Int32(4) - Length of message, including self. + def serialize(self): + return 'S\x00\x00\x00\x04' + + def __repr__(self): + return "" + + +## +# Transmits a password. +#

+# Stability: This is an internal class. No stability guarantee is made. +class PasswordMessage(object): + def __init__(self, pwd): + self.pwd = pwd + + # Byte1('p') - Identifies the message as a password message. + # Int32 - Message length including self. + # String - The password. Password may be encrypted. + def serialize(self): + val = self.pwd + "\x00" + val = struct.pack("!i", len(val) + 4) + val + val = "p" + val + return val + + +## +# Requests that the backend execute a portal and retrieve any number of rows. +#

+# Stability: This is an internal class. No stability guarantee is made. +# @param row_count The number of rows to return. Can be zero to indicate the +# backend should return all rows. If the portal represents a +# query that does not return rows, no rows will be returned +# no matter what the row_count. +class Execute(object): + def __init__(self, portal, row_count): + self.portal = portal + self.row_count = row_count + + # Byte1('E') - Identifies the message as an execute message. + # Int32 - Message length, including self. + # String - The name of the portal to execute. + # Int32 - Maximum number of rows to return, if portal contains a query that + # returns rows. 0 = no limit. + def serialize(self): + val = self.portal + "\x00" + struct.pack("!i", self.row_count) + val = struct.pack("!i", len(val) + 4) + val + val = "E" + val + return val + + +## +# Informs the backend that the connection is being closed. +#

+# Stability: This is an internal class. No stability guarantee is made. +class Terminate(object): + def __init__(self): + pass + + # Byte1('X') - Identifies the message as a terminate message. + # Int32(4) - Message length, including self. + def serialize(self): + return 'X\x00\x00\x00\x04' + +## +# Base class of all Authentication[*] messages. +#

+# Stability: This is an internal class. No stability guarantee is made. +class AuthenticationRequest(object): + def __init__(self, data): + pass + + # Byte1('R') - Identifies the message as an authentication request. + # Int32(8) - Message length, including self. + # Int32 - An authentication code that represents different + # authentication messages: + # 0 = AuthenticationOk + # 5 = MD5 pwd + # 2 = Kerberos v5 (not supported by pg8000) + # 3 = Cleartext pwd (not supported by pg8000) + # 4 = crypt() pwd (not supported by pg8000) + # 6 = SCM credential (not supported by pg8000) + # 7 = GSSAPI (not supported by pg8000) + # 8 = GSSAPI data (not supported by pg8000) + # 9 = SSPI (not supported by pg8000) + # Some authentication messages have additional data following the + # authentication code. That data is documented in the appropriate class. + def createFromData(data): + ident = struct.unpack("!i", data[:4])[0] + klass = authentication_codes.get(ident, None) + if klass != None: + return klass(data[4:]) + else: + raise NotSupportedError("authentication method %r not supported" % (ident,)) + createFromData = staticmethod(createFromData) + + def ok(self, conn, user, **kwargs): + raise InternalError("ok method should be overridden on AuthenticationRequest instance") + +## +# A message representing that the backend accepting the provided username +# without any challenge. +#

+# Stability: This is an internal class. No stability guarantee is made. +class AuthenticationOk(AuthenticationRequest): + def ok(self, conn, user, **kwargs): + return True + + +## +# A message representing the backend requesting an MD5 hashed password +# response. The response will be sent as md5(md5(pwd + login) + salt). +#

+# Stability: This is an internal class. No stability guarantee is made. +class AuthenticationMD5Password(AuthenticationRequest): + # Additional message data: + # Byte4 - Hash salt. + def __init__(self, data): + self.salt = "".join(struct.unpack("4c", data)) + + def ok(self, conn, user, password=None, **kwargs): + if password == None: + raise InterfaceError("server requesting MD5 password authentication, but no password was provided") + pwd = "md5" + hashlib.md5(hashlib.md5(password + user).hexdigest() + self.salt).hexdigest() + conn._send(PasswordMessage(pwd)) + conn._flush() + + reader = MessageReader(conn) + reader.add_message(AuthenticationRequest, lambda msg, reader: reader.return_value(msg.ok(conn, user)), reader) + reader.add_message(ErrorResponse, self._ok_error) + return reader.handle_messages() + + def _ok_error(self, msg): + if msg.code == "28000": + raise InterfaceError("md5 password authentication failed") + else: + raise msg.createException() + +authentication_codes = { + 0: AuthenticationOk, + 5: AuthenticationMD5Password, +} + + +## +# ParameterStatus message sent from backend, used to inform the frotnend of +# runtime configuration parameter changes. +#

+# Stability: This is an internal class. No stability guarantee is made. +class ParameterStatus(object): + def __init__(self, key, value): + self.key = key + self.value = value + + # Byte1('S') - Identifies ParameterStatus + # Int32 - Message length, including self. + # String - Runtime parameter name. + # String - Runtime parameter value. + def createFromData(data): + key = data[:data.find("\x00")] + value = data[data.find("\x00")+1:-1] + return ParameterStatus(key, value) + createFromData = staticmethod(createFromData) + + +## +# BackendKeyData message sent from backend. Contains a connection's process +# ID and a secret key. Can be used to terminate the connection's current +# actions, such as a long running query. Not supported by pg8000 yet. +#

+# Stability: This is an internal class. No stability guarantee is made. +class BackendKeyData(object): + def __init__(self, process_id, secret_key): + self.process_id = process_id + self.secret_key = secret_key + + # Byte1('K') - Identifier. + # Int32(12) - Message length, including self. + # Int32 - Process ID. + # Int32 - Secret key. + def createFromData(data): + process_id, secret_key = struct.unpack("!2i", data) + return BackendKeyData(process_id, secret_key) + createFromData = staticmethod(createFromData) + + +## +# Message representing a query with no data. +#

+# Stability: This is an internal class. No stability guarantee is made. +class NoData(object): + # Byte1('n') - Identifier. + # Int32(4) - Message length, including self. + def createFromData(data): + return NoData() + createFromData = staticmethod(createFromData) + + +## +# Message representing a successful Parse. +#

+# Stability: This is an internal class. No stability guarantee is made. +class ParseComplete(object): + # Byte1('1') - Identifier. + # Int32(4) - Message length, including self. + def createFromData(data): + return ParseComplete() + createFromData = staticmethod(createFromData) + + +## +# Message representing a successful Bind. +#

+# Stability: This is an internal class. No stability guarantee is made. +class BindComplete(object): + # Byte1('2') - Identifier. + # Int32(4) - Message length, including self. + def createFromData(data): + return BindComplete() + createFromData = staticmethod(createFromData) + + +## +# Message representing a successful Close. +#

+# Stability: This is an internal class. No stability guarantee is made. +class CloseComplete(object): + # Byte1('3') - Identifier. + # Int32(4) - Message length, including self. + def createFromData(data): + return CloseComplete() + createFromData = staticmethod(createFromData) + + +## +# Message representing data from an Execute has been received, but more data +# exists in the portal. +#

+# Stability: This is an internal class. No stability guarantee is made. +class PortalSuspended(object): + # Byte1('s') - Identifier. + # Int32(4) - Message length, including self. + def createFromData(data): + return PortalSuspended() + createFromData = staticmethod(createFromData) + + +## +# Message representing the backend is ready to process a new query. +#

+# Stability: This is an internal class. No stability guarantee is made. +class ReadyForQuery(object): + def __init__(self, status): + self._status = status + + ## + # I = Idle, T = Idle in Transaction, E = idle in failed transaction. + status = property(lambda self: self._status) + + def __repr__(self): + return "" % \ + {"I": "Idle", "T": "Idle in Transaction", "E": "Idle in Failed Transaction"}[self.status] + + # Byte1('Z') - Identifier. + # Int32(5) - Message length, including self. + # Byte1 - Status indicator. + def createFromData(data): + return ReadyForQuery(data) + createFromData = staticmethod(createFromData) + + +## +# Represents a notice sent from the server. This is not the same as a +# notification. A notice is just additional information about a query, such +# as a notice that a primary key has automatically been created for a table. +#

+# A NoticeResponse instance will have properties containing the data sent +# from the server: +#

    +#
  • severity -- "ERROR", "FATAL', "PANIC", "WARNING", "NOTICE", "DEBUG", +# "INFO", or "LOG". Always present.
  • +#
  • code -- the SQLSTATE code for the error. See Appendix A of the +# PostgreSQL documentation for specific error codes. Always present.
  • +#
  • msg -- human-readable error message. Always present.
  • +#
  • detail -- Optional additional information.
  • +#
  • hint -- Optional suggestion about what to do about the issue.
  • +#
  • position -- Optional index into the query string.
  • +#
  • where -- Optional context.
  • +#
  • file -- Source-code file.
  • +#
  • line -- Source-code line.
  • +#
  • routine -- Source-code routine.
  • +#
+#

+# Stability: Added in pg8000 v1.03. Required properties severity, code, and +# msg are guaranteed for v1.xx. Other properties should be checked with +# hasattr before accessing. +class NoticeResponse(object): + responseKeys = { + "S": "severity", # always present + "C": "code", # always present + "M": "msg", # always present + "D": "detail", + "H": "hint", + "P": "position", + "p": "_position", + "q": "_query", + "W": "where", + "F": "file", + "L": "line", + "R": "routine", + } + + def __init__(self, **kwargs): + for arg, value in kwargs.items(): + setattr(self, arg, value) + + def __repr__(self): + return "" % (self.severity, self.code, self.msg) + + def dataIntoDict(data): + retval = {} + for s in data.split("\x00"): + if not s: continue + key, value = s[0], s[1:] + key = NoticeResponse.responseKeys.get(key, key) + retval[key] = value + return retval + dataIntoDict = staticmethod(dataIntoDict) + + # Byte1('N') - Identifier + # Int32 - Message length + # Any number of these, followed by a zero byte: + # Byte1 - code identifying the field type (see responseKeys) + # String - field value + def createFromData(data): + return NoticeResponse(**NoticeResponse.dataIntoDict(data)) + createFromData = staticmethod(createFromData) + + +## +# A message sent in case of a server-side error. Contains the same properties +# that {@link NoticeResponse NoticeResponse} contains. +#

+# Stability: Added in pg8000 v1.03. Required properties severity, code, and +# msg are guaranteed for v1.xx. Other properties should be checked with +# hasattr before accessing. +class ErrorResponse(object): + def __init__(self, **kwargs): + for arg, value in kwargs.items(): + setattr(self, arg, value) + + def __repr__(self): + return "" % (self.severity, self.code, self.msg) + + def createException(self): + return ProgrammingError(self.severity, self.code, self.msg) + + def createFromData(data): + return ErrorResponse(**NoticeResponse.dataIntoDict(data)) + createFromData = staticmethod(createFromData) + + +## +# A message sent if this connection receives a NOTIFY that it was LISTENing for. +#

+# Stability: Added in pg8000 v1.03. When limited to accessing properties from +# a notification event dispatch, stability is guaranteed for v1.xx. +class NotificationResponse(object): + def __init__(self, backend_pid, condition, additional_info): + self._backend_pid = backend_pid + self._condition = condition + self._additional_info = additional_info + + ## + # An integer representing the process ID of the backend that triggered + # the NOTIFY. + #

+ # Stability: Added in pg8000 v1.03, stability guaranteed for v1.xx. + backend_pid = property(lambda self: self._backend_pid) + + ## + # The name of the notification fired. + #

+ # Stability: Added in pg8000 v1.03, stability guaranteed for v1.xx. + condition = property(lambda self: self._condition) + + ## + # Currently unspecified by the PostgreSQL documentation as of v8.3.1. + #

+ # Stability: Added in pg8000 v1.03, stability guaranteed for v1.xx. + additional_info = property(lambda self: self._additional_info) + + def __repr__(self): + return "" % (self.backend_pid, self.condition, self.additional_info) + + def createFromData(data): + backend_pid = struct.unpack("!i", data[:4])[0] + data = data[4:] + null = data.find("\x00") + condition = data[:null] + data = data[null+1:] + null = data.find("\x00") + additional_info = data[:null] + return NotificationResponse(backend_pid, condition, additional_info) + createFromData = staticmethod(createFromData) + + +class ParameterDescription(object): + def __init__(self, type_oids): + self.type_oids = type_oids + def createFromData(data): + count = struct.unpack("!h", data[:2])[0] + type_oids = struct.unpack("!" + "i"*count, data[2:]) + return ParameterDescription(type_oids) + createFromData = staticmethod(createFromData) + + +class RowDescription(object): + def __init__(self, fields): + self.fields = fields + + def createFromData(data): + count = struct.unpack("!h", data[:2])[0] + data = data[2:] + fields = [] + for i in range(count): + null = data.find("\x00") + field = {"name": data[:null]} + data = data[null+1:] + field["table_oid"], field["column_attrnum"], field["type_oid"], field["type_size"], field["type_modifier"], field["format"] = struct.unpack("!ihihih", data[:18]) + data = data[18:] + fields.append(field) + return RowDescription(fields) + createFromData = staticmethod(createFromData) + +class CommandComplete(object): + def __init__(self, command, rows=None, oid=None): + self.command = command + self.rows = rows + self.oid = oid + + def createFromData(data): + values = data[:-1].split(" ") + args = {} + args['command'] = values[0] + if args['command'] in ("INSERT", "DELETE", "UPDATE", "MOVE", "FETCH", "COPY"): + args['rows'] = int(values[-1]) + if args['command'] == "INSERT": + args['oid'] = int(values[1]) + else: + args['command'] = data[:-1] + return CommandComplete(**args) + createFromData = staticmethod(createFromData) + + +class DataRow(object): + def __init__(self, fields): + self.fields = fields + + def createFromData(data): + count = struct.unpack("!h", data[:2])[0] + data = data[2:] + fields = [] + for i in range(count): + val_len = struct.unpack("!i", data[:4])[0] + data = data[4:] + if val_len == -1: + fields.append(None) + else: + fields.append(data[:val_len]) + data = data[val_len:] + return DataRow(fields) + createFromData = staticmethod(createFromData) + + +class CopyData(object): + # "d": CopyData, + def __init__(self, data): + self.data = data + + def createFromData(data): + return CopyData(data) + createFromData = staticmethod(createFromData) + + def serialize(self): + return 'd' + struct.pack('!i', len(self.data) + 4) + self.data + + +class CopyDone(object): + # Byte1('c') - Identifier. + # Int32(4) - Message length, including self. + + def createFromData(data): + return CopyDone() + + createFromData = staticmethod(createFromData) + + def serialize(self): + return 'c\x00\x00\x00\x04' + +class CopyOutResponse(object): + # Byte1('H') + # Int32(4) - Length of message contents in bytes, including self. + # Int8(1) - 0 textual, 1 binary + # Int16(2) - Number of columns + # Int16(N) - Format codes for each column (0 text, 1 binary) + + def __init__(self, is_binary, column_formats): + self.is_binary = is_binary + self.column_formats = column_formats + + def createFromData(data): + is_binary, num_cols = struct.unpack('!bh', data[:3]) + column_formats = struct.unpack('!' + ('h' * num_cols), data[3:]) + return CopyOutResponse(is_binary, column_formats) + + createFromData = staticmethod(createFromData) + + +class CopyInResponse(object): + # Byte1('G') + # Otherwise the same as CopyOutResponse + + def __init__(self, is_binary, column_formats): + self.is_binary = is_binary + self.column_formats = column_formats + + def createFromData(data): + is_binary, num_cols = struct.unpack('!bh', data[:3]) + column_formats = struct.unpack('!' + ('h' * num_cols), data[3:]) + return CopyInResponse(is_binary, column_formats) + + createFromData = staticmethod(createFromData) + + +class MessageReader(object): + def __init__(self, connection): + self._conn = connection + self._msgs = [] + + # If true, raise exception from an ErrorResponse after messages are + # processed. This can be used to leave the connection in a usable + # state after an error response, rather than having unconsumed + # messages that won't be understood in another context. + self.delay_raising_exception = False + + self.ignore_unhandled_messages = False + + def add_message(self, msg_class, handler, *args, **kwargs): + self._msgs.append((msg_class, handler, args, kwargs)) + + def clear_messages(self): + self._msgs = [] + + def return_value(self, value): + self._retval = value + + def handle_messages(self): + exc = None + while 1: + msg = self._conn._read_message() + msg_handled = False + for (msg_class, handler, args, kwargs) in self._msgs: + if isinstance(msg, msg_class): + msg_handled = True + retval = handler(msg, *args, **kwargs) + if retval: + # The handler returned a true value, meaning that the + # message loop should be aborted. + if exc != None: + raise exc + return retval + elif hasattr(self, "_retval"): + # The handler told us to return -- used for non-true + # return values + if exc != None: + raise exc + return self._retval + if msg_handled: + continue + elif isinstance(msg, ErrorResponse): + exc = msg.createException() + if not self.delay_raising_exception: + raise exc + elif isinstance(msg, NoticeResponse): + self._conn.handleNoticeResponse(msg) + elif isinstance(msg, ParameterStatus): + self._conn.handleParameterStatus(msg) + elif isinstance(msg, NotificationResponse): + self._conn.handleNotificationResponse(msg) + elif not self.ignore_unhandled_messages: + raise InternalError("Unexpected response msg %r" % (msg)) + +def sync_on_error(fn): + def _fn(self, *args, **kwargs): + try: + self._sock_lock.acquire() + return fn(self, *args, **kwargs) + except: + self._sync() + raise + finally: + self._sock_lock.release() + return _fn + +class Connection(object): + def __init__(self, unix_sock=None, host=None, port=5432, socket_timeout=60, ssl=False): + self._client_encoding = "ascii" + self._integer_datetimes = False + self._server_version = None + self._sock_buf = "" + self._sock_buf_pos = 0 + self._send_sock_buf = [] + self._block_size = 8192 + self._sock_lock = threading.Lock() + if unix_sock == None and host != None: + self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + elif unix_sock != None: + if not hasattr(socket, "AF_UNIX"): + raise InterfaceError("attempt to connect to unix socket on unsupported platform") + self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + else: + raise ProgrammingError("one of host or unix_sock must be provided") + if unix_sock == None and host != None: + self._sock.connect((host, port)) + elif unix_sock != None: + self._sock.connect(unix_sock) + if ssl: + self._sock_lock.acquire() + try: + self._send(SSLRequest()) + self._flush() + resp = self._sock.recv(1) + if resp == 'S' and sslmodule is not None: + self._sock = sslmodule.wrap_socket(self._sock) + elif sslmodule is None: + raise InterfaceError("SSL required but ssl module not available in this python installation") + else: + raise InterfaceError("server refuses SSL") + finally: + self._sock_lock.release() + else: + # settimeout causes ssl failure, on windows. Python bug 1462352. + self._sock.settimeout(socket_timeout) + self._state = "noauth" + self._backend_key_data = None + + self.NoticeReceived = MulticastDelegate() + self.ParameterStatusReceived = MulticastDelegate() + self.NotificationReceived = MulticastDelegate() + + self.ParameterStatusReceived += self._onParameterStatusReceived + + def verifyState(self, state): + if self._state != state: + raise InternalError("connection state must be %s, is %s" % (state, self._state)) + + def _send(self, msg): + assert self._sock_lock.locked() + #print "_send(%r)" % msg + data = msg.serialize() + if not isinstance(data, str): + raise TypeError("bytes data expected") + self._send_sock_buf.append(data) + + def _flush(self): + assert self._sock_lock.locked() + self._sock.sendall("".join(self._send_sock_buf)) + del self._send_sock_buf[:] + + def _read_bytes(self, byte_count): + retval = [] + bytes_read = 0 + while bytes_read < byte_count: + if self._sock_buf_pos == len(self._sock_buf): + self._sock_buf = self._sock.recv(1024) + self._sock_buf_pos = 0 + rpos = min(len(self._sock_buf), self._sock_buf_pos + (byte_count - bytes_read)) + addt_data = self._sock_buf[self._sock_buf_pos:rpos] + bytes_read += (rpos - self._sock_buf_pos) + assert bytes_read <= byte_count + self._sock_buf_pos = rpos + retval.append(addt_data) + return "".join(retval) + + def _read_message(self): + assert self._sock_lock.locked() + bytes = self._read_bytes(5) + message_code = bytes[0] + data_len = struct.unpack("!i", bytes[1:])[0] - 4 + bytes = self._read_bytes(data_len) + assert len(bytes) == data_len + msg = message_types[message_code].createFromData(bytes) + #print "_read_message() -> %r" % msg + return msg + + def authenticate(self, user, **kwargs): + self.verifyState("noauth") + self._sock_lock.acquire() + try: + self._send(StartupMessage(user, database=kwargs.get("database",None))) + self._flush() + + reader = MessageReader(self) + reader.add_message(AuthenticationRequest, self._authentication_request(user, **kwargs)) + reader.handle_messages() + finally: + self._sock_lock.release() + + def _authentication_request(self, user, **kwargs): + def _func(msg): + assert self._sock_lock.locked() + if not msg.ok(self, user, **kwargs): + raise InterfaceError("authentication method %s failed" % msg.__class__.__name__) + self._state = "auth" + reader = MessageReader(self) + reader.add_message(ReadyForQuery, self._ready_for_query) + reader.add_message(BackendKeyData, self._receive_backend_key_data) + reader.handle_messages() + return 1 + return _func + + def _ready_for_query(self, msg): + self._state = "ready" + return True + + def _receive_backend_key_data(self, msg): + self._backend_key_data = msg + + @sync_on_error + def parse(self, statement, qs, param_types): + self.verifyState("ready") + + type_info = [types.pg_type_info(x) for x in param_types] + param_types, param_fc = [x[0] for x in type_info], [x[1] for x in type_info] # zip(*type_info) -- fails on empty arr + self._send(Parse(statement, qs.encode(self._client_encoding), param_types)) + self._send(DescribePreparedStatement(statement)) + self._send(Flush()) + self._flush() + + reader = MessageReader(self) + + # ParseComplete is good. + reader.add_message(ParseComplete, lambda msg: 0) + + # Well, we don't really care -- we're going to send whatever we + # want and let the database deal with it. But thanks anyways! + reader.add_message(ParameterDescription, lambda msg: 0) + + # We're not waiting for a row description. Return something + # destinctive to let bind know that there is no output. + reader.add_message(NoData, lambda msg: (None, param_fc)) + + # Common row description response + reader.add_message(RowDescription, lambda msg: (msg, param_fc)) + + return reader.handle_messages() + + @sync_on_error + def bind(self, portal, statement, params, parse_data, copy_stream): + self.verifyState("ready") + + row_desc, param_fc = parse_data + if row_desc == None: + # no data coming out + output_fc = () + else: + # We've got row_desc that allows us to identify what we're going to + # get back from this statement. + output_fc = [types.py_type_info(f) for f in row_desc.fields] + self._send(Bind(portal, statement, param_fc, params, output_fc, client_encoding = self._client_encoding, integer_datetimes = self._integer_datetimes)) + # We need to describe the portal after bind, since the return + # format codes will be different (hopefully, always what we + # requested). + self._send(DescribePortal(portal)) + self._send(Flush()) + self._flush() + + # Read responses from server... + reader = MessageReader(self) + + # BindComplete is good -- just ignore + reader.add_message(BindComplete, lambda msg: 0) + + # NoData in this case means we're not executing a query. As a + # result, we won't be fetching rows, so we'll never execute the + # portal we just created... unless we execute it right away, which + # we'll do. + reader.add_message(NoData, self._bind_nodata, portal, reader, copy_stream) + + # Return the new row desc, since it will have the format types we + # asked the server for + reader.add_message(RowDescription, lambda msg: (msg, None)) + + return reader.handle_messages() + + def _copy_in_response(self, copyin, fileobj, old_reader): + if fileobj == None: + raise CopyQueryWithoutStreamError() + while True: + data = fileobj.read(self._block_size) + if not data: + break + self._send(CopyData(data)) + self._flush() + self._send(CopyDone()) + self._send(Sync()) + self._flush() + + def _copy_out_response(self, copyout, fileobj, old_reader): + if fileobj == None: + raise CopyQueryWithoutStreamError() + reader = MessageReader(self) + reader.add_message(CopyData, self._copy_data, fileobj) + reader.add_message(CopyDone, lambda msg: 1) + reader.handle_messages() + + def _copy_data(self, copydata, fileobj): + fileobj.write(copydata.data) + + def _bind_nodata(self, msg, portal, old_reader, copy_stream): + # Bind message returned NoData, causing us to execute the command. + self._send(Execute(portal, 0)) + self._send(Sync()) + self._flush() + + output = {} + reader = MessageReader(self) + reader.add_message(CopyOutResponse, self._copy_out_response, copy_stream, reader) + reader.add_message(CopyInResponse, self._copy_in_response, copy_stream, reader) + reader.add_message(CommandComplete, lambda msg, out: out.setdefault('msg', msg) and False, output) + reader.add_message(ReadyForQuery, lambda msg: 1) + reader.delay_raising_exception = True + reader.handle_messages() + + old_reader.return_value((None, output['msg'])) + + @sync_on_error + def fetch_rows(self, portal, row_count, row_desc): + self.verifyState("ready") + + self._send(Execute(portal, row_count)) + self._send(Flush()) + self._flush() + rows = [] + + reader = MessageReader(self) + reader.add_message(DataRow, self._fetch_datarow, rows, row_desc) + reader.add_message(PortalSuspended, lambda msg: 1) + reader.add_message(CommandComplete, self._fetch_commandcomplete, portal) + retval = reader.handle_messages() + + # retval = 2 when command complete, indicating that we've hit the + # end of the available data for this command + return (retval == 2), rows + + def _fetch_datarow(self, msg, rows, row_desc): + rows.append( + [ + types.py_value( + msg.fields[i], + row_desc.fields[i], + client_encoding=self._client_encoding, + integer_datetimes=self._integer_datetimes, + ) + for i in range(len(msg.fields)) + ] + ) + + def _fetch_commandcomplete(self, msg, portal): + self._send(ClosePortal(portal)) + self._send(Sync()) + self._flush() + + reader = MessageReader(self) + reader.add_message(ReadyForQuery, self._fetch_commandcomplete_rfq) + reader.add_message(CloseComplete, lambda msg: False) + reader.handle_messages() + + return 2 # signal end-of-data + + def _fetch_commandcomplete_rfq(self, msg): + self._state = "ready" + return True + + # Send a Sync message, then read and discard all messages until we + # receive a ReadyForQuery message. + def _sync(self): + # it is assumed _sync is called from sync_on_error, which holds + # a _sock_lock throughout the call + self._send(Sync()) + self._flush() + reader = MessageReader(self) + reader.ignore_unhandled_messages = True + reader.add_message(ReadyForQuery, lambda msg: True) + reader.handle_messages() + + def close_statement(self, statement): + if self._state == "closed": + return + self.verifyState("ready") + self._sock_lock.acquire() + try: + self._send(ClosePreparedStatement(statement)) + self._send(Sync()) + self._flush() + + reader = MessageReader(self) + reader.add_message(CloseComplete, lambda msg: 0) + reader.add_message(ReadyForQuery, lambda msg: 1) + reader.handle_messages() + finally: + self._sock_lock.release() + + def close_portal(self, portal): + if self._state == "closed": + return + self.verifyState("ready") + self._sock_lock.acquire() + try: + self._send(ClosePortal(portal)) + self._send(Sync()) + self._flush() + + reader = MessageReader(self) + reader.add_message(CloseComplete, lambda msg: 0) + reader.add_message(ReadyForQuery, lambda msg: 1) + reader.handle_messages() + finally: + self._sock_lock.release() + + def close(self): + self._sock_lock.acquire() + try: + self._send(Terminate()) + self._flush() + self._sock.close() + self._state = "closed" + finally: + self._sock_lock.release() + + def _onParameterStatusReceived(self, msg): + if msg.key == "client_encoding": + self._client_encoding = types.encoding_convert(msg.value) + elif msg.key == "integer_datetimes": + self._integer_datetimes = (msg.value == "on") + elif msg.key == "server_version": + self._server_version = msg.value + + def handleNoticeResponse(self, msg): + self.NoticeReceived(msg) + + def handleParameterStatus(self, msg): + self.ParameterStatusReceived(msg) + + def handleNotificationResponse(self, msg): + self.NotificationReceived(msg) + + def fileno(self): + # This should be safe to do without a lock + return self._sock.fileno() + + def isready(self): + self._sock_lock.acquire() + try: + rlst, _wlst, _xlst = select.select([self], [], [], 0) + if not rlst: + return False + + self._sync() + return True + finally: + self._sock_lock.release() + + def server_version(self): + self.verifyState("ready") + if not self._server_version: + raise InterfaceError("Server did not provide server_version parameter.") + return self._server_version + + +message_types = { + "N": NoticeResponse, + "R": AuthenticationRequest, + "S": ParameterStatus, + "K": BackendKeyData, + "Z": ReadyForQuery, + "T": RowDescription, + "E": ErrorResponse, + "D": DataRow, + "C": CommandComplete, + "1": ParseComplete, + "2": BindComplete, + "3": CloseComplete, + "s": PortalSuspended, + "n": NoData, + "t": ParameterDescription, + "A": NotificationResponse, + "c": CopyDone, + "d": CopyData, + "G": CopyInResponse, + "H": CopyOutResponse, + } + + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/types.py b/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/types.py new file mode 100644 index 0000000..9556b17 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/types.py @@ -0,0 +1,708 @@ +# vim: sw=4:expandtab:foldmethod=marker +# +# Copyright (c) 2007-2009, Mathieu Fenniak +# All rights reserved. +# +# 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. +# * The name of the author may not 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. + +__author__ = "Mathieu Fenniak" + +import datetime +import decimal +import struct +import math +from errors import (NotSupportedError, ArrayDataParseError, InternalError, + ArrayContentEmptyError, ArrayContentNotHomogenousError, + ArrayContentNotSupportedError, ArrayDimensionsNotConsistentError) + +try: + from pytz import utc +except ImportError: + ZERO = datetime.timedelta(0) + class UTC(datetime.tzinfo): + def utcoffset(self, dt): + return ZERO + def tzname(self, dt): + return "UTC" + def dst(self, dt): + return ZERO + utc = UTC() + +class Bytea(str): + pass + +class Interval(object): + def __init__(self, microseconds=0, days=0, months=0): + self.microseconds = microseconds + self.days = days + self.months = months + + def _setMicroseconds(self, value): + if not isinstance(value, int) and not isinstance(value, long): + raise TypeError("microseconds must be an int or long") + elif not (min_int8 < value < max_int8): + raise OverflowError("microseconds must be representable as a 64-bit integer") + else: + self._microseconds = value + + def _setDays(self, value): + if not isinstance(value, int) and not isinstance(value, long): + raise TypeError("days must be an int or long") + elif not (min_int4 < value < max_int4): + raise OverflowError("days must be representable as a 32-bit integer") + else: + self._days = value + + def _setMonths(self, value): + if not isinstance(value, int) and not isinstance(value, long): + raise TypeError("months must be an int or long") + elif not (min_int4 < value < max_int4): + raise OverflowError("months must be representable as a 32-bit integer") + else: + self._months = value + + microseconds = property(lambda self: self._microseconds, _setMicroseconds) + days = property(lambda self: self._days, _setDays) + months = property(lambda self: self._months, _setMonths) + + def __repr__(self): + return "" % (self.months, self.days, self.microseconds) + + def __cmp__(self, other): + if other == None: return -1 + c = cmp(self.months, other.months) + if c != 0: return c + c = cmp(self.days, other.days) + if c != 0: return c + return cmp(self.microseconds, other.microseconds) + +def pg_type_info(typ): + value = None + if isinstance(typ, dict): + value = typ["value"] + typ = typ["type"] + + data = py_types.get(typ) + if data == None: + raise NotSupportedError("type %r not mapped to pg type" % typ) + + # permit the type data to be determined by the value, if provided + inspect_func = data.get("inspect") + if value != None and inspect_func != None: + data = inspect_func(value) + + type_oid = data.get("typeoid") + if type_oid == None: + raise InternalError("type %r has no type_oid" % typ) + elif type_oid == -1: + # special case: NULL values + return type_oid, 0 + + # prefer bin, but go with whatever exists + if data.get("bin_out"): + format = 1 + elif data.get("txt_out"): + format = 0 + else: + raise InternalError("no conversion fuction for type %r" % typ) + + return type_oid, format + +def pg_value(value, fc, **kwargs): + typ = type(value) + data = py_types.get(typ) + if data == None: + raise NotSupportedError("type %r not mapped to pg type" % typ) + + # permit the type conversion to be determined by the value, if provided + inspect_func = data.get("inspect") + if value != None and inspect_func != None: + data = inspect_func(value) + + # special case: NULL values + if data.get("typeoid") == -1: + return None + + if fc == 0: + func = data.get("txt_out") + elif fc == 1: + func = data.get("bin_out") + else: + raise InternalError("unrecognized format code %r" % fc) + if func == None: + raise NotSupportedError("type %r, format code %r not supported" % (typ, fc)) + return func(value, **kwargs) + +def py_type_info(description): + type_oid = description['type_oid'] + data = pg_types.get(type_oid) + if data == None: + raise NotSupportedError("type oid %r not mapped to py type" % type_oid) + # prefer bin, but go with whatever exists + if data.get("bin_in"): + format = 1 + elif data.get("txt_in"): + format = 0 + else: + raise InternalError("no conversion fuction for type oid %r" % type_oid) + return format + +def py_value(v, description, **kwargs): + if v == None: + # special case - NULL value + return None + type_oid = description['type_oid'] + format = description['format'] + data = pg_types.get(type_oid) + if data == None: + raise NotSupportedError("type oid %r not supported" % type_oid) + if format == 0: + func = data.get("txt_in") + elif format == 1: + func = data.get("bin_in") + else: + raise NotSupportedError("format code %r not supported" % format) + if func == None: + raise NotSupportedError("data response format %r, type %r not supported" % (format, type_oid)) + return func(v, **kwargs) + +def boolrecv(data, **kwargs): + return data == "\x01" + +def boolsend(v, **kwargs): + if v: + return "\x01" + else: + return "\x00" + +min_int2, max_int2 = -2 ** 15, 2 ** 15 +min_int4, max_int4 = -2 ** 31, 2 ** 31 +min_int8, max_int8 = -2 ** 63, 2 ** 63 + +def int_inspect(value): + if min_int2 < value < max_int2: + return {"typeoid": 21, "bin_out": int2send} + elif min_int4 < value < max_int4: + return {"typeoid": 23, "bin_out": int4send} + elif min_int8 < value < max_int8: + return {"typeoid": 20, "bin_out": int8send} + else: + return {"typeoid": 1700, "bin_out": numeric_send} + +def int2recv(data, **kwargs): + return struct.unpack("!h", data)[0] + +def int2send(v, **kwargs): + return struct.pack("!h", v) + +def int4recv(data, **kwargs): + return struct.unpack("!i", data)[0] + +def int4send(v, **kwargs): + return struct.pack("!i", v) + +def int8recv(data, **kwargs): + return struct.unpack("!q", data)[0] + +def int8send(v, **kwargs): + return struct.pack("!q", v) + +def float4recv(data, **kwargs): + return struct.unpack("!f", data)[0] + +def float8recv(data, **kwargs): + return struct.unpack("!d", data)[0] + +def float8send(v, **kwargs): + return struct.pack("!d", v) + +def datetime_inspect(value): + if value.tzinfo != None: + # send as timestamptz if timezone is provided + return {"typeoid": 1184, "bin_out": timestamptz_send} + else: + # otherwise send as timestamp + return {"typeoid": 1114, "bin_out": timestamp_send} + +def timestamp_recv(data, integer_datetimes, **kwargs): + if integer_datetimes: + # data is 64-bit integer representing milliseconds since 2000-01-01 + val = struct.unpack("!q", data)[0] + return datetime.datetime(2000, 1, 1) + datetime.timedelta(microseconds = val) + else: + # data is double-precision float representing seconds since 2000-01-01 + val = struct.unpack("!d", data)[0] + return datetime.datetime(2000, 1, 1) + datetime.timedelta(seconds = val) + +# return a timezone-aware datetime instance if we're reading from a +# "timestamp with timezone" type. The timezone returned will always be UTC, +# but providing that additional information can permit conversion to local. +def timestamptz_recv(data, **kwargs): + return timestamp_recv(data, **kwargs).replace(tzinfo=utc) + +def timestamp_send(v, integer_datetimes, **kwargs): + delta = v - datetime.datetime(2000, 1, 1) + val = delta.microseconds + (delta.seconds * 1000000) + (delta.days * 86400000000) + if integer_datetimes: + # data is 64-bit integer representing milliseconds since 2000-01-01 + return struct.pack("!q", val) + else: + # data is double-precision float representing seconds since 2000-01-01 + return struct.pack("!d", val / 1000.0 / 1000.0) + +def timestamptz_send(v, **kwargs): + # timestamps should be sent as UTC. If they have zone info, + # convert them. + return timestamp_send(v.astimezone(utc).replace(tzinfo=None), **kwargs) + +def date_in(data, **kwargs): + year = int(data[0:4]) + month = int(data[5:7]) + day = int(data[8:10]) + return datetime.date(year, month, day) + +def date_out(v, **kwargs): + return v.isoformat() + +def time_in(data, **kwargs): + hour = int(data[0:2]) + minute = int(data[3:5]) + sec = decimal.Decimal(data[6:]) + return datetime.time(hour, minute, int(sec), int((sec - int(sec)) * 1000000)) + +def time_out(v, **kwargs): + return v.isoformat() + +def numeric_in(data, **kwargs): + if data.find(".") == -1: + return int(data) + else: + return decimal.Decimal(data) + +def numeric_recv(data, **kwargs): + num_digits, weight, sign, scale = struct.unpack("!hhhh", data[:8]) + data = data[8:] + digits = struct.unpack("!" + ("h" * num_digits), data) + weight = decimal.Decimal(weight) + retval = 0 + for d in digits: + d = decimal.Decimal(d) + retval += d * (10000 ** weight) + weight -= 1 + if sign: + retval *= -1 + return retval + +DEC_DIGITS = 4 +def numeric_send(d, **kwargs): + # This is a very straight port of src/backend/utils/adt/numeric.c set_var_from_str() + s = str(d) + pos = 0 + sign = 0 + if s[0] == '-': + sign = 0x4000 # NEG + pos=1 + elif s[0] == '+': + sign = 0 # POS + pos=1 + have_dp = False + decdigits = [0, 0, 0, 0] + dweight = -1 + dscale = 0 + for char in s[pos:]: + if char.isdigit(): + decdigits.append(int(char)) + if not have_dp: + dweight += 1 + else: + dscale += 1 + pos+=1 + elif char == '.': + have_dp = True + pos+=1 + else: + break + + if len(s) > pos: + char = s[pos] + if char == 'e' or char == 'E': + pos+=1 + exponent = int(s[pos:]) + dweight += exponent + dscale -= exponent + if dscale < 0: dscale = 0 + + if dweight >= 0: + weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1 + else: + weight = -((-dweight - 1) / DEC_DIGITS + 1) + offset = (weight + 1) * DEC_DIGITS - (dweight + 1) + ndigits = (len(decdigits)-DEC_DIGITS + offset + DEC_DIGITS - 1) / DEC_DIGITS + + i = DEC_DIGITS - offset + decdigits.extend([0, 0, 0]) + ndigits_ = ndigits + digits = '' + while ndigits_ > 0: + # ifdef DEC_DIGITS == 4 + digits += struct.pack("!h", ((decdigits[i] * 10 + decdigits[i + 1]) * 10 + decdigits[i + 2]) * 10 + decdigits[i + 3]) + ndigits_ -= 1 + i += DEC_DIGITS + + # strip_var() + if ndigits == 0: + sign = 0x4000 # pos + weight = 0 + # ---------- + + retval = struct.pack("!hhhh", ndigits, weight, sign, dscale) + digits + return retval + +def numeric_out(v, **kwargs): + return str(v) + +# PostgreSQL encodings: +# http://www.postgresql.org/docs/8.3/interactive/multibyte.html +# Python encodings: +# http://www.python.org/doc/2.4/lib/standard-encodings.html +# +# Commented out encodings don't require a name change between PostgreSQL and +# Python. If the py side is None, then the encoding isn't supported. +pg_to_py_encodings = { + # Not supported: + "mule_internal": None, + "euc_tw": None, + + # Name fine as-is: + #"euc_jp", + #"euc_jis_2004", + #"euc_kr", + #"gb18030", + #"gbk", + #"johab", + #"sjis", + #"shift_jis_2004", + #"uhc", + #"utf8", + + # Different name: + "euc_cn": "gb2312", + "iso_8859_5": "is8859_5", + "iso_8859_6": "is8859_6", + "iso_8859_7": "is8859_7", + "iso_8859_8": "is8859_8", + "koi8": "koi8_r", + "latin1": "iso8859-1", + "latin2": "iso8859_2", + "latin3": "iso8859_3", + "latin4": "iso8859_4", + "latin5": "iso8859_9", + "latin6": "iso8859_10", + "latin7": "iso8859_13", + "latin8": "iso8859_14", + "latin9": "iso8859_15", + "sql_ascii": "ascii", + "win866": "cp886", + "win874": "cp874", + "win1250": "cp1250", + "win1251": "cp1251", + "win1252": "cp1252", + "win1253": "cp1253", + "win1254": "cp1254", + "win1255": "cp1255", + "win1256": "cp1256", + "win1257": "cp1257", + "win1258": "cp1258", +} + +def encoding_convert(encoding): + return pg_to_py_encodings.get(encoding.lower(), encoding) + +def varcharin(data, client_encoding, **kwargs): + return unicode(data, encoding_convert(client_encoding)) + +def textout(v, client_encoding, **kwargs): + if isinstance(v, unicode): + return v.encode(encoding_convert(client_encoding)) + else: + return v + +def byteasend(v, **kwargs): + return str(v) + +def bytearecv(data, **kwargs): + return Bytea(data) + +# interval support does not provide a Python-usable interval object yet +def interval_recv(data, integer_datetimes, **kwargs): + if integer_datetimes: + microseconds, days, months = struct.unpack("!qii", data) + else: + seconds, days, months = struct.unpack("!dii", data) + microseconds = int(seconds * 1000 * 1000) + return Interval(microseconds, days, months) + +def interval_send(data, integer_datetimes, **kwargs): + if integer_datetimes: + return struct.pack("!qii", data.microseconds, data.days, data.months) + else: + return struct.pack("!dii", data.microseconds / 1000.0 / 1000.0, data.days, data.months) + +def array_recv(data, **kwargs): + dim, hasnull, typeoid = struct.unpack("!iii", data[:12]) + data = data[12:] + + # get type conversion method for typeoid + conversion = pg_types[typeoid]["bin_in"] + + # Read dimension info + dim_lengths = [] + element_count = 1 + for idim in range(dim): + dim_len, dim_lbound = struct.unpack("!ii", data[:8]) + data = data[8:] + dim_lengths.append(dim_len) + element_count *= dim_len + + # Read all array values + array_values = [] + for i in range(element_count): + if len(data): + element_len, = struct.unpack("!i", data[:4]) + data = data[4:] + if element_len == -1: + array_values.append(None) + else: + array_values.append(conversion(data[:element_len], **kwargs)) + data = data[element_len:] + if data != "": + raise ArrayDataParseError("unexpected data left over after array read") + + # at this point, {{1,2,3},{4,5,6}}::int[][] looks like [1,2,3,4,5,6]. + # go through the dimensions and fix up the array contents to match + # expected dimensions + for dim_length in reversed(dim_lengths[1:]): + val = [] + while array_values: + val.append(array_values[:dim_length]) + array_values = array_values[dim_length:] + array_values = val + + return array_values + +def array_inspect(value): + # Check if array has any values. If not, we can't determine the proper + # array typeoid. + first_element = array_find_first_element(value) + if first_element == None: + raise ArrayContentEmptyError("array has no values") + + # supported array output + typ = type(first_element) + if issubclass(typ, int) or issubclass(typ, long): + # special int array support -- send as smallest possible array type + special_int_support = True + int2_ok, int4_ok, int8_ok = True, True, True + for v in array_flatten(value): + if v == None: + continue + if min_int2 < v < max_int2: + continue + int2_ok = False + if min_int4 < v < max_int4: + continue + int4_ok = False + if min_int8 < v < max_int8: + continue + int8_ok = False + if int2_ok: + array_typeoid = 1005 # INT2[] + elif int4_ok: + array_typeoid = 1007 # INT4[] + elif int8_ok: + array_typeoid = 1016 # INT8[] + else: + raise ArrayContentNotSupportedError("numeric not supported as array contents") + else: + special_int_support = False + array_typeoid = py_array_types.get(typ) + if array_typeoid == None: + raise ArrayContentNotSupportedError("type %r not supported as array contents" % typ) + + # check for homogenous array + for v in array_flatten(value): + if v != None and not (isinstance(v, typ) or (typ == long and isinstance(v, int)) or (typ == int and isinstance(v, long))): + raise ArrayContentNotHomogenousError("not all array elements are of type %r" % typ) + + # check that all array dimensions are consistent + array_check_dimensions(value) + + type_data = py_types[typ] + if special_int_support: + if array_typeoid == 1005: + type_data = {"typeoid": 21, "bin_out": int2send} + elif array_typeoid == 1007: + type_data = {"typeoid": 23, "bin_out": int4send} + elif array_typeoid == 1016: + type_data = {"typeoid": 20, "bin_out": int8send} + else: + type_data = py_types[typ] + return { + "typeoid": array_typeoid, + "bin_out": array_send(type_data["typeoid"], type_data["bin_out"]) + } + +def array_find_first_element(arr): + for v in array_flatten(arr): + if v != None: + return v + return None + +def array_flatten(arr): + for v in arr: + if isinstance(v, list): + for v2 in array_flatten(v): + yield v2 + else: + yield v + +def array_check_dimensions(arr): + v0 = arr[0] + if isinstance(v0, list): + req_len = len(v0) + req_inner_lengths = array_check_dimensions(v0) + for v in arr: + inner_lengths = array_check_dimensions(v) + if len(v) != req_len or inner_lengths != req_inner_lengths: + raise ArrayDimensionsNotConsistentError("array dimensions not consistent") + retval = [req_len] + retval.extend(req_inner_lengths) + return retval + else: + # make sure nothing else at this level is a list + for v in arr: + if isinstance(v, list): + raise ArrayDimensionsNotConsistentError("array dimensions not consistent") + return [] + +def array_has_null(arr): + for v in array_flatten(arr): + if v == None: + return True + return False + +def array_dim_lengths(arr): + v0 = arr[0] + if isinstance(v0, list): + retval = [len(v0)] + retval.extend(array_dim_lengths(v0)) + else: + return [len(arr)] + return retval + +class array_send(object): + def __init__(self, typeoid, bin_out_func): + self.typeoid = typeoid + self.bin_out_func = bin_out_func + + def __call__(self, arr, **kwargs): + has_null = array_has_null(arr) + dim_lengths = array_dim_lengths(arr) + data = struct.pack("!iii", len(dim_lengths), has_null, self.typeoid) + for i in dim_lengths: + data += struct.pack("!ii", i, 1) + for v in array_flatten(arr): + if v == None: + data += struct.pack("!i", -1) + else: + inner_data = self.bin_out_func(v, **kwargs) + data += struct.pack("!i", len(inner_data)) + data += inner_data + return data + +py_types = { + bool: {"typeoid": 16, "bin_out": boolsend}, + int: {"inspect": int_inspect}, + long: {"inspect": int_inspect}, + str: {"typeoid": 25, "bin_out": textout}, + unicode: {"typeoid": 25, "bin_out": textout}, + float: {"typeoid": 701, "bin_out": float8send}, + decimal.Decimal: {"typeoid": 1700, "bin_out": numeric_send}, + Bytea: {"typeoid": 17, "bin_out": byteasend}, + datetime.datetime: {"typeoid": 1114, "bin_out": timestamp_send, "inspect": datetime_inspect}, + datetime.date: {"typeoid": 1082, "txt_out": date_out}, + datetime.time: {"typeoid": 1083, "txt_out": time_out}, + Interval: {"typeoid": 1186, "bin_out": interval_send}, + type(None): {"typeoid": -1}, + list: {"inspect": array_inspect}, +} + +# py type -> pg array typeoid +py_array_types = { + float: 1022, + bool: 1000, + str: 1009, # TEXT[] + unicode: 1009, # TEXT[] + decimal.Decimal: 1231, # NUMERIC[] +} + +pg_types = { + 16: {"bin_in": boolrecv}, + 17: {"bin_in": bytearecv}, + 19: {"bin_in": varcharin}, # name type + 20: {"bin_in": int8recv}, + 21: {"bin_in": int2recv}, + 23: {"bin_in": int4recv}, + 25: {"bin_in": varcharin}, # TEXT type + 26: {"txt_in": numeric_in}, # oid type + 142: {"bin_in": varcharin}, # XML + 194: {"bin_in": varcharin}, # "string representing an internal node tree" + 700: {"bin_in": float4recv}, + 701: {"bin_in": float8recv}, + 705: {"bin_in": varcharin}, + 829: {"txt_in": varcharin}, # MACADDR type + 1000: {"bin_in": array_recv}, # BOOL[] + 1003: {"bin_in": array_recv}, # NAME[] + 1005: {"bin_in": array_recv}, # INT2[] + 1007: {"bin_in": array_recv}, # INT4[] + 1009: {"bin_in": array_recv}, # TEXT[] + 1014: {"bin_in": array_recv}, # CHAR[] + 1015: {"bin_in": array_recv}, # VARCHAR[] + 1016: {"bin_in": array_recv}, # INT8[] + 1021: {"bin_in": array_recv}, # FLOAT4[] + 1022: {"bin_in": array_recv}, # FLOAT8[] + 1042: {"bin_in": varcharin}, # CHAR type + 1043: {"bin_in": varcharin}, # VARCHAR type + 1082: {"txt_in": date_in}, + 1083: {"txt_in": time_in}, + 1114: {"bin_in": timestamp_recv}, + 1184: {"bin_in": timestamptz_recv}, # timestamp w/ tz + 1186: {"bin_in": interval_recv}, + 1231: {"bin_in": array_recv}, # NUMERIC[] + 1263: {"bin_in": array_recv}, # cstring[] + 1700: {"bin_in": numeric_recv}, + 2275: {"bin_in": varcharin}, # cstring +} + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/util.py b/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/util.py new file mode 100644 index 0000000..f228033 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pg8000/util.py @@ -0,0 +1,20 @@ + +class MulticastDelegate(object): + def __init__(self): + self.delegates = [] + + def __iadd__(self, delegate): + self.add(delegate) + return self + + def add(self, delegate): + self.delegates.append(delegate) + + def __isub__(self, delegate): + self.delegates.remove(delegate) + return self + + def __call__(self, *args, **kwargs): + for d in self.delegates: + d(*args, **kwargs) + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/porter.py b/interactive-mining-3rdparty-madis/madis/src/lib/porter.py new file mode 100755 index 0000000..cd2992a --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/porter.py @@ -0,0 +1,188 @@ +""" +Reimplementation of the +`Porter stemming algorithm `_ +in Python. + +In my quick tests, this implementation about 3.5 times faster than the +seriously weird Python linked from the official page. +""" + +import re + +# Suffix replacement lists + +_step2list = { + "ational": "ate", + "tional": "tion", + "enci": "ence", + "anci": "ance", + "izer": "ize", + "bli": "ble", + "alli": "al", + "entli": "ent", + "eli": "e", + "ousli": "ous", + "ization": "ize", + "ation": "ate", + "ator": "ate", + "alism": "al", + "iveness": "ive", + "fulness": "ful", + "ousness": "ous", + "aliti": "al", + "iviti": "ive", + "biliti": "ble", + "logi": "log", + } + +_step3list = { + "icate": "ic", + "ative": "", + "alize": "al", + "iciti": "ic", + "ical": "ic", + "ful": "", + "ness": "", + } + + +_cons = "[^aeiou]" +_vowel = "[aeiouy]" +_cons_seq = "[^aeiouy]+" +_vowel_seq = "[aeiou]+" + +# m > 0 +_mgr0 = re.compile("^(" + _cons_seq + ")?" + _vowel_seq + _cons_seq) +# m == 0 +_meq1 = re.compile("^(" + _cons_seq + ")?" + _vowel_seq + _cons_seq + "(" + _vowel_seq + ")?$") +# m > 1 +_mgr1 = re.compile("^(" + _cons_seq + ")?" + _vowel_seq + _cons_seq + _vowel_seq + _cons_seq) +# vowel in stem +_s_v = re.compile("^(" + _cons_seq + ")?" + _vowel) +# ??? +_c_v = re.compile("^" + _cons_seq + _vowel + "[^aeiouwxy]$") + +# Patterns used in the rules + +_ed_ing = re.compile("^(.*)(ed|ing)$") +_at_bl_iz = re.compile("(at|bl|iz)$") +_step1b = re.compile("([^aeiouylsz])\\1$") +_step2 = re.compile("^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$") +_step3 = re.compile("^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$") +_step4_1 = re.compile("^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$") +_step4_2 = re.compile("^(.+?)(s|t)(ion)$") +_step5 = re.compile("^(.+?)e$") + +# Stemming function + +def stem(w): + """Uses the Porter stemming algorithm to remove suffixes from English + words. + + >>> stem("fundamentally") + "fundament" + """ + + if len(w) < 3: return w + + first_is_y = w[0] == "y" + if first_is_y: + w = "Y" + w[1:] + + # Step 1a + if w.endswith("s"): + if w.endswith("sses"): + w = w[:-2] + elif w.endswith("ies"): + w = w[:-2] + elif w[-2] != "s": + w = w[:-1] + + # Step 1b + + if w.endswith("eed"): + s = w[:-3] + if _mgr0.match(s): + w = w[:-1] + else: + m = _ed_ing.match(w) + if m: + stem = m.group(1) + if _s_v.match(stem): + w = stem + if _at_bl_iz.match(w): + w += "e" + elif _step1b.match(w): + w = w[:-1] + elif _c_v.match(w): + w += "e" + + # Step 1c + + if w.endswith("y"): + stem = w[:-1] + if _s_v.match(stem): + w = stem + "i" + + # Step 2 + + m = _step2.match(w) + if m: + stem = m.group(1) + suffix = m.group(2) + if _mgr0.match(stem): + w = stem + _step2list[suffix] + + # Step 3 + + m = _step3.match(w) + if m: + stem = m.group(1) + suffix = m.group(2) + if _mgr0.match(stem): + w = stem + _step3list[suffix] + + # Step 4 + + m = _step4_1.match(w) + if m: + stem = m.group(1) + if _mgr1.match(stem): + w = stem + else: + m = _step4_2.match(w) + if m: + stem = m.group(1) + m.group(2) + if _mgr1.match(stem): + w = stem + + # Step 5 + + m = _step5.match(w) + if m: + stem = m.group(1) + if _mgr1.match(stem) or (_meq1.match(stem) and not _c_v.match(stem)): + w = stem + + if w.endswith("ll") and _mgr1.match(w): + w = w[:-1] + + if first_is_y: + w = "y" + w[1:] + + return w + +if __name__ == '__main__': + print stem("fundamentally") + + + + + + + + + + + + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/porter2.py b/interactive-mining-3rdparty-madis/madis/src/lib/porter2.py new file mode 100644 index 0000000..7af286d --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/porter2.py @@ -0,0 +1,310 @@ +# Copyright (c) 2008 Michael Dirolf (mike at dirolf dot com) + +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: + +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. + +"""An implementation of the Porter2 stemming algorithm. +See http://snowball.tartarus.org/algorithms/english/stemmer.html + +Adapted from pyporter2 by Michael Dirolf. + +This algorithm is more correct but (at least in this implementation) +several times slower than the original porter algorithm as implemented +in whoosh.lang.porter. +""" + +import re + +r_exp = re.compile(r"[^aeiouy]*[aeiouy]+[^aeiouy](\w*)") +ewss_exp1 = re.compile(r"^[aeiouy][^aeiouy]$") +ewss_exp2 = re.compile(r".*[^aeiouy][aeiouy][^aeiouywxY]$") +ccy_exp = re.compile(r"([aeiouy])y") +s1a_exp = re.compile(r"[aeiouy].") +s1b_exp = re.compile(r"[aeiouy]") + +def get_r1(word): + # exceptional forms + if word.startswith('gener') or word.startswith('arsen'): + return 5 + if word.startswith('commun'): + return 6 + + # normal form + match = r_exp.match(word) + if match: + return match.start(1) + return len(word) + +def get_r2(word): + match = r_exp.match(word, get_r1(word)) + if match: + return match.start(1) + return len(word) + +def ends_with_short_syllable(word): + if len(word) == 2: + if ewss_exp1.match(word): + return True + if ewss_exp2.match(word): + return True + return False + +def is_short_word(word): + if ends_with_short_syllable(word): + if get_r1(word) == len(word): + return True + return False + +def remove_initial_apostrophe(word): + if word.startswith("'"): + return word[1:] + return word + +def capitalize_consonant_ys(word): + if word.startswith('y'): + word = 'Y' + word[1:] + return ccy_exp.sub('\g<1>Y', word) + +def step_0(word): + if word.endswith("'s'"): + return word[:-3] + if word.endswith("'s"): + return word[:-2] + if word.endswith("'"): + return word[:-1] + return word + +def step_1a(word): + if word.endswith('sses'): + return word[:-4] + 'ss' + if word.endswith('ied') or word.endswith('ies'): + if len(word) > 4: + return word[:-3] + 'i' + else: + return word[:-3] + 'ie' + if word.endswith('us') or word.endswith('ss'): + return word + if word.endswith('s'): + preceding = word[:-1] + if s1a_exp.search(preceding): + return preceding + return word + return word + +doubles = ('bb', 'dd', 'ff', 'gg', 'mm', 'nn', 'pp', 'rr', 'tt') +def ends_with_double(word): + for double in doubles: + if word.endswith(double): + return True + return False +def step_1b_helper(word): + if word.endswith('at') or word.endswith('bl') or word.endswith('iz'): + return word + 'e' + if ends_with_double(word): + return word[:-1] + if is_short_word(word): + return word + 'e' + return word +s1b_suffixes = ('ed', 'edly', 'ing', 'ingly') + +def step_1b(word, r1): + if word.endswith('eedly'): + if len(word) - 5 >= r1: + return word[:-3] + return word + if word.endswith('eed'): + if len(word) - 3 >= r1: + return word[:-1] + return word + + for suffix in s1b_suffixes: + if word.endswith(suffix): + preceding = word[:-len(suffix)] + if s1b_exp.search(preceding): + return step_1b_helper(preceding) + return word + + return word + +def step_1c(word): + if word.endswith('y') or word.endswith('Y'): + if word[-2] not in 'aeiouy': + if len(word) > 2: + return word[:-1] + 'i' + return word + +def step_2_helper(word, r1, end, repl, prev): + if word.endswith(end): + if len(word) - len(end) >= r1: + if prev == []: + return word[:-len(end)] + repl + for p in prev: + if word[:-len(end)].endswith(p): + return word[:-len(end)] + repl + return word + return None +s2_triples = (('ization', 'ize', []), + ('ational', 'ate', []), + ('fulness', 'ful', []), + ('ousness', 'ous', []), + ('iveness', 'ive', []), + ('tional', 'tion', []), + ('biliti', 'ble', []), + ('lessli', 'less', []), + ('entli', 'ent', []), + ('ation', 'ate', []), + ('alism', 'al', []), + ('aliti', 'al', []), + ('ousli', 'ous', []), + ('iviti', 'ive', []), + ('fulli', 'ful', []), + ('enci', 'ence', []), + ('anci', 'ance', []), + ('abli', 'able', []), + ('izer', 'ize', []), + ('ator', 'ate', []), + ('alli', 'al', []), + ('bli', 'ble', []), + ('ogi', 'og', ['l']), + ('li', '', ['c', 'd', 'e', 'g', 'h', 'k', 'm', 'n', 'r', 't'])) + +def step_2(word, r1): + for trip in s2_triples: + attempt = step_2_helper(word, r1, trip[0], trip[1], trip[2]) + if attempt: + return attempt + return word + +def step_3_helper(word, r1, r2, end, repl, r2_necessary): + if word.endswith(end): + if len(word) - len(end) >= r1: + if not r2_necessary: + return word[:-len(end)] + repl + else: + if len(word) - len(end) >= r2: + return word[:-len(end)] + repl + return word + return None +s3_triples = (('ational', 'ate', False), + ('tional', 'tion', False), + ('alize', 'al', False), + ('icate', 'ic', False), + ('iciti', 'ic', False), + ('ative', '', True), + ('ical', 'ic', False), + ('ness', '', False), + ('ful', '', False)) +def step_3(word, r1, r2): + for trip in s3_triples: + attempt = step_3_helper(word, r1, r2, trip[0], trip[1], trip[2]) + if attempt: + return attempt + return word + +s4_delete_list = ('al', 'ance', 'ence', 'er', 'ic', 'able', 'ible', 'ant', 'ement', + 'ment', 'ent', 'ism', 'ate', 'iti', 'ous', 'ive', 'ize') + +def step_4(word, r2): + for end in s4_delete_list: + if word.endswith(end): + if len(word) - len(end) >= r2: + return word[:-len(end)] + return word + + if word.endswith('sion') or word.endswith('tion'): + if len(word) - 3 >= r2: + return word[:-3] + + return word + +def step_5(word, r1, r2): + if word.endswith('l'): + if len(word) - 1 >= r2 and word[-2] == 'l': + return word[:-1] + return word + + if word.endswith('e'): + if len(word) - 1 >= r2: + return word[:-1] + if len(word) - 1 >= r1 and not ends_with_short_syllable(word[:-1]): + return word[:-1] + + return word + +def normalize_ys(word): + return word.replace('Y', 'y') + +exceptional_forms = {'skis': 'ski', + 'skies': 'sky', + 'dying': 'die', + 'lying': 'lie', + 'tying': 'tie', + 'idly': 'idl', + 'gently': 'gentl', + 'ugly': 'ugli', + 'early': 'earli', + 'only': 'onli', + 'singly': 'singl', + 'sky': 'sky', + 'news': 'news', + 'howe': 'howe', + 'atlas': 'atlas', + 'cosmos': 'cosmos', + 'bias': 'bias', + 'andes': 'andes'} + +exceptional_early_exit_post_1a = frozenset(['inning', 'outing', 'canning', 'herring', + 'earring', 'proceed', 'exceed', 'succeed']) + + +def stem(word): + if len(word) <= 2: + return word + word = remove_initial_apostrophe(word) + + # handle some exceptional forms + if word in exceptional_forms: + return exceptional_forms[word] + + word = capitalize_consonant_ys(word) + r1 = get_r1(word) + r2 = get_r2(word) + word = step_0(word) + word = step_1a(word) + + # handle some more exceptional forms + if word in exceptional_early_exit_post_1a: + return word + + word = step_1b(word, r1) + word = step_1c(word) + word = step_2(word, r1) + word = step_3(word, r1, r2) + word = step_4(word, r2) + word = step_5(word, r1, r2) + word = normalize_ys(word) + + return word + +if __name__ == '__main__': + print stem("fundamentally") + + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pptable.py b/interactive-mining-3rdparty-madis/madis/src/lib/pptable.py new file mode 100644 index 0000000..cb2ba61 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pptable.py @@ -0,0 +1,64 @@ +import cStringIO,operator + +def indent(rows, hasHeader=False, headerChar='-', delim=' | ', justify='left', + separateRows=False, prefix='', postfix='', wrapfunc=lambda x:x): + """Indents a table by column. + - rows: A sequence of sequences of items, one sequence per row. + - hasHeader: True if the first row consists of the columns' names. + - headerChar: Character to be used for the row separator line + (if hasHeader==True or separateRows==True). + - delim: The column delimiter. + - justify: Determines how are data justified in their column. + Valid values are 'left','right' and 'center'. + - separateRows: True if rows are to be separated by a line + of 'headerChar's. + - prefix: A string prepended to each printed row. + - postfix: A string appended to each printed row. + - wrapfunc: A function f(text) for wrapping text; each element in + the table is first wrapped by this function.""" + + logicalRows = [[row] for row in rows] + # columns of physical rows + columns = map(None,*reduce(operator.add,logicalRows)) + # get the maximum of each column by the string length of its items + maxWidths = [max([len(str(item)) for item in column]) for column in columns] + rowSeparator = headerChar * (len(prefix) + len(postfix) + sum(maxWidths) + \ + len(delim)*(len(maxWidths)-1)) + # select the appropriate justify method + justify = {'center':str.center, 'right':str.rjust, 'left':str.ljust}[justify.lower()] + output=cStringIO.StringIO() + if separateRows: print >> output, rowSeparator + for physicalRows in logicalRows: + for row in physicalRows: + print >> output, \ + (prefix \ + + delim.join([justify(str(item),width) for (item,width) in zip(row,maxWidths)]) \ + + postfix).rstrip() + if separateRows or hasHeader: print >> output, rowSeparator; hasHeader=False + return output.getvalue() + + +if __name__ == '__main__': + labels = ('First Name', 'Last Name', 'Age', 'Position') + data = \ + '''John,Smith,24,Software Engineer + Mary,Brohowski,23,Sales Manager + Aristidis,Papageorgopoulos,28,Senior Reseacher''' + rows = [row.strip().split(',') for row in data.splitlines()] + + print indent([labels]+rows, hasHeader=True) + + data=[['0asdf'],[1]] + + print indent(data, hasHeader=True) + + # output: + # + #Without wrapping function + # + #First Name | Last Name | Age | Position + #------------------------------------------------------- + #John | Smith | 24 | Software Engineer + #Mary | Brohowski | 23 | Sales Manager + #Aristidis | Papageorgopoulos | 28 | Senior Reseacher + # diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/__init__.py new file mode 100644 index 0000000..0b3686d --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/__init__.py @@ -0,0 +1,136 @@ +''' +PyMySQL: A pure-Python drop-in replacement for MySQLdb. + +Copyright (c) 2010 PyMySQL contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +''' + +VERSION = (0, 5, None) + +from constants import FIELD_TYPE +from converters import escape_dict, escape_sequence, escape_string +from err import Warning, Error, InterfaceError, DataError, \ + DatabaseError, OperationalError, IntegrityError, InternalError, \ + NotSupportedError, ProgrammingError, MySQLError +from times import Date, Time, Timestamp, \ + DateFromTicks, TimeFromTicks, TimestampFromTicks + +import sys + +try: + frozenset +except NameError: + from sets import ImmutableSet as frozenset + try: + from sets import BaseSet as set + except ImportError: + from sets import Set as set + +threadsafety = 1 +apilevel = "2.0" +paramstyle = "format" + +class DBAPISet(frozenset): + + + def __ne__(self, other): + if isinstance(other, set): + return super(DBAPISet, self).__ne__(self, other) + else: + return other not in self + + def __eq__(self, other): + if isinstance(other, frozenset): + return frozenset.__eq__(self, other) + else: + return other in self + + def __hash__(self): + return frozenset.__hash__(self) + + +STRING = DBAPISet([FIELD_TYPE.ENUM, FIELD_TYPE.STRING, + FIELD_TYPE.VAR_STRING]) +BINARY = DBAPISet([FIELD_TYPE.BLOB, FIELD_TYPE.LONG_BLOB, + FIELD_TYPE.MEDIUM_BLOB, FIELD_TYPE.TINY_BLOB]) +NUMBER = DBAPISet([FIELD_TYPE.DECIMAL, FIELD_TYPE.DOUBLE, FIELD_TYPE.FLOAT, + FIELD_TYPE.INT24, FIELD_TYPE.LONG, FIELD_TYPE.LONGLONG, + FIELD_TYPE.TINY, FIELD_TYPE.YEAR]) +DATE = DBAPISet([FIELD_TYPE.DATE, FIELD_TYPE.NEWDATE]) +TIME = DBAPISet([FIELD_TYPE.TIME]) +TIMESTAMP = DBAPISet([FIELD_TYPE.TIMESTAMP, FIELD_TYPE.DATETIME]) +DATETIME = TIMESTAMP +ROWID = DBAPISet() + +def Binary(x): + """Return x as a binary type.""" + return str(x) + +def Connect(*args, **kwargs): + """ + Connect to the database; see connections.Connection.__init__() for + more information. + """ + from connections import Connection + return Connection(*args, **kwargs) + +from pymysql import connections as _orig_conn +Connect.__doc__ = _orig_conn.Connection.__init__.__doc__ + """\nSee connections.Connection.__init__() for + information about defaults.""" +del _orig_conn + +def get_client_info(): # for MySQLdb compatibility + return '%s.%s.%s' % VERSION + +connect = Connection = Connect + +# we include a doctored version_info here for MySQLdb compatibility +version_info = (1,2,2,"final",0) + +NULL = "NULL" + +__version__ = get_client_info() + +def thread_safe(): + return True # match MySQLdb.thread_safe() + +def install_as_MySQLdb(): + """ + After this function is called, any application that imports MySQLdb or + _mysql will unwittingly actually use + """ + sys.modules["MySQLdb"] = sys.modules["_mysql"] = sys.modules["pymysql"] + +__all__ = [ + 'BINARY', 'Binary', 'Connect', 'Connection', 'DATE', 'Date', + 'Time', 'Timestamp', 'DateFromTicks', 'TimeFromTicks', 'TimestampFromTicks', + 'DataError', 'DatabaseError', 'Error', 'FIELD_TYPE', 'IntegrityError', + 'InterfaceError', 'InternalError', 'MySQLError', 'NULL', 'NUMBER', + 'NotSupportedError', 'DBAPISet', 'OperationalError', 'ProgrammingError', + 'ROWID', 'STRING', 'TIME', 'TIMESTAMP', 'Warning', 'apilevel', 'connect', + 'connections', 'constants', 'converters', 'cursors', + 'escape_dict', 'escape_sequence', 'escape_string', 'get_client_info', + 'paramstyle', 'threadsafety', 'version_info', + + "install_as_MySQLdb", + + "NULL","__version__", + ] diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/charset.py b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/charset.py new file mode 100644 index 0000000..ce994eb --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/charset.py @@ -0,0 +1,244 @@ +MBLENGTH = { + 8:1, + 33:3, + 88:2, + 91:2 + } + +class Charset: + def __init__(self, id, name, collation, is_default): + self.id, self.name, self.collation = id, name, collation + self.is_default = is_default == 'Yes' + +class Charsets: + def __init__(self): + self._by_id = {} + + def add(self, c): + self._by_id[c.id] = c + + def by_id(self, id): + return self._by_id[id] + + def by_name(self, name): + for c in self._by_id.values(): + if c.name == name and c.is_default: + return c + +_charsets = Charsets() +""" +Generated with: + +mysql -N -s -e "select id, character_set_name, collation_name, is_default +from information_schema.collations order by id;" | python -c "import sys +for l in sys.stdin.readlines(): + id, name, collation, is_default = l.split(chr(9)) + print '_charsets.add(Charset(%s, \'%s\', \'%s\', \'%s\'))' \ + % (id, name, collation, is_default.strip()) +" + +""" +_charsets.add(Charset(1, 'big5', 'big5_chinese_ci', 'Yes')) +_charsets.add(Charset(2, 'latin2', 'latin2_czech_cs', '')) +_charsets.add(Charset(3, 'dec8', 'dec8_swedish_ci', 'Yes')) +_charsets.add(Charset(4, 'cp850', 'cp850_general_ci', 'Yes')) +_charsets.add(Charset(5, 'latin1', 'latin1_german1_ci', '')) +_charsets.add(Charset(6, 'hp8', 'hp8_english_ci', 'Yes')) +_charsets.add(Charset(7, 'koi8r', 'koi8r_general_ci', 'Yes')) +_charsets.add(Charset(8, 'latin1', 'latin1_swedish_ci', 'Yes')) +_charsets.add(Charset(9, 'latin2', 'latin2_general_ci', 'Yes')) +_charsets.add(Charset(10, 'swe7', 'swe7_swedish_ci', 'Yes')) +_charsets.add(Charset(11, 'ascii', 'ascii_general_ci', 'Yes')) +_charsets.add(Charset(12, 'ujis', 'ujis_japanese_ci', 'Yes')) +_charsets.add(Charset(13, 'sjis', 'sjis_japanese_ci', 'Yes')) +_charsets.add(Charset(14, 'cp1251', 'cp1251_bulgarian_ci', '')) +_charsets.add(Charset(15, 'latin1', 'latin1_danish_ci', '')) +_charsets.add(Charset(16, 'hebrew', 'hebrew_general_ci', 'Yes')) +_charsets.add(Charset(18, 'tis620', 'tis620_thai_ci', 'Yes')) +_charsets.add(Charset(19, 'euckr', 'euckr_korean_ci', 'Yes')) +_charsets.add(Charset(20, 'latin7', 'latin7_estonian_cs', '')) +_charsets.add(Charset(21, 'latin2', 'latin2_hungarian_ci', '')) +_charsets.add(Charset(22, 'koi8u', 'koi8u_general_ci', 'Yes')) +_charsets.add(Charset(23, 'cp1251', 'cp1251_ukrainian_ci', '')) +_charsets.add(Charset(24, 'gb2312', 'gb2312_chinese_ci', 'Yes')) +_charsets.add(Charset(25, 'greek', 'greek_general_ci', 'Yes')) +_charsets.add(Charset(26, 'cp1250', 'cp1250_general_ci', 'Yes')) +_charsets.add(Charset(27, 'latin2', 'latin2_croatian_ci', '')) +_charsets.add(Charset(28, 'gbk', 'gbk_chinese_ci', 'Yes')) +_charsets.add(Charset(29, 'cp1257', 'cp1257_lithuanian_ci', '')) +_charsets.add(Charset(30, 'latin5', 'latin5_turkish_ci', 'Yes')) +_charsets.add(Charset(31, 'latin1', 'latin1_german2_ci', '')) +_charsets.add(Charset(32, 'armscii8', 'armscii8_general_ci', 'Yes')) +_charsets.add(Charset(33, 'utf8', 'utf8_general_ci', 'Yes')) +_charsets.add(Charset(34, 'cp1250', 'cp1250_czech_cs', '')) +_charsets.add(Charset(35, 'ucs2', 'ucs2_general_ci', 'Yes')) +_charsets.add(Charset(36, 'cp866', 'cp866_general_ci', 'Yes')) +_charsets.add(Charset(37, 'keybcs2', 'keybcs2_general_ci', 'Yes')) +_charsets.add(Charset(38, 'macce', 'macce_general_ci', 'Yes')) +_charsets.add(Charset(39, 'macroman', 'macroman_general_ci', 'Yes')) +_charsets.add(Charset(40, 'cp852', 'cp852_general_ci', 'Yes')) +_charsets.add(Charset(41, 'latin7', 'latin7_general_ci', 'Yes')) +_charsets.add(Charset(42, 'latin7', 'latin7_general_cs', '')) +_charsets.add(Charset(43, 'macce', 'macce_bin', '')) +_charsets.add(Charset(44, 'cp1250', 'cp1250_croatian_ci', '')) +_charsets.add(Charset(45, 'utf8mb4', 'utf8mb4_general_ci', 'Yes')) +_charsets.add(Charset(46, 'utf8mb4', 'utf8mb4_bin', '')) +_charsets.add(Charset(47, 'latin1', 'latin1_bin', '')) +_charsets.add(Charset(48, 'latin1', 'latin1_general_ci', '')) +_charsets.add(Charset(49, 'latin1', 'latin1_general_cs', '')) +_charsets.add(Charset(50, 'cp1251', 'cp1251_bin', '')) +_charsets.add(Charset(51, 'cp1251', 'cp1251_general_ci', 'Yes')) +_charsets.add(Charset(52, 'cp1251', 'cp1251_general_cs', '')) +_charsets.add(Charset(53, 'macroman', 'macroman_bin', '')) +_charsets.add(Charset(54, 'utf16', 'utf16_general_ci', 'Yes')) +_charsets.add(Charset(55, 'utf16', 'utf16_bin', '')) +_charsets.add(Charset(57, 'cp1256', 'cp1256_general_ci', 'Yes')) +_charsets.add(Charset(58, 'cp1257', 'cp1257_bin', '')) +_charsets.add(Charset(59, 'cp1257', 'cp1257_general_ci', 'Yes')) +_charsets.add(Charset(60, 'utf32', 'utf32_general_ci', 'Yes')) +_charsets.add(Charset(61, 'utf32', 'utf32_bin', '')) +_charsets.add(Charset(63, 'binary', 'binary', 'Yes')) +_charsets.add(Charset(64, 'armscii8', 'armscii8_bin', '')) +_charsets.add(Charset(65, 'ascii', 'ascii_bin', '')) +_charsets.add(Charset(66, 'cp1250', 'cp1250_bin', '')) +_charsets.add(Charset(67, 'cp1256', 'cp1256_bin', '')) +_charsets.add(Charset(68, 'cp866', 'cp866_bin', '')) +_charsets.add(Charset(69, 'dec8', 'dec8_bin', '')) +_charsets.add(Charset(70, 'greek', 'greek_bin', '')) +_charsets.add(Charset(71, 'hebrew', 'hebrew_bin', '')) +_charsets.add(Charset(72, 'hp8', 'hp8_bin', '')) +_charsets.add(Charset(73, 'keybcs2', 'keybcs2_bin', '')) +_charsets.add(Charset(74, 'koi8r', 'koi8r_bin', '')) +_charsets.add(Charset(75, 'koi8u', 'koi8u_bin', '')) +_charsets.add(Charset(77, 'latin2', 'latin2_bin', '')) +_charsets.add(Charset(78, 'latin5', 'latin5_bin', '')) +_charsets.add(Charset(79, 'latin7', 'latin7_bin', '')) +_charsets.add(Charset(80, 'cp850', 'cp850_bin', '')) +_charsets.add(Charset(81, 'cp852', 'cp852_bin', '')) +_charsets.add(Charset(82, 'swe7', 'swe7_bin', '')) +_charsets.add(Charset(83, 'utf8', 'utf8_bin', '')) +_charsets.add(Charset(84, 'big5', 'big5_bin', '')) +_charsets.add(Charset(85, 'euckr', 'euckr_bin', '')) +_charsets.add(Charset(86, 'gb2312', 'gb2312_bin', '')) +_charsets.add(Charset(87, 'gbk', 'gbk_bin', '')) +_charsets.add(Charset(88, 'sjis', 'sjis_bin', '')) +_charsets.add(Charset(89, 'tis620', 'tis620_bin', '')) +_charsets.add(Charset(90, 'ucs2', 'ucs2_bin', '')) +_charsets.add(Charset(91, 'ujis', 'ujis_bin', '')) +_charsets.add(Charset(92, 'geostd8', 'geostd8_general_ci', 'Yes')) +_charsets.add(Charset(93, 'geostd8', 'geostd8_bin', '')) +_charsets.add(Charset(94, 'latin1', 'latin1_spanish_ci', '')) +_charsets.add(Charset(95, 'cp932', 'cp932_japanese_ci', 'Yes')) +_charsets.add(Charset(96, 'cp932', 'cp932_bin', '')) +_charsets.add(Charset(97, 'eucjpms', 'eucjpms_japanese_ci', 'Yes')) +_charsets.add(Charset(98, 'eucjpms', 'eucjpms_bin', '')) +_charsets.add(Charset(99, 'cp1250', 'cp1250_polish_ci', '')) +_charsets.add(Charset(101, 'utf16', 'utf16_unicode_ci', '')) +_charsets.add(Charset(102, 'utf16', 'utf16_icelandic_ci', '')) +_charsets.add(Charset(103, 'utf16', 'utf16_latvian_ci', '')) +_charsets.add(Charset(104, 'utf16', 'utf16_romanian_ci', '')) +_charsets.add(Charset(105, 'utf16', 'utf16_slovenian_ci', '')) +_charsets.add(Charset(106, 'utf16', 'utf16_polish_ci', '')) +_charsets.add(Charset(107, 'utf16', 'utf16_estonian_ci', '')) +_charsets.add(Charset(108, 'utf16', 'utf16_spanish_ci', '')) +_charsets.add(Charset(109, 'utf16', 'utf16_swedish_ci', '')) +_charsets.add(Charset(110, 'utf16', 'utf16_turkish_ci', '')) +_charsets.add(Charset(111, 'utf16', 'utf16_czech_ci', '')) +_charsets.add(Charset(112, 'utf16', 'utf16_danish_ci', '')) +_charsets.add(Charset(113, 'utf16', 'utf16_lithuanian_ci', '')) +_charsets.add(Charset(114, 'utf16', 'utf16_slovak_ci', '')) +_charsets.add(Charset(115, 'utf16', 'utf16_spanish2_ci', '')) +_charsets.add(Charset(116, 'utf16', 'utf16_roman_ci', '')) +_charsets.add(Charset(117, 'utf16', 'utf16_persian_ci', '')) +_charsets.add(Charset(118, 'utf16', 'utf16_esperanto_ci', '')) +_charsets.add(Charset(119, 'utf16', 'utf16_hungarian_ci', '')) +_charsets.add(Charset(120, 'utf16', 'utf16_sinhala_ci', '')) +_charsets.add(Charset(128, 'ucs2', 'ucs2_unicode_ci', '')) +_charsets.add(Charset(129, 'ucs2', 'ucs2_icelandic_ci', '')) +_charsets.add(Charset(130, 'ucs2', 'ucs2_latvian_ci', '')) +_charsets.add(Charset(131, 'ucs2', 'ucs2_romanian_ci', '')) +_charsets.add(Charset(132, 'ucs2', 'ucs2_slovenian_ci', '')) +_charsets.add(Charset(133, 'ucs2', 'ucs2_polish_ci', '')) +_charsets.add(Charset(134, 'ucs2', 'ucs2_estonian_ci', '')) +_charsets.add(Charset(135, 'ucs2', 'ucs2_spanish_ci', '')) +_charsets.add(Charset(136, 'ucs2', 'ucs2_swedish_ci', '')) +_charsets.add(Charset(137, 'ucs2', 'ucs2_turkish_ci', '')) +_charsets.add(Charset(138, 'ucs2', 'ucs2_czech_ci', '')) +_charsets.add(Charset(139, 'ucs2', 'ucs2_danish_ci', '')) +_charsets.add(Charset(140, 'ucs2', 'ucs2_lithuanian_ci', '')) +_charsets.add(Charset(141, 'ucs2', 'ucs2_slovak_ci', '')) +_charsets.add(Charset(142, 'ucs2', 'ucs2_spanish2_ci', '')) +_charsets.add(Charset(143, 'ucs2', 'ucs2_roman_ci', '')) +_charsets.add(Charset(144, 'ucs2', 'ucs2_persian_ci', '')) +_charsets.add(Charset(145, 'ucs2', 'ucs2_esperanto_ci', '')) +_charsets.add(Charset(146, 'ucs2', 'ucs2_hungarian_ci', '')) +_charsets.add(Charset(147, 'ucs2', 'ucs2_sinhala_ci', '')) +_charsets.add(Charset(159, 'ucs2', 'ucs2_general_mysql500_ci', '')) +_charsets.add(Charset(160, 'utf32', 'utf32_unicode_ci', '')) +_charsets.add(Charset(161, 'utf32', 'utf32_icelandic_ci', '')) +_charsets.add(Charset(162, 'utf32', 'utf32_latvian_ci', '')) +_charsets.add(Charset(163, 'utf32', 'utf32_romanian_ci', '')) +_charsets.add(Charset(164, 'utf32', 'utf32_slovenian_ci', '')) +_charsets.add(Charset(165, 'utf32', 'utf32_polish_ci', '')) +_charsets.add(Charset(166, 'utf32', 'utf32_estonian_ci', '')) +_charsets.add(Charset(167, 'utf32', 'utf32_spanish_ci', '')) +_charsets.add(Charset(168, 'utf32', 'utf32_swedish_ci', '')) +_charsets.add(Charset(169, 'utf32', 'utf32_turkish_ci', '')) +_charsets.add(Charset(170, 'utf32', 'utf32_czech_ci', '')) +_charsets.add(Charset(171, 'utf32', 'utf32_danish_ci', '')) +_charsets.add(Charset(172, 'utf32', 'utf32_lithuanian_ci', '')) +_charsets.add(Charset(173, 'utf32', 'utf32_slovak_ci', '')) +_charsets.add(Charset(174, 'utf32', 'utf32_spanish2_ci', '')) +_charsets.add(Charset(175, 'utf32', 'utf32_roman_ci', '')) +_charsets.add(Charset(176, 'utf32', 'utf32_persian_ci', '')) +_charsets.add(Charset(177, 'utf32', 'utf32_esperanto_ci', '')) +_charsets.add(Charset(178, 'utf32', 'utf32_hungarian_ci', '')) +_charsets.add(Charset(179, 'utf32', 'utf32_sinhala_ci', '')) +_charsets.add(Charset(192, 'utf8', 'utf8_unicode_ci', '')) +_charsets.add(Charset(193, 'utf8', 'utf8_icelandic_ci', '')) +_charsets.add(Charset(194, 'utf8', 'utf8_latvian_ci', '')) +_charsets.add(Charset(195, 'utf8', 'utf8_romanian_ci', '')) +_charsets.add(Charset(196, 'utf8', 'utf8_slovenian_ci', '')) +_charsets.add(Charset(197, 'utf8', 'utf8_polish_ci', '')) +_charsets.add(Charset(198, 'utf8', 'utf8_estonian_ci', '')) +_charsets.add(Charset(199, 'utf8', 'utf8_spanish_ci', '')) +_charsets.add(Charset(200, 'utf8', 'utf8_swedish_ci', '')) +_charsets.add(Charset(201, 'utf8', 'utf8_turkish_ci', '')) +_charsets.add(Charset(202, 'utf8', 'utf8_czech_ci', '')) +_charsets.add(Charset(203, 'utf8', 'utf8_danish_ci', '')) +_charsets.add(Charset(204, 'utf8', 'utf8_lithuanian_ci', '')) +_charsets.add(Charset(205, 'utf8', 'utf8_slovak_ci', '')) +_charsets.add(Charset(206, 'utf8', 'utf8_spanish2_ci', '')) +_charsets.add(Charset(207, 'utf8', 'utf8_roman_ci', '')) +_charsets.add(Charset(208, 'utf8', 'utf8_persian_ci', '')) +_charsets.add(Charset(209, 'utf8', 'utf8_esperanto_ci', '')) +_charsets.add(Charset(210, 'utf8', 'utf8_hungarian_ci', '')) +_charsets.add(Charset(211, 'utf8', 'utf8_sinhala_ci', '')) +_charsets.add(Charset(223, 'utf8', 'utf8_general_mysql500_ci', '')) +_charsets.add(Charset(224, 'utf8mb4', 'utf8mb4_unicode_ci', '')) +_charsets.add(Charset(225, 'utf8mb4', 'utf8mb4_icelandic_ci', '')) +_charsets.add(Charset(226, 'utf8mb4', 'utf8mb4_latvian_ci', '')) +_charsets.add(Charset(227, 'utf8mb4', 'utf8mb4_romanian_ci', '')) +_charsets.add(Charset(228, 'utf8mb4', 'utf8mb4_slovenian_ci', '')) +_charsets.add(Charset(229, 'utf8mb4', 'utf8mb4_polish_ci', '')) +_charsets.add(Charset(230, 'utf8mb4', 'utf8mb4_estonian_ci', '')) +_charsets.add(Charset(231, 'utf8mb4', 'utf8mb4_spanish_ci', '')) +_charsets.add(Charset(232, 'utf8mb4', 'utf8mb4_swedish_ci', '')) +_charsets.add(Charset(233, 'utf8mb4', 'utf8mb4_turkish_ci', '')) +_charsets.add(Charset(234, 'utf8mb4', 'utf8mb4_czech_ci', '')) +_charsets.add(Charset(235, 'utf8mb4', 'utf8mb4_danish_ci', '')) +_charsets.add(Charset(236, 'utf8mb4', 'utf8mb4_lithuanian_ci', '')) +_charsets.add(Charset(237, 'utf8mb4', 'utf8mb4_slovak_ci', '')) +_charsets.add(Charset(238, 'utf8mb4', 'utf8mb4_spanish2_ci', '')) +_charsets.add(Charset(239, 'utf8mb4', 'utf8mb4_roman_ci', '')) +_charsets.add(Charset(240, 'utf8mb4', 'utf8mb4_persian_ci', '')) +_charsets.add(Charset(241, 'utf8mb4', 'utf8mb4_esperanto_ci', '')) +_charsets.add(Charset(242, 'utf8mb4', 'utf8mb4_hungarian_ci', '')) +_charsets.add(Charset(243, 'utf8mb4', 'utf8mb4_sinhala_ci', '')) + +def charset_by_name(name): + return _charsets.by_name(name) + +def charset_by_id(id): + return _charsets.by_id(id) + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/connections.py b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/connections.py new file mode 100644 index 0000000..99a256c --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/connections.py @@ -0,0 +1,1079 @@ +# Python implementation of the MySQL client-server protocol +# http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol + +try: + import hashlib + sha_new = lambda *args, **kwargs: hashlib.new("sha1", *args, **kwargs) +except ImportError: + import sha + sha_new = sha.new + +import socket +try: + import ssl + SSL_ENABLED = True +except ImportError: + SSL_ENABLED = False + +import struct +import sys +import os +import ConfigParser + +try: + import cStringIO as StringIO +except ImportError: + import StringIO + +try: + import getpass + DEFAULT_USER = getpass.getuser() +except ImportError: + DEFAULT_USER = None + +from charset import MBLENGTH, charset_by_name, charset_by_id +from cursors import Cursor +from constants import FIELD_TYPE, FLAG +from constants import SERVER_STATUS +from constants.CLIENT import * +from constants.COMMAND import * +from util import join_bytes, byte2int, int2byte +from converters import escape_item, encoders, decoders +from err import raise_mysql_exception, Warning, Error, \ + InterfaceError, DataError, DatabaseError, OperationalError, \ + IntegrityError, InternalError, NotSupportedError, ProgrammingError + +DEBUG = False + +NULL_COLUMN = 251 +UNSIGNED_CHAR_COLUMN = 251 +UNSIGNED_SHORT_COLUMN = 252 +UNSIGNED_INT24_COLUMN = 253 +UNSIGNED_INT64_COLUMN = 254 +UNSIGNED_CHAR_LENGTH = 1 +UNSIGNED_SHORT_LENGTH = 2 +UNSIGNED_INT24_LENGTH = 3 +UNSIGNED_INT64_LENGTH = 8 + +DEFAULT_CHARSET = 'latin1' + + +def dump_packet(data): + + def is_ascii(data): + if byte2int(data) >= 65 and byte2int(data) <= 122: #data.isalnum(): + return data + return '.' + + try: + print "packet length %d" % len(data) + print "method call[1]: %s" % sys._getframe(1).f_code.co_name + print "method call[2]: %s" % sys._getframe(2).f_code.co_name + print "method call[3]: %s" % sys._getframe(3).f_code.co_name + print "method call[4]: %s" % sys._getframe(4).f_code.co_name + print "method call[5]: %s" % sys._getframe(5).f_code.co_name + print "-" * 88 + except ValueError: pass + dump_data = [data[i:i+16] for i in xrange(len(data)) if i%16 == 0] + for d in dump_data: + print ' '.join(map(lambda x:"%02X" % byte2int(x), d)) + \ + ' ' * (16 - len(d)) + ' ' * 2 + \ + ' '.join(map(lambda x:"%s" % is_ascii(x), d)) + print "-" * 88 + print "" + +def _scramble(password, message): + if password == None or len(password) == 0: + return int2byte(0) + if DEBUG: print 'password=' + password + stage1 = sha_new(password).digest() + stage2 = sha_new(stage1).digest() + s = sha_new() + s.update(message) + s.update(stage2) + result = s.digest() + return _my_crypt(result, stage1) + +def _my_crypt(message1, message2): + length = len(message1) + result = struct.pack('B', length) + for i in xrange(length): + x = (struct.unpack('B', message1[i:i+1])[0] ^ \ + struct.unpack('B', message2[i:i+1])[0]) + result += struct.pack('B', x) + return result + +# old_passwords support ported from libmysql/password.c +SCRAMBLE_LENGTH_323 = 8 + +class RandStruct_323(object): + def __init__(self, seed1, seed2): + self.max_value = 0x3FFFFFFFL + self.seed1 = seed1 % self.max_value + self.seed2 = seed2 % self.max_value + + def my_rnd(self): + self.seed1 = (self.seed1 * 3L + self.seed2) % self.max_value + self.seed2 = (self.seed1 + self.seed2 + 33L) % self.max_value + return float(self.seed1) / float(self.max_value) + +def _scramble_323(password, message): + hash_pass = _hash_password_323(password) + hash_message = _hash_password_323(message[:SCRAMBLE_LENGTH_323]) + hash_pass_n = struct.unpack(">LL", hash_pass) + hash_message_n = struct.unpack(">LL", hash_message) + + rand_st = RandStruct_323(hash_pass_n[0] ^ hash_message_n[0], + hash_pass_n[1] ^ hash_message_n[1]) + outbuf = StringIO.StringIO() + for _ in xrange(min(SCRAMBLE_LENGTH_323, len(message))): + outbuf.write(int2byte(int(rand_st.my_rnd() * 31) + 64)) + extra = int2byte(int(rand_st.my_rnd() * 31)) + out = outbuf.getvalue() + outbuf = StringIO.StringIO() + for c in out: + outbuf.write(int2byte(byte2int(c) ^ byte2int(extra))) + return outbuf.getvalue() + +def _hash_password_323(password): + nr = 1345345333L + add = 7L + nr2 = 0x12345671L + + for c in [byte2int(x) for x in password if x not in (' ', '\t')]: + nr^= (((nr & 63)+add)*c)+ (nr << 8) & 0xFFFFFFFF + nr2= (nr2 + ((nr2 << 8) ^ nr)) & 0xFFFFFFFF + add= (add + c) & 0xFFFFFFFF + + r1 = nr & ((1L << 31) - 1L) # kill sign bits + r2 = nr2 & ((1L << 31) - 1L) + + # pack + return struct.pack(">LL", r1, r2) + +def pack_int24(n): + return struct.pack('BBB', n&0xFF, (n>>8)&0xFF, (n>>16)&0xFF) + +def unpack_uint16(n): + return struct.unpack(' len(self.__data): + raise Exception('Invalid advance amount (%s) for cursor. ' + 'Position=%s' % (length, new_position)) + self.__position = new_position + + def rewind(self, position=0): + """Set the position of the data buffer cursor to 'position'.""" + if position < 0 or position > len(self.__data): + raise Exception("Invalid position to rewind cursor to: %s." % position) + self.__position = position + + def peek(self, size): + """Look at the first 'size' bytes in packet without moving cursor.""" + result = self.__data[self.__position:(self.__position+size)] + if len(result) != size: + error = ('Result length not requested length:\n' + 'Expected=%s. Actual=%s. Position: %s. Data Length: %s' + % (size, len(result), self.__position, len(self.__data))) + if DEBUG: + print error + self.dump() + raise AssertionError(error) + return result + + def get_bytes(self, position, length=1): + """Get 'length' bytes starting at 'position'. + + Position is start of payload (first four packet header bytes are not + included) starting at index '0'. + + No error checking is done. If requesting outside end of buffer + an empty string (or string shorter than 'length') may be returned! + """ + return self.__data[position:(position+length)] + + def read_length_coded_binary(self): + """Read a 'Length Coded Binary' number from the data buffer. + + Length coded numbers can be anywhere from 1 to 9 bytes depending + on the value of the first byte. + """ + c = byte2int(self.read(1)) + if c == NULL_COLUMN: + return None + if c < UNSIGNED_CHAR_COLUMN: + return c + elif c == UNSIGNED_SHORT_COLUMN: + return unpack_uint16(self.read(UNSIGNED_SHORT_LENGTH)) + elif c == UNSIGNED_INT24_COLUMN: + return unpack_int24(self.read(UNSIGNED_INT24_LENGTH)) + elif c == UNSIGNED_INT64_COLUMN: + # TODO: what was 'longlong'? confirm it wasn't used? + return unpack_int64(self.read(UNSIGNED_INT64_LENGTH)) + + def read_length_coded_string(self): + """Read a 'Length Coded String' from the data buffer. + + A 'Length Coded String' consists first of a length coded + (unsigned, positive) integer represented in 1-9 bytes followed by + that many bytes of binary data. (For example "cat" would be "3cat".) + """ + length = self.read_length_coded_binary() + if length is None: + return None + return self.read(length) + + def is_ok_packet(self): + return byte2int(self.get_bytes(0)) == 0 + + def is_eof_packet(self): + return byte2int(self.get_bytes(0)) == 254 # 'fe' + + def is_resultset_packet(self): + field_count = byte2int(self.get_bytes(0)) + return field_count >= 1 and field_count <= 250 + + def is_error_packet(self): + return byte2int(self.get_bytes(0)) == 255 + + def check_error(self): + if self.is_error_packet(): + self.rewind() + self.advance(1) # field_count == error (we already know that) + errno = unpack_uint16(self.read(2)) + if DEBUG: print "errno = %d" % errno + raise_mysql_exception(self.__data) + + def dump(self): + dump_packet(self.__data) + + +class FieldDescriptorPacket(MysqlPacket): + """A MysqlPacket that represents a specific column's metadata in the result. + + Parsing is automatically done and the results are exported via public + attributes on the class such as: db, table_name, name, length, type_code. + """ + + def __init__(self, *args): + MysqlPacket.__init__(self, *args) + self.__parse_field_descriptor() + + def __parse_field_descriptor(self): + """Parse the 'Field Descriptor' (Metadata) packet. + + This is compatible with MySQL 4.1+ (not compatible with MySQL 4.0). + """ + self.catalog = self.read_length_coded_string() + self.db = self.read_length_coded_string() + self.table_name = self.read_length_coded_string() + self.org_table = self.read_length_coded_string() + self.name = self.read_length_coded_string().decode(self.connection.charset) + self.org_name = self.read_length_coded_string() + self.advance(1) # non-null filler + self.charsetnr = struct.unpack(' 2: + use_unicode = True + + if compress or named_pipe: + raise NotImplementedError, "compress and named_pipe arguments are not supported" + + if ssl and (ssl.has_key('capath') or ssl.has_key('cipher')): + raise NotImplementedError, 'ssl options capath and cipher are not supported' + + self.ssl = False + if ssl: + if not SSL_ENABLED: + raise NotImplementedError, "ssl module not found" + self.ssl = True + client_flag |= SSL + for k in ('key', 'cert', 'ca'): + v = None + if ssl.has_key(k): + v = ssl[k] + setattr(self, k, v) + + if read_default_group and not read_default_file: + if sys.platform.startswith("win"): + read_default_file = "c:\\my.ini" + else: + read_default_file = "/etc/my.cnf" + + if read_default_file: + if not read_default_group: + read_default_group = "client" + + cfg = ConfigParser.RawConfigParser() + cfg.read(os.path.expanduser(read_default_file)) + + def _config(key, default): + try: + return cfg.get(read_default_group,key) + except: + return default + + user = _config("user",user) + passwd = _config("password",passwd) + host = _config("host", host) + db = _config("db",db) + unix_socket = _config("socket",unix_socket) + port = int(_config("port", port)) + charset = _config("default-character-set", charset) + + self.host = host + self.port = port + self.user = user or DEFAULT_USER + self.password = passwd + self.db = db + self.no_delay = no_delay + self.unix_socket = unix_socket + if charset: + self.charset = charset + self.use_unicode = True + else: + self.charset = DEFAULT_CHARSET + self.use_unicode = False + + if use_unicode is not None: + self.use_unicode = use_unicode + + client_flag |= CAPABILITIES + client_flag |= MULTI_STATEMENTS + if self.db: + client_flag |= CONNECT_WITH_DB + self.client_flag = client_flag + + self.cursorclass = cursorclass + self.connect_timeout = connect_timeout + + self._result = None + self._affected_rows = 0 + self.host_info = "Not connected" + + self.messages = [] + + self.autocommit_mode = False + self._connect() + + self.set_charset(charset) + self.encoders = encoders + self.decoders = conv + + if sql_mode is not None: + c = self.cursor() + c.execute("SET sql_mode=%s", (sql_mode,)) + + self.commit() + + if init_command is not None: + c = self.cursor() + c.execute(init_command) + + self.commit() + + + def close(self): + ''' Send the quit message and close the socket ''' + if self.socket is None: + raise Error("Already closed") + send_data = struct.pack('= i + 1: + i += 1 + + self.server_capabilities = struct.unpack('= i+12-1: + rest_salt = data[i:i+12] + self.salt += rest_salt + + def get_server_info(self): + return self.server_version + + Warning = Warning + Error = Error + InterfaceError = InterfaceError + DatabaseError = DatabaseError + DataError = DataError + OperationalError = OperationalError + IntegrityError = IntegrityError + InternalError = InternalError + ProgrammingError = ProgrammingError + NotSupportedError = NotSupportedError + +# TODO: move OK and EOF packet parsing/logic into a proper subclass +# of MysqlPacket like has been done with FieldDescriptorPacket. +class MySQLResult(object): + + def __init__(self, connection): + from weakref import proxy + self.connection = proxy(connection) + self.affected_rows = None + self.insert_id = None + self.server_status = 0 + self.warning_count = 0 + self.message = None + self.field_count = 0 + self.description = None + self.rows = None + self.has_next = None + self.unbuffered_active = False + + def __del__(self): + if self.unbuffered_active: + self._finish_unbuffered_query() + + def read(self): + first_packet = self.connection.read_packet() + + # TODO: use classes for different packet types? + if first_packet.is_ok_packet(): + self._read_ok_packet(first_packet) + else: + self._read_result_packet(first_packet) + + def init_unbuffered_query(self): + self.unbuffered_active = True + first_packet = self.connection.read_packet() + + if first_packet.is_ok_packet(): + self._read_ok_packet(first_packet) + self.unbuffered_active = False + else: + self.field_count = byte2int(first_packet.read(1)) + self._get_descriptions() + + # Apparently, MySQLdb picks this number because it's the maximum + # value of a 64bit unsigned integer. Since we're emulating MySQLdb, + # we set it to this instead of None, which would be preferred. + self.affected_rows = 18446744073709551615 + + def _read_ok_packet(self, first_packet): + ok_packet = OKPacketWrapper(first_packet) + self.affected_rows = ok_packet.affected_rows + self.insert_id = ok_packet.insert_id + self.server_status = ok_packet.server_status + self.warning_count = ok_packet.warning_count + self.message = ok_packet.message + + def _check_packet_is_eof(self, packet): + if packet.is_eof_packet(): + eof_packet = EOFPacketWrapper(packet) + self.warning_count = eof_packet.warning_count + self.has_next = eof_packet.has_next + return True + return False + + def _read_result_packet(self, first_packet): + self.field_count = byte2int(first_packet.read(1)) + self._get_descriptions() + self._read_rowdata_packet() + + def _read_rowdata_packet_unbuffered(self): + # Check if in an active query + if self.unbuffered_active == False: return + + # EOF + packet = self.connection.read_packet() + if self._check_packet_is_eof(packet): + self.unbuffered_active = False + self.rows = None + return + + row = [] + for field in self.fields: + data = packet.read_length_coded_string() + converted = None + if field.type_code in self.connection.decoders: + converter = self.connection.decoders[field.type_code] + if DEBUG: print "DEBUG: field=%s, converter=%s" % (field, converter) + if data != None: + converted = converter(self.connection, field, data) + row.append(converted) + + self.affected_rows = 1 + self.rows = tuple((row)) + if DEBUG: self.rows + + def _finish_unbuffered_query(self): + # After much reading on the MySQL protocol, it appears that there is, + # in fact, no way to stop MySQL from sending all the data after + # executing a query, so we just spin, and wait for an EOF packet. + while self.unbuffered_active: + packet = self.connection.read_packet() + if self._check_packet_is_eof(packet): + self.unbuffered_active = False + + # TODO: implement this as an iteratable so that it is more + # memory efficient and lower-latency to client... + def _read_rowdata_packet(self): + """Read a rowdata packet for each data row in the result set.""" + rows = [] + while True: + packet = self.connection.read_packet() + if self._check_packet_is_eof(packet): + break + + row = [] + for field in self.fields: + data = packet.read_length_coded_string() + converted = None + if field.type_code in self.connection.decoders: + converter = self.connection.decoders[field.type_code] + if DEBUG: print "DEBUG: field=%s, converter=%s" % (field, converter) + if data != None: + converted = converter(self.connection, field, data) + row.append(converted) + + rows.append(tuple(row)) + + self.affected_rows = len(rows) + self.rows = tuple(rows) + if DEBUG: self.rows + + def _get_descriptions(self): + """Read a column descriptor packet for each column in the result.""" + self.fields = [] + description = [] + for i in xrange(self.field_count): + field = self.connection.read_packet(FieldDescriptorPacket) + self.fields.append(field) + description.append(field.description()) + + eof_packet = self.connection.read_packet() + assert eof_packet.is_eof_packet(), 'Protocol error, expecting EOF' + self.description = tuple(description) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/CLIENT.py b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/CLIENT.py new file mode 100644 index 0000000..9d11ea1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/CLIENT.py @@ -0,0 +1,20 @@ + +LONG_PASSWORD = 1 +FOUND_ROWS = 1 << 1 +LONG_FLAG = 1 << 2 +CONNECT_WITH_DB = 1 << 3 +NO_SCHEMA = 1 << 4 +COMPRESS = 1 << 5 +ODBC = 1 << 6 +LOCAL_FILES = 1 << 7 +IGNORE_SPACE = 1 << 8 +PROTOCOL_41 = 1 << 9 +INTERACTIVE = 1 << 10 +SSL = 1 << 11 +IGNORE_SIGPIPE = 1 << 12 +TRANSACTIONS = 1 << 13 +SECURE_CONNECTION = 1 << 15 +MULTI_STATEMENTS = 1 << 16 +MULTI_RESULTS = 1 << 17 +CAPABILITIES = LONG_PASSWORD|LONG_FLAG|TRANSACTIONS| \ + PROTOCOL_41|SECURE_CONNECTION diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/COMMAND.py b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/COMMAND.py new file mode 100644 index 0000000..4a757da --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/COMMAND.py @@ -0,0 +1,23 @@ + +COM_SLEEP = 0x00 +COM_QUIT = 0x01 +COM_INIT_DB = 0x02 +COM_QUERY = 0x03 +COM_FIELD_LIST = 0x04 +COM_CREATE_DB = 0x05 +COM_DROP_DB = 0x06 +COM_REFRESH = 0x07 +COM_SHUTDOWN = 0x08 +COM_STATISTICS = 0x09 +COM_PROCESS_INFO = 0x0a +COM_CONNECT = 0x0b +COM_PROCESS_KILL = 0x0c +COM_DEBUG = 0x0d +COM_PING = 0x0e +COM_TIME = 0x0f +COM_DELAYED_INSERT = 0x10 +COM_CHANGE_USER = 0x11 +COM_BINLOG_DUMP = 0x12 +COM_TABLE_DUMP = 0x13 +COM_CONNECT_OUT = 0x14 +COM_REGISTER_SLAVE = 0x15 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/ER.py b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/ER.py new file mode 100644 index 0000000..553983f --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/ER.py @@ -0,0 +1,472 @@ + +ERROR_FIRST = 1000 +HASHCHK = 1000 +NISAMCHK = 1001 +NO = 1002 +YES = 1003 +CANT_CREATE_FILE = 1004 +CANT_CREATE_TABLE = 1005 +CANT_CREATE_DB = 1006 +DB_CREATE_EXISTS = 1007 +DB_DROP_EXISTS = 1008 +DB_DROP_DELETE = 1009 +DB_DROP_RMDIR = 1010 +CANT_DELETE_FILE = 1011 +CANT_FIND_SYSTEM_REC = 1012 +CANT_GET_STAT = 1013 +CANT_GET_WD = 1014 +CANT_LOCK = 1015 +CANT_OPEN_FILE = 1016 +FILE_NOT_FOUND = 1017 +CANT_READ_DIR = 1018 +CANT_SET_WD = 1019 +CHECKREAD = 1020 +DISK_FULL = 1021 +DUP_KEY = 1022 +ERROR_ON_CLOSE = 1023 +ERROR_ON_READ = 1024 +ERROR_ON_RENAME = 1025 +ERROR_ON_WRITE = 1026 +FILE_USED = 1027 +FILSORT_ABORT = 1028 +FORM_NOT_FOUND = 1029 +GET_ERRNO = 1030 +ILLEGAL_HA = 1031 +KEY_NOT_FOUND = 1032 +NOT_FORM_FILE = 1033 +NOT_KEYFILE = 1034 +OLD_KEYFILE = 1035 +OPEN_AS_READONLY = 1036 +OUTOFMEMORY = 1037 +OUT_OF_SORTMEMORY = 1038 +UNEXPECTED_EOF = 1039 +CON_COUNT_ERROR = 1040 +OUT_OF_RESOURCES = 1041 +BAD_HOST_ERROR = 1042 +HANDSHAKE_ERROR = 1043 +DBACCESS_DENIED_ERROR = 1044 +ACCESS_DENIED_ERROR = 1045 +NO_DB_ERROR = 1046 +UNKNOWN_COM_ERROR = 1047 +BAD_NULL_ERROR = 1048 +BAD_DB_ERROR = 1049 +TABLE_EXISTS_ERROR = 1050 +BAD_TABLE_ERROR = 1051 +NON_UNIQ_ERROR = 1052 +SERVER_SHUTDOWN = 1053 +BAD_FIELD_ERROR = 1054 +WRONG_FIELD_WITH_GROUP = 1055 +WRONG_GROUP_FIELD = 1056 +WRONG_SUM_SELECT = 1057 +WRONG_VALUE_COUNT = 1058 +TOO_LONG_IDENT = 1059 +DUP_FIELDNAME = 1060 +DUP_KEYNAME = 1061 +DUP_ENTRY = 1062 +WRONG_FIELD_SPEC = 1063 +PARSE_ERROR = 1064 +EMPTY_QUERY = 1065 +NONUNIQ_TABLE = 1066 +INVALID_DEFAULT = 1067 +MULTIPLE_PRI_KEY = 1068 +TOO_MANY_KEYS = 1069 +TOO_MANY_KEY_PARTS = 1070 +TOO_LONG_KEY = 1071 +KEY_COLUMN_DOES_NOT_EXITS = 1072 +BLOB_USED_AS_KEY = 1073 +TOO_BIG_FIELDLENGTH = 1074 +WRONG_AUTO_KEY = 1075 +READY = 1076 +NORMAL_SHUTDOWN = 1077 +GOT_SIGNAL = 1078 +SHUTDOWN_COMPLETE = 1079 +FORCING_CLOSE = 1080 +IPSOCK_ERROR = 1081 +NO_SUCH_INDEX = 1082 +WRONG_FIELD_TERMINATORS = 1083 +BLOBS_AND_NO_TERMINATED = 1084 +TEXTFILE_NOT_READABLE = 1085 +FILE_EXISTS_ERROR = 1086 +LOAD_INFO = 1087 +ALTER_INFO = 1088 +WRONG_SUB_KEY = 1089 +CANT_REMOVE_ALL_FIELDS = 1090 +CANT_DROP_FIELD_OR_KEY = 1091 +INSERT_INFO = 1092 +UPDATE_TABLE_USED = 1093 +NO_SUCH_THREAD = 1094 +KILL_DENIED_ERROR = 1095 +NO_TABLES_USED = 1096 +TOO_BIG_SET = 1097 +NO_UNIQUE_LOGFILE = 1098 +TABLE_NOT_LOCKED_FOR_WRITE = 1099 +TABLE_NOT_LOCKED = 1100 +BLOB_CANT_HAVE_DEFAULT = 1101 +WRONG_DB_NAME = 1102 +WRONG_TABLE_NAME = 1103 +TOO_BIG_SELECT = 1104 +UNKNOWN_ERROR = 1105 +UNKNOWN_PROCEDURE = 1106 +WRONG_PARAMCOUNT_TO_PROCEDURE = 1107 +WRONG_PARAMETERS_TO_PROCEDURE = 1108 +UNKNOWN_TABLE = 1109 +FIELD_SPECIFIED_TWICE = 1110 +INVALID_GROUP_FUNC_USE = 1111 +UNSUPPORTED_EXTENSION = 1112 +TABLE_MUST_HAVE_COLUMNS = 1113 +RECORD_FILE_FULL = 1114 +UNKNOWN_CHARACTER_SET = 1115 +TOO_MANY_TABLES = 1116 +TOO_MANY_FIELDS = 1117 +TOO_BIG_ROWSIZE = 1118 +STACK_OVERRUN = 1119 +WRONG_OUTER_JOIN = 1120 +NULL_COLUMN_IN_INDEX = 1121 +CANT_FIND_UDF = 1122 +CANT_INITIALIZE_UDF = 1123 +UDF_NO_PATHS = 1124 +UDF_EXISTS = 1125 +CANT_OPEN_LIBRARY = 1126 +CANT_FIND_DL_ENTRY = 1127 +FUNCTION_NOT_DEFINED = 1128 +HOST_IS_BLOCKED = 1129 +HOST_NOT_PRIVILEGED = 1130 +PASSWORD_ANONYMOUS_USER = 1131 +PASSWORD_NOT_ALLOWED = 1132 +PASSWORD_NO_MATCH = 1133 +UPDATE_INFO = 1134 +CANT_CREATE_THREAD = 1135 +WRONG_VALUE_COUNT_ON_ROW = 1136 +CANT_REOPEN_TABLE = 1137 +INVALID_USE_OF_NULL = 1138 +REGEXP_ERROR = 1139 +MIX_OF_GROUP_FUNC_AND_FIELDS = 1140 +NONEXISTING_GRANT = 1141 +TABLEACCESS_DENIED_ERROR = 1142 +COLUMNACCESS_DENIED_ERROR = 1143 +ILLEGAL_GRANT_FOR_TABLE = 1144 +GRANT_WRONG_HOST_OR_USER = 1145 +NO_SUCH_TABLE = 1146 +NONEXISTING_TABLE_GRANT = 1147 +NOT_ALLOWED_COMMAND = 1148 +SYNTAX_ERROR = 1149 +DELAYED_CANT_CHANGE_LOCK = 1150 +TOO_MANY_DELAYED_THREADS = 1151 +ABORTING_CONNECTION = 1152 +NET_PACKET_TOO_LARGE = 1153 +NET_READ_ERROR_FROM_PIPE = 1154 +NET_FCNTL_ERROR = 1155 +NET_PACKETS_OUT_OF_ORDER = 1156 +NET_UNCOMPRESS_ERROR = 1157 +NET_READ_ERROR = 1158 +NET_READ_INTERRUPTED = 1159 +NET_ERROR_ON_WRITE = 1160 +NET_WRITE_INTERRUPTED = 1161 +TOO_LONG_STRING = 1162 +TABLE_CANT_HANDLE_BLOB = 1163 +TABLE_CANT_HANDLE_AUTO_INCREMENT = 1164 +DELAYED_INSERT_TABLE_LOCKED = 1165 +WRONG_COLUMN_NAME = 1166 +WRONG_KEY_COLUMN = 1167 +WRONG_MRG_TABLE = 1168 +DUP_UNIQUE = 1169 +BLOB_KEY_WITHOUT_LENGTH = 1170 +PRIMARY_CANT_HAVE_NULL = 1171 +TOO_MANY_ROWS = 1172 +REQUIRES_PRIMARY_KEY = 1173 +NO_RAID_COMPILED = 1174 +UPDATE_WITHOUT_KEY_IN_SAFE_MODE = 1175 +KEY_DOES_NOT_EXITS = 1176 +CHECK_NO_SUCH_TABLE = 1177 +CHECK_NOT_IMPLEMENTED = 1178 +CANT_DO_THIS_DURING_AN_TRANSACTION = 1179 +ERROR_DURING_COMMIT = 1180 +ERROR_DURING_ROLLBACK = 1181 +ERROR_DURING_FLUSH_LOGS = 1182 +ERROR_DURING_CHECKPOINT = 1183 +NEW_ABORTING_CONNECTION = 1184 +DUMP_NOT_IMPLEMENTED = 1185 +FLUSH_MASTER_BINLOG_CLOSED = 1186 +INDEX_REBUILD = 1187 +MASTER = 1188 +MASTER_NET_READ = 1189 +MASTER_NET_WRITE = 1190 +FT_MATCHING_KEY_NOT_FOUND = 1191 +LOCK_OR_ACTIVE_TRANSACTION = 1192 +UNKNOWN_SYSTEM_VARIABLE = 1193 +CRASHED_ON_USAGE = 1194 +CRASHED_ON_REPAIR = 1195 +WARNING_NOT_COMPLETE_ROLLBACK = 1196 +TRANS_CACHE_FULL = 1197 +SLAVE_MUST_STOP = 1198 +SLAVE_NOT_RUNNING = 1199 +BAD_SLAVE = 1200 +MASTER_INFO = 1201 +SLAVE_THREAD = 1202 +TOO_MANY_USER_CONNECTIONS = 1203 +SET_CONSTANTS_ONLY = 1204 +LOCK_WAIT_TIMEOUT = 1205 +LOCK_TABLE_FULL = 1206 +READ_ONLY_TRANSACTION = 1207 +DROP_DB_WITH_READ_LOCK = 1208 +CREATE_DB_WITH_READ_LOCK = 1209 +WRONG_ARGUMENTS = 1210 +NO_PERMISSION_TO_CREATE_USER = 1211 +UNION_TABLES_IN_DIFFERENT_DIR = 1212 +LOCK_DEADLOCK = 1213 +TABLE_CANT_HANDLE_FT = 1214 +CANNOT_ADD_FOREIGN = 1215 +NO_REFERENCED_ROW = 1216 +ROW_IS_REFERENCED = 1217 +CONNECT_TO_MASTER = 1218 +QUERY_ON_MASTER = 1219 +ERROR_WHEN_EXECUTING_COMMAND = 1220 +WRONG_USAGE = 1221 +WRONG_NUMBER_OF_COLUMNS_IN_SELECT = 1222 +CANT_UPDATE_WITH_READLOCK = 1223 +MIXING_NOT_ALLOWED = 1224 +DUP_ARGUMENT = 1225 +USER_LIMIT_REACHED = 1226 +SPECIFIC_ACCESS_DENIED_ERROR = 1227 +LOCAL_VARIABLE = 1228 +GLOBAL_VARIABLE = 1229 +NO_DEFAULT = 1230 +WRONG_VALUE_FOR_VAR = 1231 +WRONG_TYPE_FOR_VAR = 1232 +VAR_CANT_BE_READ = 1233 +CANT_USE_OPTION_HERE = 1234 +NOT_SUPPORTED_YET = 1235 +MASTER_FATAL_ERROR_READING_BINLOG = 1236 +SLAVE_IGNORED_TABLE = 1237 +INCORRECT_GLOBAL_LOCAL_VAR = 1238 +WRONG_FK_DEF = 1239 +KEY_REF_DO_NOT_MATCH_TABLE_REF = 1240 +OPERAND_COLUMNS = 1241 +SUBQUERY_NO_1_ROW = 1242 +UNKNOWN_STMT_HANDLER = 1243 +CORRUPT_HELP_DB = 1244 +CYCLIC_REFERENCE = 1245 +AUTO_CONVERT = 1246 +ILLEGAL_REFERENCE = 1247 +DERIVED_MUST_HAVE_ALIAS = 1248 +SELECT_REDUCED = 1249 +TABLENAME_NOT_ALLOWED_HERE = 1250 +NOT_SUPPORTED_AUTH_MODE = 1251 +SPATIAL_CANT_HAVE_NULL = 1252 +COLLATION_CHARSET_MISMATCH = 1253 +SLAVE_WAS_RUNNING = 1254 +SLAVE_WAS_NOT_RUNNING = 1255 +TOO_BIG_FOR_UNCOMPRESS = 1256 +ZLIB_Z_MEM_ERROR = 1257 +ZLIB_Z_BUF_ERROR = 1258 +ZLIB_Z_DATA_ERROR = 1259 +CUT_VALUE_GROUP_CONCAT = 1260 +WARN_TOO_FEW_RECORDS = 1261 +WARN_TOO_MANY_RECORDS = 1262 +WARN_NULL_TO_NOTNULL = 1263 +WARN_DATA_OUT_OF_RANGE = 1264 +WARN_DATA_TRUNCATED = 1265 +WARN_USING_OTHER_HANDLER = 1266 +CANT_AGGREGATE_2COLLATIONS = 1267 +DROP_USER = 1268 +REVOKE_GRANTS = 1269 +CANT_AGGREGATE_3COLLATIONS = 1270 +CANT_AGGREGATE_NCOLLATIONS = 1271 +VARIABLE_IS_NOT_STRUCT = 1272 +UNKNOWN_COLLATION = 1273 +SLAVE_IGNORED_SSL_PARAMS = 1274 +SERVER_IS_IN_SECURE_AUTH_MODE = 1275 +WARN_FIELD_RESOLVED = 1276 +BAD_SLAVE_UNTIL_COND = 1277 +MISSING_SKIP_SLAVE = 1278 +UNTIL_COND_IGNORED = 1279 +WRONG_NAME_FOR_INDEX = 1280 +WRONG_NAME_FOR_CATALOG = 1281 +WARN_QC_RESIZE = 1282 +BAD_FT_COLUMN = 1283 +UNKNOWN_KEY_CACHE = 1284 +WARN_HOSTNAME_WONT_WORK = 1285 +UNKNOWN_STORAGE_ENGINE = 1286 +WARN_DEPRECATED_SYNTAX = 1287 +NON_UPDATABLE_TABLE = 1288 +FEATURE_DISABLED = 1289 +OPTION_PREVENTS_STATEMENT = 1290 +DUPLICATED_VALUE_IN_TYPE = 1291 +TRUNCATED_WRONG_VALUE = 1292 +TOO_MUCH_AUTO_TIMESTAMP_COLS = 1293 +INVALID_ON_UPDATE = 1294 +UNSUPPORTED_PS = 1295 +GET_ERRMSG = 1296 +GET_TEMPORARY_ERRMSG = 1297 +UNKNOWN_TIME_ZONE = 1298 +WARN_INVALID_TIMESTAMP = 1299 +INVALID_CHARACTER_STRING = 1300 +WARN_ALLOWED_PACKET_OVERFLOWED = 1301 +CONFLICTING_DECLARATIONS = 1302 +SP_NO_RECURSIVE_CREATE = 1303 +SP_ALREADY_EXISTS = 1304 +SP_DOES_NOT_EXIST = 1305 +SP_DROP_FAILED = 1306 +SP_STORE_FAILED = 1307 +SP_LILABEL_MISMATCH = 1308 +SP_LABEL_REDEFINE = 1309 +SP_LABEL_MISMATCH = 1310 +SP_UNINIT_VAR = 1311 +SP_BADSELECT = 1312 +SP_BADRETURN = 1313 +SP_BADSTATEMENT = 1314 +UPDATE_LOG_DEPRECATED_IGNORED = 1315 +UPDATE_LOG_DEPRECATED_TRANSLATED = 1316 +QUERY_INTERRUPTED = 1317 +SP_WRONG_NO_OF_ARGS = 1318 +SP_COND_MISMATCH = 1319 +SP_NORETURN = 1320 +SP_NORETURNEND = 1321 +SP_BAD_CURSOR_QUERY = 1322 +SP_BAD_CURSOR_SELECT = 1323 +SP_CURSOR_MISMATCH = 1324 +SP_CURSOR_ALREADY_OPEN = 1325 +SP_CURSOR_NOT_OPEN = 1326 +SP_UNDECLARED_VAR = 1327 +SP_WRONG_NO_OF_FETCH_ARGS = 1328 +SP_FETCH_NO_DATA = 1329 +SP_DUP_PARAM = 1330 +SP_DUP_VAR = 1331 +SP_DUP_COND = 1332 +SP_DUP_CURS = 1333 +SP_CANT_ALTER = 1334 +SP_SUBSELECT_NYI = 1335 +STMT_NOT_ALLOWED_IN_SF_OR_TRG = 1336 +SP_VARCOND_AFTER_CURSHNDLR = 1337 +SP_CURSOR_AFTER_HANDLER = 1338 +SP_CASE_NOT_FOUND = 1339 +FPARSER_TOO_BIG_FILE = 1340 +FPARSER_BAD_HEADER = 1341 +FPARSER_EOF_IN_COMMENT = 1342 +FPARSER_ERROR_IN_PARAMETER = 1343 +FPARSER_EOF_IN_UNKNOWN_PARAMETER = 1344 +VIEW_NO_EXPLAIN = 1345 +FRM_UNKNOWN_TYPE = 1346 +WRONG_OBJECT = 1347 +NONUPDATEABLE_COLUMN = 1348 +VIEW_SELECT_DERIVED = 1349 +VIEW_SELECT_CLAUSE = 1350 +VIEW_SELECT_VARIABLE = 1351 +VIEW_SELECT_TMPTABLE = 1352 +VIEW_WRONG_LIST = 1353 +WARN_VIEW_MERGE = 1354 +WARN_VIEW_WITHOUT_KEY = 1355 +VIEW_INVALID = 1356 +SP_NO_DROP_SP = 1357 +SP_GOTO_IN_HNDLR = 1358 +TRG_ALREADY_EXISTS = 1359 +TRG_DOES_NOT_EXIST = 1360 +TRG_ON_VIEW_OR_TEMP_TABLE = 1361 +TRG_CANT_CHANGE_ROW = 1362 +TRG_NO_SUCH_ROW_IN_TRG = 1363 +NO_DEFAULT_FOR_FIELD = 1364 +DIVISION_BY_ZERO = 1365 +TRUNCATED_WRONG_VALUE_FOR_FIELD = 1366 +ILLEGAL_VALUE_FOR_TYPE = 1367 +VIEW_NONUPD_CHECK = 1368 +VIEW_CHECK_FAILED = 1369 +PROCACCESS_DENIED_ERROR = 1370 +RELAY_LOG_FAIL = 1371 +PASSWD_LENGTH = 1372 +UNKNOWN_TARGET_BINLOG = 1373 +IO_ERR_LOG_INDEX_READ = 1374 +BINLOG_PURGE_PROHIBITED = 1375 +FSEEK_FAIL = 1376 +BINLOG_PURGE_FATAL_ERR = 1377 +LOG_IN_USE = 1378 +LOG_PURGE_UNKNOWN_ERR = 1379 +RELAY_LOG_INIT = 1380 +NO_BINARY_LOGGING = 1381 +RESERVED_SYNTAX = 1382 +WSAS_FAILED = 1383 +DIFF_GROUPS_PROC = 1384 +NO_GROUP_FOR_PROC = 1385 +ORDER_WITH_PROC = 1386 +LOGGING_PROHIBIT_CHANGING_OF = 1387 +NO_FILE_MAPPING = 1388 +WRONG_MAGIC = 1389 +PS_MANY_PARAM = 1390 +KEY_PART_0 = 1391 +VIEW_CHECKSUM = 1392 +VIEW_MULTIUPDATE = 1393 +VIEW_NO_INSERT_FIELD_LIST = 1394 +VIEW_DELETE_MERGE_VIEW = 1395 +CANNOT_USER = 1396 +XAER_NOTA = 1397 +XAER_INVAL = 1398 +XAER_RMFAIL = 1399 +XAER_OUTSIDE = 1400 +XAER_RMERR = 1401 +XA_RBROLLBACK = 1402 +NONEXISTING_PROC_GRANT = 1403 +PROC_AUTO_GRANT_FAIL = 1404 +PROC_AUTO_REVOKE_FAIL = 1405 +DATA_TOO_LONG = 1406 +SP_BAD_SQLSTATE = 1407 +STARTUP = 1408 +LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR = 1409 +CANT_CREATE_USER_WITH_GRANT = 1410 +WRONG_VALUE_FOR_TYPE = 1411 +TABLE_DEF_CHANGED = 1412 +SP_DUP_HANDLER = 1413 +SP_NOT_VAR_ARG = 1414 +SP_NO_RETSET = 1415 +CANT_CREATE_GEOMETRY_OBJECT = 1416 +FAILED_ROUTINE_BREAK_BINLOG = 1417 +BINLOG_UNSAFE_ROUTINE = 1418 +BINLOG_CREATE_ROUTINE_NEED_SUPER = 1419 +EXEC_STMT_WITH_OPEN_CURSOR = 1420 +STMT_HAS_NO_OPEN_CURSOR = 1421 +COMMIT_NOT_ALLOWED_IN_SF_OR_TRG = 1422 +NO_DEFAULT_FOR_VIEW_FIELD = 1423 +SP_NO_RECURSION = 1424 +TOO_BIG_SCALE = 1425 +TOO_BIG_PRECISION = 1426 +M_BIGGER_THAN_D = 1427 +WRONG_LOCK_OF_SYSTEM_TABLE = 1428 +CONNECT_TO_FOREIGN_DATA_SOURCE = 1429 +QUERY_ON_FOREIGN_DATA_SOURCE = 1430 +FOREIGN_DATA_SOURCE_DOESNT_EXIST = 1431 +FOREIGN_DATA_STRING_INVALID_CANT_CREATE = 1432 +FOREIGN_DATA_STRING_INVALID = 1433 +CANT_CREATE_FEDERATED_TABLE = 1434 +TRG_IN_WRONG_SCHEMA = 1435 +STACK_OVERRUN_NEED_MORE = 1436 +TOO_LONG_BODY = 1437 +WARN_CANT_DROP_DEFAULT_KEYCACHE = 1438 +TOO_BIG_DISPLAYWIDTH = 1439 +XAER_DUPID = 1440 +DATETIME_FUNCTION_OVERFLOW = 1441 +CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG = 1442 +VIEW_PREVENT_UPDATE = 1443 +PS_NO_RECURSION = 1444 +SP_CANT_SET_AUTOCOMMIT = 1445 +MALFORMED_DEFINER = 1446 +VIEW_FRM_NO_USER = 1447 +VIEW_OTHER_USER = 1448 +NO_SUCH_USER = 1449 +FORBID_SCHEMA_CHANGE = 1450 +ROW_IS_REFERENCED_2 = 1451 +NO_REFERENCED_ROW_2 = 1452 +SP_BAD_VAR_SHADOW = 1453 +TRG_NO_DEFINER = 1454 +OLD_FILE_FORMAT = 1455 +SP_RECURSION_LIMIT = 1456 +SP_PROC_TABLE_CORRUPT = 1457 +SP_WRONG_NAME = 1458 +TABLE_NEEDS_UPGRADE = 1459 +SP_NO_AGGREGATE = 1460 +MAX_PREPARED_STMT_COUNT_REACHED = 1461 +VIEW_RECURSIVE = 1462 +NON_GROUPING_FIELD_USED = 1463 +TABLE_CANT_HANDLE_SPKEYS = 1464 +NO_TRIGGERS_ON_SYSTEM_SCHEMA = 1465 +USERNAME = 1466 +HOSTNAME = 1467 +WRONG_STRING_LENGTH = 1468 +ERROR_LAST = 1468 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/FIELD_TYPE.py b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/FIELD_TYPE.py new file mode 100644 index 0000000..3df7ff4 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/FIELD_TYPE.py @@ -0,0 +1,32 @@ + + +DECIMAL = 0 +TINY = 1 +SHORT = 2 +LONG = 3 +FLOAT = 4 +DOUBLE = 5 +NULL = 6 +TIMESTAMP = 7 +LONGLONG = 8 +INT24 = 9 +DATE = 10 +TIME = 11 +DATETIME = 12 +YEAR = 13 +NEWDATE = 14 +VARCHAR = 15 +BIT = 16 +NEWDECIMAL = 246 +ENUM = 247 +SET = 248 +TINY_BLOB = 249 +MEDIUM_BLOB = 250 +LONG_BLOB = 251 +BLOB = 252 +VAR_STRING = 253 +STRING = 254 +GEOMETRY = 255 + +CHAR = TINY +INTERVAL = ENUM diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/FLAG.py b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/FLAG.py new file mode 100644 index 0000000..f9ebfad --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/FLAG.py @@ -0,0 +1,15 @@ +NOT_NULL = 1 +PRI_KEY = 2 +UNIQUE_KEY = 4 +MULTIPLE_KEY = 8 +BLOB = 16 +UNSIGNED = 32 +ZEROFILL = 64 +BINARY = 128 +ENUM = 256 +AUTO_INCREMENT = 512 +TIMESTAMP = 1024 +SET = 2048 +PART_KEY = 16384 +GROUP = 32767 +UNIQUE = 65536 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/SERVER_STATUS.py b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/SERVER_STATUS.py new file mode 100644 index 0000000..010f542 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/SERVER_STATUS.py @@ -0,0 +1,12 @@ + +SERVER_STATUS_IN_TRANS = 1 +SERVER_STATUS_AUTOCOMMIT = 2 +SERVER_MORE_RESULTS_EXISTS = 8 +SERVER_QUERY_NO_GOOD_INDEX_USED = 16 +SERVER_QUERY_NO_INDEX_USED = 32 +SERVER_STATUS_CURSOR_EXISTS = 64 +SERVER_STATUS_LAST_ROW_SENT = 128 +SERVER_STATUS_DB_DROPPED = 256 +SERVER_STATUS_NO_BACKSLASH_ESCAPES = 512 +SERVER_STATUS_METADATA_CHANGED = 1024 + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/constants/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/converters.py b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/converters.py new file mode 100644 index 0000000..f08fdf0 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/converters.py @@ -0,0 +1,356 @@ +import re +import datetime +import time +import sys + +from constants import FIELD_TYPE, FLAG +from charset import charset_by_id + +PYTHON3 = sys.version_info[0] > 2 + +try: + set +except NameError: + try: + from sets import BaseSet as set + except ImportError: + from sets import Set as set + +ESCAPE_REGEX = re.compile(r"[\0\n\r\032\'\"\\]") +ESCAPE_MAP = {'\0': '\\0', '\n': '\\n', '\r': '\\r', '\032': '\\Z', + '\'': '\\\'', '"': '\\"', '\\': '\\\\'} + +def escape_item(val, charset): + if type(val) in [tuple, list, set]: + return escape_sequence(val, charset) + if type(val) is dict: + return escape_dict(val, charset) + if PYTHON3 and hasattr(val, "decode") and not isinstance(val, unicode): + # deal with py3k bytes + val = val.decode(charset) + encoder = encoders[type(val)] + val = encoder(val) + if type(val) in [str, int, unicode]: + return val + val = val.encode(charset) + return val + +def escape_dict(val, charset): + n = {} + for k, v in val.items(): + quoted = escape_item(v, charset) + n[k] = quoted + return n + +def escape_sequence(val, charset): + n = [] + for item in val: + quoted = escape_item(item, charset) + n.append(quoted) + return "(" + ",".join(n) + ")" + +def escape_set(val, charset): + val = map(lambda x: escape_item(x, charset), val) + return ','.join(val) + +def escape_bool(value): + return str(int(value)) + +def escape_object(value): + return str(value) + +def escape_int(value): + return value + +escape_long = escape_object + +def escape_float(value): + return ('%.15g' % value) + +def escape_string(value): + return ("'%s'" % ESCAPE_REGEX.sub( + lambda match: ESCAPE_MAP.get(match.group(0)), value)) + +def escape_unicode(value): + return escape_string(value) + +def escape_None(value): + return 'NULL' + +def escape_timedelta(obj): + seconds = int(obj.seconds) % 60 + minutes = int(obj.seconds // 60) % 60 + hours = int(obj.seconds // 3600) % 24 + int(obj.days) * 24 + return escape_string('%02d:%02d:%02d' % (hours, minutes, seconds)) + +def escape_time(obj): + s = "%02d:%02d:%02d" % (int(obj.hour), int(obj.minute), + int(obj.second)) + if obj.microsecond: + s += ".%f" % obj.microsecond + + return escape_string(s) + +def escape_datetime(obj): + return escape_string(obj.strftime("%Y-%m-%d %H:%M:%S")) + +def escape_date(obj): + return escape_string(obj.strftime("%Y-%m-%d")) + +def escape_struct_time(obj): + return escape_datetime(datetime.datetime(*obj[:6])) + +def convert_datetime(connection, field, obj): + """Returns a DATETIME or TIMESTAMP column value as a datetime object: + + >>> datetime_or_None('2007-02-25 23:06:20') + datetime.datetime(2007, 2, 25, 23, 6, 20) + >>> datetime_or_None('2007-02-25T23:06:20') + datetime.datetime(2007, 2, 25, 23, 6, 20) + + Illegal values are returned as None: + + >>> datetime_or_None('2007-02-31T23:06:20') is None + True + >>> datetime_or_None('0000-00-00 00:00:00') is None + True + + """ + if not isinstance(obj, unicode): + obj = obj.decode(connection.charset) + if ' ' in obj: + sep = ' ' + elif 'T' in obj: + sep = 'T' + else: + return convert_date(connection, field, obj) + + try: + ymd, hms = obj.split(sep, 1) + return datetime.datetime(*[ int(x) for x in ymd.split('-')+hms.split(':') ]) + except ValueError: + return convert_date(connection, field, obj) + +def convert_timedelta(connection, field, obj): + """Returns a TIME column as a timedelta object: + + >>> timedelta_or_None('25:06:17') + datetime.timedelta(1, 3977) + >>> timedelta_or_None('-25:06:17') + datetime.timedelta(-2, 83177) + + Illegal values are returned as None: + + >>> timedelta_or_None('random crap') is None + True + + Note that MySQL always returns TIME columns as (+|-)HH:MM:SS, but + can accept values as (+|-)DD HH:MM:SS. The latter format will not + be parsed correctly by this function. + """ + try: + microseconds = 0 + if not isinstance(obj, unicode): + obj = obj.decode(connection.charset) + if "." in obj: + (obj, tail) = obj.split('.') + microseconds = int(tail) + hours, minutes, seconds = obj.split(':') + tdelta = datetime.timedelta( + hours = int(hours), + minutes = int(minutes), + seconds = int(seconds), + microseconds = microseconds + ) + return tdelta + except ValueError: + return None + +def convert_time(connection, field, obj): + """Returns a TIME column as a time object: + + >>> time_or_None('15:06:17') + datetime.time(15, 6, 17) + + Illegal values are returned as None: + + >>> time_or_None('-25:06:17') is None + True + >>> time_or_None('random crap') is None + True + + Note that MySQL always returns TIME columns as (+|-)HH:MM:SS, but + can accept values as (+|-)DD HH:MM:SS. The latter format will not + be parsed correctly by this function. + + Also note that MySQL's TIME column corresponds more closely to + Python's timedelta and not time. However if you want TIME columns + to be treated as time-of-day and not a time offset, then you can + use set this function as the converter for FIELD_TYPE.TIME. + """ + try: + microseconds = 0 + if "." in obj: + (obj, tail) = obj.split('.') + microseconds = int(tail) + hours, minutes, seconds = obj.split(':') + return datetime.time(hour=int(hours), minute=int(minutes), + second=int(seconds), microsecond=microseconds) + except ValueError: + return None + +def convert_date(connection, field, obj): + """Returns a DATE column as a date object: + + >>> date_or_None('2007-02-26') + datetime.date(2007, 2, 26) + + Illegal values are returned as None: + + >>> date_or_None('2007-02-31') is None + True + >>> date_or_None('0000-00-00') is None + True + + """ + try: + if not isinstance(obj, unicode): + obj = obj.decode(connection.charset) + return datetime.date(*[ int(x) for x in obj.split('-', 2) ]) + except ValueError: + return None + +def convert_mysql_timestamp(connection, field, timestamp): + """Convert a MySQL TIMESTAMP to a Timestamp object. + + MySQL >= 4.1 returns TIMESTAMP in the same format as DATETIME: + + >>> mysql_timestamp_converter('2007-02-25 22:32:17') + datetime.datetime(2007, 2, 25, 22, 32, 17) + + MySQL < 4.1 uses a big string of numbers: + + >>> mysql_timestamp_converter('20070225223217') + datetime.datetime(2007, 2, 25, 22, 32, 17) + + Illegal values are returned as None: + + >>> mysql_timestamp_converter('2007-02-31 22:32:17') is None + True + >>> mysql_timestamp_converter('00000000000000') is None + True + + """ + if not isinstance(timestamp, unicode): + timestamp = timestamp.decode(connection.charset) + + if timestamp[4] == '-': + return convert_datetime(connection, field, timestamp) + timestamp += "0"*(14-len(timestamp)) # padding + year, month, day, hour, minute, second = \ + int(timestamp[:4]), int(timestamp[4:6]), int(timestamp[6:8]), \ + int(timestamp[8:10]), int(timestamp[10:12]), int(timestamp[12:14]) + try: + return datetime.datetime(year, month, day, hour, minute, second) + except ValueError: + return None + +def convert_set(s): + return set(s.split(",")) + +def convert_bit(connection, field, b): + #b = "\x00" * (8 - len(b)) + b # pad w/ zeroes + #return struct.unpack(">Q", b)[0] + # + # the snippet above is right, but MySQLdb doesn't process bits, + # so we shouldn't either + return b + +def convert_characters(connection, field, data): + field_charset = charset_by_id(field.charsetnr).name + if field.flags & FLAG.SET: + return convert_set(data.decode(field_charset)) + if field.flags & FLAG.BINARY: + return data + + if connection.use_unicode: + data = data.decode(field_charset) + elif connection.charset != field_charset: + data = data.decode(field_charset) + data = data.encode(connection.charset) + return data + +def convert_int(connection, field, data): + return int(data) + +def convert_long(connection, field, data): + return long(data) + +def convert_float(connection, field, data): + return float(data) + +encoders = { + bool: escape_bool, + int: escape_int, + long: escape_long, + float: escape_float, + str: escape_string, + unicode: escape_unicode, + tuple: escape_sequence, + list:escape_sequence, + set:escape_sequence, + dict:escape_dict, + type(None):escape_None, + datetime.date: escape_date, + datetime.datetime : escape_datetime, + datetime.timedelta : escape_timedelta, + datetime.time : escape_time, + time.struct_time : escape_struct_time, + } + +decoders = { + FIELD_TYPE.BIT: convert_bit, + FIELD_TYPE.TINY: convert_int, + FIELD_TYPE.SHORT: convert_int, + FIELD_TYPE.LONG: convert_long, + FIELD_TYPE.FLOAT: convert_float, + FIELD_TYPE.DOUBLE: convert_float, + FIELD_TYPE.DECIMAL: convert_float, + FIELD_TYPE.NEWDECIMAL: convert_float, + FIELD_TYPE.LONGLONG: convert_long, + FIELD_TYPE.INT24: convert_int, + FIELD_TYPE.YEAR: convert_int, + FIELD_TYPE.TIMESTAMP: convert_mysql_timestamp, + FIELD_TYPE.DATETIME: convert_datetime, + FIELD_TYPE.TIME: convert_timedelta, + FIELD_TYPE.DATE: convert_date, + FIELD_TYPE.SET: convert_set, + FIELD_TYPE.BLOB: convert_characters, + FIELD_TYPE.TINY_BLOB: convert_characters, + FIELD_TYPE.MEDIUM_BLOB: convert_characters, + FIELD_TYPE.LONG_BLOB: convert_characters, + FIELD_TYPE.STRING: convert_characters, + FIELD_TYPE.VAR_STRING: convert_characters, + FIELD_TYPE.VARCHAR: convert_characters, + #FIELD_TYPE.BLOB: str, + #FIELD_TYPE.STRING: str, + #FIELD_TYPE.VAR_STRING: str, + #FIELD_TYPE.VARCHAR: str + } +conversions = decoders # for MySQLdb compatibility + +try: + # python version > 2.3 + from decimal import Decimal + def convert_decimal(connection, field, data): + data = data.decode(connection.charset) + return Decimal(data) + decoders[FIELD_TYPE.DECIMAL] = convert_decimal + decoders[FIELD_TYPE.NEWDECIMAL] = convert_decimal + + def escape_decimal(obj): + return unicode(obj) + encoders[Decimal] = escape_decimal + +except ImportError: + pass diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/cursors.py b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/cursors.py new file mode 100644 index 0000000..3b6a359 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/cursors.py @@ -0,0 +1,413 @@ +# -*- coding: utf-8 -*- +import struct +import re + +try: + import cStringIO as StringIO +except ImportError: + import StringIO + +from err import Warning, Error, InterfaceError, DataError, \ + DatabaseError, OperationalError, IntegrityError, InternalError, \ + NotSupportedError, ProgrammingError + +insert_values = re.compile(r'\svalues\s*(\(.+\))', re.IGNORECASE) + +class Cursor(object): + ''' + This is the object you use to interact with the database. + ''' + def __init__(self, connection): + ''' + Do not create an instance of a Cursor yourself. Call + connections.Connection.cursor(). + ''' + from weakref import proxy + self.connection = proxy(connection) + self.description = None + self.rownumber = 0 + self.rowcount = -1 + self.arraysize = 1 + self._executed = None + self.messages = [] + self.errorhandler = connection.errorhandler + self._has_next = None + self._rows = () + + def __del__(self): + ''' + When this gets GC'd close it. + ''' + self.close() + + def close(self): + ''' + Closing a cursor just exhausts all remaining data. + ''' + if not self.connection: + return + try: + while self.nextset(): + pass + except: + pass + + self.connection = None + + def _get_db(self): + if not self.connection: + self.errorhandler(self, ProgrammingError, "cursor closed") + return self.connection + + def _check_executed(self): + if not self._executed: + self.errorhandler(self, ProgrammingError, "execute() first") + + def setinputsizes(self, *args): + """Does nothing, required by DB API.""" + + def setoutputsizes(self, *args): + """Does nothing, required by DB API.""" + + def nextset(self): + ''' Get the next query set ''' + if self._executed: + self.fetchall() + del self.messages[:] + + if not self._has_next: + return None + connection = self._get_db() + connection.next_result() + self._do_get_result() + return True + + def execute(self, query, args=None): + ''' Execute a query ''' + from sys import exc_info + + conn = self._get_db() + charset = conn.charset + del self.messages[:] + + # TODO: make sure that conn.escape is correct + + if isinstance(query, unicode): + query = query.encode(charset) + + if args is not None: + if isinstance(args, tuple) or isinstance(args, list): + escaped_args = tuple(conn.escape(arg) for arg in args) + elif isinstance(args, dict): + escaped_args = dict((key, conn.escape(val)) for (key, val) in args.items()) + else: + #If it's not a dictionary let's try escaping it anyways. + #Worst case it will throw a Value error + escaped_args = conn.escape(args) + + query = query % escaped_args + + result = 0 + try: + result = self._query(query) + except: + exc, value, tb = exc_info() + del tb + self.messages.append((exc,value)) + self.errorhandler(self, exc, value) + + self._executed = query + return result + + def executemany(self, query, args): + ''' Run several data against one query ''' + del self.messages[:] + #conn = self._get_db() + if not args: + return + #charset = conn.charset + #if isinstance(query, unicode): + # query = query.encode(charset) + + self.rowcount = sum([ self.execute(query, arg) for arg in args ]) + return self.rowcount + + + def callproc(self, procname, args=()): + """Execute stored procedure procname with args + + procname -- string, name of procedure to execute on server + + args -- Sequence of parameters to use with procedure + + Returns the original args. + + Compatibility warning: PEP-249 specifies that any modified + parameters must be returned. This is currently impossible + as they are only available by storing them in a server + variable and then retrieved by a query. Since stored + procedures return zero or more result sets, there is no + reliable way to get at OUT or INOUT parameters via callproc. + The server variables are named @_procname_n, where procname + is the parameter above and n is the position of the parameter + (from zero). Once all result sets generated by the procedure + have been fetched, you can issue a SELECT @_procname_0, ... + query using .execute() to get any OUT or INOUT values. + + Compatibility warning: The act of calling a stored procedure + itself creates an empty result set. This appears after any + result sets generated by the procedure. This is non-standard + behavior with respect to the DB-API. Be sure to use nextset() + to advance through all result sets; otherwise you may get + disconnected. + """ + conn = self._get_db() + for index, arg in enumerate(args): + q = "SET @_%s_%d=%s" % (procname, index, conn.escape(arg)) + if isinstance(q, unicode): + q = q.encode(conn.charset) + self._query(q) + self.nextset() + + q = "CALL %s(%s)" % (procname, + ','.join(['@_%s_%d' % (procname, i) + for i in range(len(args))])) + if isinstance(q, unicode): + q = q.encode(conn.charset) + self._query(q) + self._executed = q + + return args + + def fetchone(self): + ''' Fetch the next row ''' + self._check_executed() + if self._rows is None or self.rownumber >= len(self._rows): + return None + result = self._rows[self.rownumber] + self.rownumber += 1 + return result + + def fetchmany(self, size=None): + ''' Fetch several rows ''' + self._check_executed() + end = self.rownumber + (size or self.arraysize) + result = self._rows[self.rownumber:end] + if self._rows is None: + return None + self.rownumber = min(end, len(self._rows)) + return result + + def fetchall(self): + ''' Fetch all the rows ''' + self._check_executed() + if self._rows is None: + return None + if self.rownumber: + result = self._rows[self.rownumber:] + else: + result = self._rows + self.rownumber = len(self._rows) + return result + + def scroll(self, value, mode='relative'): + self._check_executed() + if mode == 'relative': + r = self.rownumber + value + elif mode == 'absolute': + r = value + else: + self.errorhandler(self, ProgrammingError, + "unknown scroll mode %s" % mode) + + if r < 0 or r >= len(self._rows): + self.errorhandler(self, IndexError, "out of range") + self.rownumber = r + + def _query(self, q): + conn = self._get_db() + self._last_executed = q + conn.query(q) + self._do_get_result() + return self.rowcount + + def _do_get_result(self): + conn = self._get_db() + self.rowcount = conn._result.affected_rows + + self.rownumber = 0 + self.description = conn._result.description + self.lastrowid = conn._result.insert_id + self._rows = conn._result.rows + self._has_next = conn._result.has_next + + def __iter__(self): + return iter(self.fetchone, None) + + Warning = Warning + Error = Error + InterfaceError = InterfaceError + DatabaseError = DatabaseError + DataError = DataError + OperationalError = OperationalError + IntegrityError = IntegrityError + InternalError = InternalError + ProgrammingError = ProgrammingError + NotSupportedError = NotSupportedError + +class DictCursor(Cursor): + """A cursor which returns results as a dictionary""" + + def execute(self, query, args=None): + result = super(DictCursor, self).execute(query, args) + if self.description: + self._fields = [ field[0] for field in self.description ] + return result + + def fetchone(self): + ''' Fetch the next row ''' + self._check_executed() + if self._rows is None or self.rownumber >= len(self._rows): + return None + result = dict(zip(self._fields, self._rows[self.rownumber])) + self.rownumber += 1 + return result + + def fetchmany(self, size=None): + ''' Fetch several rows ''' + self._check_executed() + if self._rows is None: + return None + end = self.rownumber + (size or self.arraysize) + result = [ dict(zip(self._fields, r)) for r in self._rows[self.rownumber:end] ] + self.rownumber = min(end, len(self._rows)) + return tuple(result) + + def fetchall(self): + ''' Fetch all the rows ''' + self._check_executed() + if self._rows is None: + return None + if self.rownumber: + result = [ dict(zip(self._fields, r)) for r in self._rows[self.rownumber:] ] + else: + result = [ dict(zip(self._fields, r)) for r in self._rows ] + self.rownumber = len(self._rows) + return tuple(result) + +class SSCursor(Cursor): + """ + Unbuffered Cursor, mainly useful for queries that return a lot of data, + or for connections to remote servers over a slow network. + + Instead of copying every row of data into a buffer, this will fetch + rows as needed. The upside of this, is the client uses much less memory, + and rows are returned much faster when traveling over a slow network, + or if the result set is very big. + + There are limitations, though. The MySQL protocol doesn't support + returning the total number of rows, so the only way to tell how many rows + there are is to iterate over every row returned. Also, it currently isn't + possible to scroll backwards, as only the current row is held in memory. + """ + + def close(self): + conn = self._get_db() + try: + conn._result._finish_unbuffered_query() + except AttributeError: + pass + + try: + if self._has_next: + while self.nextset(): pass + except: pass + + def _query(self, q): + conn = self._get_db() + self._last_executed = q + conn.query(q, unbuffered=True) + self._do_get_result() + return self.rowcount + + def read_next(self): + """ Read next row """ + + conn = self._get_db() + conn._result._read_rowdata_packet_unbuffered() + return conn._result.rows + + def fetchone(self): + """ Fetch next row """ + + self._check_executed() + row = self.read_next() + if row is None: + return None + self.rownumber += 1 + return row + + def fetchall(self): + """ + Fetch all, as per MySQLdb. Pretty useless for large queries, as + it is buffered. See fetchall_unbuffered(), if you want an unbuffered + generator version of this method. + """ + + rows = [] + while True: + row = self.fetchone() + if row is None: + break + rows.append(row) + return tuple(rows) + + def fetchall_unbuffered(self): + """ + Fetch all, implemented as a generator, which isn't to standard, + however, it doesn't make sense to return everything in a list, as that + would use ridiculous memory for large result sets. + """ + + row = self.fetchone() + while row is not None: + yield row + row = self.fetchone() + + def fetchmany(self, size=None): + """ Fetch many """ + + self._check_executed() + if size is None: + size = self.arraysize + + rows = [] + for i in range(0, size): + row = self.read_next() + if row is None: + break + rows.append(row) + self.rownumber += 1 + return tuple(rows) + + def scroll(self, value, mode='relative'): + self._check_executed() + if not mode == 'relative' and not mode == 'absolute': + self.errorhandler(self, ProgrammingError, + "unknown scroll mode %s" % mode) + + if mode == 'relative': + if value < 0: + self.errorhandler(self, NotSupportedError, + "Backwards scrolling not supported by this cursor") + + for i in range(0, value): self.read_next() + self.rownumber += value + else: + if value < self.rownumber: + self.errorhandler(self, NotSupportedError, + "Backwards scrolling not supported by this cursor") + + end = value - self.rownumber + for i in range(0, end): self.read_next() + self.rownumber = value diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/err.py b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/err.py new file mode 100644 index 0000000..b4322c6 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pymysql/err.py @@ -0,0 +1,147 @@ +import struct + + +try: + StandardError, Warning +except ImportError: + try: + from exceptions import StandardError, Warning + except ImportError: + import sys + e = sys.modules['exceptions'] + StandardError = e.StandardError + Warning = e.Warning + +from constants import ER +import sys + +class MySQLError(StandardError): + + """Exception related to operation with MySQL.""" + + +class Warning(Warning, MySQLError): + + """Exception raised for important warnings like data truncations + while inserting, etc.""" + +class Error(MySQLError): + + """Exception that is the base class of all other error exceptions + (not Warning).""" + + +class InterfaceError(Error): + + """Exception raised for errors that are related to the database + interface rather than the database itself.""" + + +class DatabaseError(Error): + + """Exception raised for errors that are related to the + database.""" + + +class DataError(DatabaseError): + + """Exception raised for errors that are due to problems with the + processed data like division by zero, numeric value out of range, + etc.""" + + +class OperationalError(DatabaseError): + + """Exception raised for errors that are related to the database's + operation and not necessarily under the control of the programmer, + e.g. an unexpected disconnect occurs, the data source name is not + found, a transaction could not be processed, a memory allocation + error occurred during processing, etc.""" + + +class IntegrityError(DatabaseError): + + """Exception raised when the relational integrity of the database + is affected, e.g. a foreign key check fails, duplicate key, + etc.""" + + +class InternalError(DatabaseError): + + """Exception raised when the database encounters an internal + error, e.g. the cursor is not valid anymore, the transaction is + out of sync, etc.""" + + +class ProgrammingError(DatabaseError): + + """Exception raised for programming errors, e.g. table not found + or already exists, syntax error in the SQL statement, wrong number + of parameters specified, etc.""" + + +class NotSupportedError(DatabaseError): + + """Exception raised in case a method or database API was used + which is not supported by the database, e.g. requesting a + .rollback() on a connection that does not support transaction or + has transactions turned off.""" + + +error_map = {} + +def _map_error(exc, *errors): + for error in errors: + error_map[error] = exc + +_map_error(ProgrammingError, ER.DB_CREATE_EXISTS, ER.SYNTAX_ERROR, + ER.PARSE_ERROR, ER.NO_SUCH_TABLE, ER.WRONG_DB_NAME, + ER.WRONG_TABLE_NAME, ER.FIELD_SPECIFIED_TWICE, + ER.INVALID_GROUP_FUNC_USE, ER.UNSUPPORTED_EXTENSION, + ER.TABLE_MUST_HAVE_COLUMNS, ER.CANT_DO_THIS_DURING_AN_TRANSACTION) +_map_error(DataError, ER.WARN_DATA_TRUNCATED, ER.WARN_NULL_TO_NOTNULL, + ER.WARN_DATA_OUT_OF_RANGE, ER.NO_DEFAULT, ER.PRIMARY_CANT_HAVE_NULL, + ER.DATA_TOO_LONG, ER.DATETIME_FUNCTION_OVERFLOW) +_map_error(IntegrityError, ER.DUP_ENTRY, ER.NO_REFERENCED_ROW, + ER.NO_REFERENCED_ROW_2, ER.ROW_IS_REFERENCED, ER.ROW_IS_REFERENCED_2, + ER.CANNOT_ADD_FOREIGN) +_map_error(NotSupportedError, ER.WARNING_NOT_COMPLETE_ROLLBACK, + ER.NOT_SUPPORTED_YET, ER.FEATURE_DISABLED, ER.UNKNOWN_STORAGE_ENGINE) +_map_error(OperationalError, ER.DBACCESS_DENIED_ERROR, ER.ACCESS_DENIED_ERROR, + ER.TABLEACCESS_DENIED_ERROR, ER.COLUMNACCESS_DENIED_ERROR) + +del _map_error, ER + + +def _get_error_info(data): + errno = struct.unpack(', !"):: + + from pyparsing import Word, alphas + + # define grammar of a greeting + greet = Word( alphas ) + "," + Word( alphas ) + "!" + + hello = "Hello, World!" + print hello, "->", greet.parseString( hello ) + +The program outputs the following:: + + Hello, World! -> ['Hello', ',', 'World', '!'] + +The Python representation of the grammar is quite readable, owing to the self-explanatory +class names, and the use of '+', '|' and '^' operators. + +The parsed results returned from parseString() can be accessed as a nested list, a dictionary, or an +object with named attributes. + +The pyparsing module handles some of the problems that are typically vexing when writing text parsers: + - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) + - quoted strings + - embedded comments +""" + +__version__ = "1.5.2" +__versionTime__ = "17 February 2009 19:45" +__author__ = "Paul McGuire " + +import string +from weakref import ref as wkref +import copy +import sys +import warnings +import re +import sre_constants +#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) + +__all__ = [ +'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty', +'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal', +'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or', +'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException', +'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException', +'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', 'Upcase', +'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore', +'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col', +'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString', +'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'getTokensEndLoc', 'hexnums', +'htmlComment', 'javaStyleComment', 'keepOriginalText', 'line', 'lineEnd', 'lineStart', 'lineno', +'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral', +'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables', +'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', +'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd', +'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute', +'indentedBlock', 'originalTextFor', +] + + +""" +Detect if we are running version 3.X and make appropriate changes +Robert A. Clark +""" +if sys.version_info[0] > 2: + _PY3K = True + _MAX_INT = sys.maxsize + basestring = str +else: + _PY3K = False + _MAX_INT = sys.maxint + +if not _PY3K: + def _ustr(obj): + """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries + str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It + then < returns the unicode object | encodes it with the default encoding | ... >. + """ + if isinstance(obj,unicode): + return obj + + try: + # If this works, then _ustr(obj) has the same behaviour as str(obj), so + # it won't break any existing code. + return str(obj) + + except UnicodeEncodeError: + # The Python docs (http://docs.python.org/ref/customization.html#l2h-182) + # state that "The return value must be a string object". However, does a + # unicode object (being a subclass of basestring) count as a "string + # object"? + # If so, then return a unicode object: + return unicode(obj) + # Else encode it... but how? There are many choices... :) + # Replace unprintables with escape codes? + #return unicode(obj).encode(sys.getdefaultencoding(), 'backslashreplace_errors') + # Replace unprintables with question marks? + #return unicode(obj).encode(sys.getdefaultencoding(), 'replace') + # ... +else: + _ustr = str + unichr = chr + +if not _PY3K: + def _str2dict(strg): + return dict( [(c,0) for c in strg] ) +else: + _str2dict = set + +def _xml_escape(data): + """Escape &, <, >, ", ', etc. in a string of data.""" + + # ampersand must be replaced first + from_symbols = '&><"\'' + to_symbols = ['&'+s+';' for s in "amp gt lt quot apos".split()] + for from_,to_ in zip(from_symbols, to_symbols): + data = data.replace(from_, to_) + return data + +class _Constants(object): + pass + +if not _PY3K: + alphas = string.lowercase + string.uppercase +else: + alphas = string.ascii_lowercase + string.ascii_uppercase +nums = string.digits +hexnums = nums + "ABCDEFabcdef" +alphanums = alphas + nums +_bslash = chr(92) +printables = "".join( [ c for c in string.printable if c not in string.whitespace ] ) + +class ParseBaseException(Exception): + """base exception class for all parsing runtime exceptions""" + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, pstr, loc=0, msg=None, elem=None ): + self.loc = loc + if msg is None: + self.msg = pstr + self.pstr = "" + else: + self.msg = msg + self.pstr = pstr + self.parserElement = elem + + def __getattr__( self, aname ): + """supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + """ + if( aname == "lineno" ): + return lineno( self.loc, self.pstr ) + elif( aname in ("col", "column") ): + return col( self.loc, self.pstr ) + elif( aname == "line" ): + return line( self.loc, self.pstr ) + else: + raise AttributeError(aname) + + def __str__( self ): + return "%s (at char %d), (line:%d, col:%d)" % \ + ( self.msg, self.loc, self.lineno, self.column ) + def __repr__( self ): + return _ustr(self) + def markInputline( self, markerString = ">!<" ): + """Extracts the exception line from the input string, and marks + the location of the exception with a special symbol. + """ + line_str = self.line + line_column = self.column - 1 + if markerString: + line_str = "".join( [line_str[:line_column], + markerString, line_str[line_column:]]) + return line_str.strip() + def __dir__(self): + return "loc msg pstr parserElement lineno col line " \ + "markInputLine __str__ __repr__".split() + +class ParseException(ParseBaseException): + """exception thrown when parse expressions don't match class; + supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + """ + pass + +class ParseFatalException(ParseBaseException): + """user-throwable exception thrown when inconsistent parse content + is found; stops all parsing immediately""" + pass + +class ParseSyntaxException(ParseFatalException): + """just like ParseFatalException, but thrown internally when an + ErrorStop indicates that parsing is to stop immediately because + an unbacktrackable syntax error has been found""" + def __init__(self, pe): + super(ParseSyntaxException, self).__init__( + pe.pstr, pe.loc, pe.msg, pe.parserElement) + +#~ class ReparseException(ParseBaseException): + #~ """Experimental class - parse actions can raise this exception to cause + #~ pyparsing to reparse the input string: + #~ - with a modified input string, and/or + #~ - with a modified start location + #~ Set the values of the ReparseException in the constructor, and raise the + #~ exception in a parse action to cause pyparsing to use the new string/location. + #~ Setting the values as None causes no change to be made. + #~ """ + #~ def __init_( self, newstring, restartLoc ): + #~ self.newParseText = newstring + #~ self.reparseLoc = restartLoc + +class RecursiveGrammarException(Exception): + """exception thrown by validate() if the grammar could be improperly recursive""" + def __init__( self, parseElementList ): + self.parseElementTrace = parseElementList + + def __str__( self ): + return "RecursiveGrammarException: %s" % self.parseElementTrace + +class _ParseResultsWithOffset(object): + def __init__(self,p1,p2): + self.tup = (p1,p2) + def __getitem__(self,i): + return self.tup[i] + def __repr__(self): + return repr(self.tup) + def setOffset(self,i): + self.tup = (self.tup[0],i) + +class ParseResults(object): + """Structured parse results, to provide multiple means of access to the parsed data: + - as a list (len(results)) + - by list index (results[0], results[1], etc.) + - by attribute (results.) + """ + __slots__ = ( "__toklist", "__tokdict", "__doinit", "__name", "__parent", "__accumNames", "__weakref__" ) + def __new__(cls, toklist, name=None, asList=True, modal=True ): + if isinstance(toklist, cls): + return toklist + retobj = object.__new__(cls) + retobj.__doinit = True + return retobj + + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, toklist, name=None, asList=True, modal=True ): + if self.__doinit: + self.__doinit = False + self.__name = None + self.__parent = None + self.__accumNames = {} + if isinstance(toklist, list): + self.__toklist = toklist[:] + else: + self.__toklist = [toklist] + self.__tokdict = dict() + + if name: + if not modal: + self.__accumNames[name] = 0 + if isinstance(name,int): + name = _ustr(name) # will always return a str, but use _ustr for consistency + self.__name = name + if not toklist in (None,'',[]): + if isinstance(toklist,basestring): + toklist = [ toklist ] + if asList: + if isinstance(toklist,ParseResults): + self[name] = _ParseResultsWithOffset(toklist.copy(),0) + else: + self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0) + self[name].__name = name + else: + try: + self[name] = toklist[0] + except (KeyError,TypeError,IndexError): + self[name] = toklist + + def __getitem__( self, i ): + if isinstance( i, (int,slice) ): + return self.__toklist[i] + else: + if i not in self.__accumNames: + return self.__tokdict[i][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[i] ]) + + def __setitem__( self, k, v ): + if isinstance(v,_ParseResultsWithOffset): + self.__tokdict[k] = self.__tokdict.get(k,list()) + [v] + sub = v[0] + elif isinstance(k,int): + self.__toklist[k] = v + sub = v + else: + self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)] + sub = v + if isinstance(sub,ParseResults): + sub.__parent = wkref(self) + + def __delitem__( self, i ): + if isinstance(i,(int,slice)): + mylen = len( self.__toklist ) + del self.__toklist[i] + + # convert int to slice + if isinstance(i, int): + if i < 0: + i += mylen + i = slice(i, i+1) + # get removed indices + removed = list(range(*i.indices(mylen))) + removed.reverse() + # fixup indices in token dictionary + for name in self.__tokdict: + occurrences = self.__tokdict[name] + for j in removed: + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position - (position > j)) + else: + del self.__tokdict[i] + + def __contains__( self, k ): + return k in self.__tokdict + + def __len__( self ): return len( self.__toklist ) + def __bool__(self): return len( self.__toklist ) > 0 + __nonzero__ = __bool__ + def __iter__( self ): return iter( self.__toklist ) + def __reversed__( self ): return iter( reversed(self.__toklist) ) + def keys( self ): + """Returns all named result keys.""" + return self.__tokdict.keys() + + def pop( self, index=-1 ): + """Removes and returns item at specified index (default=last). + Will work with either numeric indices or dict-key indicies.""" + ret = self[index] + del self[index] + return ret + + def get(self, key, defaultValue=None): + """Returns named result matching the given key, or if there is no + such name, then returns the given defaultValue or None if no + defaultValue is specified.""" + if key in self: + return self[key] + else: + return defaultValue + + def insert( self, index, insStr ): + self.__toklist.insert(index, insStr) + # fixup indices in token dictionary + for name in self.__tokdict: + occurrences = self.__tokdict[name] + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position + (position > index)) + + def items( self ): + """Returns all named result keys and values as a list of tuples.""" + return [(k,self[k]) for k in self.__tokdict] + + def values( self ): + """Returns all named result values.""" + return [ v[-1][0] for v in self.__tokdict.values() ] + + def __getattr__( self, name ): + if name not in self.__slots__: + if name in self.__tokdict: + if name not in self.__accumNames: + return self.__tokdict[name][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[name] ]) + else: + return "" + return None + + def __add__( self, other ): + ret = self.copy() + ret += other + return ret + + def __iadd__( self, other ): + if other.__tokdict: + offset = len(self.__toklist) + addoffset = ( lambda a: (a<0 and offset) or (a+offset) ) + otheritems = other.__tokdict.items() + otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) ) + for (k,vlist) in otheritems for v in vlist] + for k,v in otherdictitems: + self[k] = v + if isinstance(v[0],ParseResults): + v[0].__parent = wkref(self) + + self.__toklist += other.__toklist + self.__accumNames.update( other.__accumNames ) + del other + return self + + def __repr__( self ): + return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) ) + + def __str__( self ): + out = "[" + sep = "" + for i in self.__toklist: + if isinstance(i, ParseResults): + out += sep + _ustr(i) + else: + out += sep + repr(i) + sep = ", " + out += "]" + return out + + def _asStringList( self, sep='' ): + out = [] + for item in self.__toklist: + if out and sep: + out.append(sep) + if isinstance( item, ParseResults ): + out += item._asStringList() + else: + out.append( _ustr(item) ) + return out + + def asList( self ): + """Returns the parse results as a nested list of matching tokens, all converted to strings.""" + out = [] + for res in self.__toklist: + if isinstance(res,ParseResults): + out.append( res.asList() ) + else: + out.append( res ) + return out + + def asDict( self ): + """Returns the named parse results as dictionary.""" + return dict( self.items() ) + + def copy( self ): + """Returns a new copy of a ParseResults object.""" + ret = ParseResults( self.__toklist ) + ret.__tokdict = self.__tokdict.copy() + ret.__parent = self.__parent + ret.__accumNames.update( self.__accumNames ) + ret.__name = self.__name + return ret + + def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ): + """Returns the parse results as XML. Tags are created for tokens and lists that have defined results names.""" + nl = "\n" + out = [] + namedItems = dict( [ (v[1],k) for (k,vlist) in self.__tokdict.items() + for v in vlist ] ) + nextLevelIndent = indent + " " + + # collapse out indents if formatting is not desired + if not formatted: + indent = "" + nextLevelIndent = "" + nl = "" + + selfTag = None + if doctag is not None: + selfTag = doctag + else: + if self.__name: + selfTag = self.__name + + if not selfTag: + if namedItemsOnly: + return "" + else: + selfTag = "ITEM" + + out += [ nl, indent, "<", selfTag, ">" ] + + worklist = self.__toklist + for i,res in enumerate(worklist): + if isinstance(res,ParseResults): + if i in namedItems: + out += [ res.asXML(namedItems[i], + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + out += [ res.asXML(None, + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + # individual token, see if there is a name for it + resTag = None + if i in namedItems: + resTag = namedItems[i] + if not resTag: + if namedItemsOnly: + continue + else: + resTag = "ITEM" + xmlBodyText = _xml_escape(_ustr(res)) + out += [ nl, nextLevelIndent, "<", resTag, ">", + xmlBodyText, + "" ] + + out += [ nl, indent, "" ] + return "".join(out) + + def __lookup(self,sub): + for k,vlist in self.__tokdict.items(): + for v,loc in vlist: + if sub is v: + return k + return None + + def getName(self): + """Returns the results name for this token expression.""" + if self.__name: + return self.__name + elif self.__parent: + par = self.__parent() + if par: + return par.__lookup(self) + else: + return None + elif (len(self) == 1 and + len(self.__tokdict) == 1 and + self.__tokdict.values()[0][0][1] in (0,-1)): + return self.__tokdict.keys()[0] + else: + return None + + def dump(self,indent='',depth=0): + """Diagnostic method for listing out the contents of a ParseResults. + Accepts an optional indent argument so that this string can be embedded + in a nested display of other data.""" + out = [] + out.append( indent+_ustr(self.asList()) ) + keys = self.items() + keys.sort() + for k,v in keys: + if out: + out.append('\n') + out.append( "%s%s- %s: " % (indent,(' '*depth), k) ) + if isinstance(v,ParseResults): + if v.keys(): + #~ out.append('\n') + out.append( v.dump(indent,depth+1) ) + #~ out.append('\n') + else: + out.append(_ustr(v)) + else: + out.append(_ustr(v)) + #~ out.append('\n') + return "".join(out) + + # add support for pickle protocol + def __getstate__(self): + return ( self.__toklist, + ( self.__tokdict.copy(), + self.__parent is not None and self.__parent() or None, + self.__accumNames, + self.__name ) ) + + def __setstate__(self,state): + self.__toklist = state[0] + self.__tokdict, \ + par, \ + inAccumNames, \ + self.__name = state[1] + self.__accumNames = {} + self.__accumNames.update(inAccumNames) + if par is not None: + self.__parent = wkref(par) + else: + self.__parent = None + + def __dir__(self): + return dir(super(ParseResults,self)) + self.keys() + +def col (loc,strg): + """Returns current column within a string, counting newlines as line separators. + The first column is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{ParserElement.parseString}} for more information + on parsing strings containing s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + return (loc} for more information + on parsing strings containing s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + return strg.count("\n",0,loc) + 1 + +def line( loc, strg ): + """Returns the line of text containing loc within a string, counting newlines as line separators. + """ + lastCR = strg.rfind("\n", 0, loc) + nextCR = strg.find("\n", loc) + if nextCR > 0: + return strg[lastCR+1:nextCR] + else: + return strg[lastCR+1:] + +def _defaultStartDebugAction( instring, loc, expr ): + print ("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) + +def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ): + print ("Matched " + _ustr(expr) + " -> " + str(toks.asList())) + +def _defaultExceptionDebugAction( instring, loc, expr, exc ): + print ("Exception raised:" + _ustr(exc)) + +def nullDebugAction(*args): + """'Do-nothing' debug action, to suppress debugging output during parsing.""" + pass + +class ParserElement(object): + """Abstract base level parser element class.""" + DEFAULT_WHITE_CHARS = " \n\t\r" + + def setDefaultWhitespaceChars( chars ): + """Overrides the default whitespace chars + """ + ParserElement.DEFAULT_WHITE_CHARS = chars + setDefaultWhitespaceChars = staticmethod(setDefaultWhitespaceChars) + + def __init__( self, savelist=False ): + self.parseAction = list() + self.failAction = None + #~ self.name = "" # don't define self.name, let subclasses try/except upcall + self.strRepr = None + self.resultsName = None + self.saveAsList = savelist + self.skipWhitespace = True + self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + self.copyDefaultWhiteChars = True + self.mayReturnEmpty = False # used when checking for left-recursion + self.keepTabs = False + self.ignoreExprs = list() + self.debug = False + self.streamlined = False + self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index + self.errmsg = "" + self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all) + self.debugActions = ( None, None, None ) #custom debug actions + self.re = None + self.callPreparse = True # used to avoid redundant calls to preParse + self.callDuringTry = False + + def copy( self ): + """Make a copy of this ParserElement. Useful for defining different parse actions + for the same parsing pattern, using copies of the original parse element.""" + cpy = copy.copy( self ) + cpy.parseAction = self.parseAction[:] + cpy.ignoreExprs = self.ignoreExprs[:] + if self.copyDefaultWhiteChars: + cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + return cpy + + def setName( self, name ): + """Define name for this expression, for use in debugging.""" + self.name = name + self.errmsg = "Expected " + self.name + if hasattr(self,"exception"): + self.exception.msg = self.errmsg + return self + + def setResultsName( self, name, listAllMatches=False ): + """Define name for referencing matching tokens as a nested attribute + of the returned parse results. + NOTE: this returns a *copy* of the original ParserElement object; + this is so that the client can define a basic element, such as an + integer, and reference it in multiple places with different names. + """ + newself = self.copy() + newself.resultsName = name + newself.modalResults = not listAllMatches + return newself + + def setBreak(self,breakFlag = True): + """Method to invoke the Python pdb debugger when this element is + about to be parsed. Set breakFlag to True to enable, False to + disable. + """ + if breakFlag: + _parseMethod = self._parse + def breaker(instring, loc, doActions=True, callPreParse=True): + import pdb + pdb.set_trace() + return _parseMethod( instring, loc, doActions, callPreParse ) + breaker._originalParseMethod = _parseMethod + self._parse = breaker + else: + if hasattr(self._parse,"_originalParseMethod"): + self._parse = self._parse._originalParseMethod + return self + + def _normalizeParseActionArgs( f ): + """Internal method used to decorate parse actions that take fewer than 3 arguments, + so that all parse actions can be called as f(s,l,t).""" + STAR_ARGS = 4 + + try: + restore = None + if isinstance(f,type): + restore = f + f = f.__init__ + if not _PY3K: + codeObj = f.func_code + else: + codeObj = f.code + if codeObj.co_flags & STAR_ARGS: + return f + numargs = codeObj.co_argcount + if not _PY3K: + if hasattr(f,"im_self"): + numargs -= 1 + else: + if hasattr(f,"__self__"): + numargs -= 1 + if restore: + f = restore + except AttributeError: + try: + if not _PY3K: + call_im_func_code = f.__call__.im_func.func_code + else: + call_im_func_code = f.__code__ + + # not a function, must be a callable object, get info from the + # im_func binding of its bound __call__ method + if call_im_func_code.co_flags & STAR_ARGS: + return f + numargs = call_im_func_code.co_argcount + if not _PY3K: + if hasattr(f.__call__,"im_self"): + numargs -= 1 + else: + if hasattr(f.__call__,"__self__"): + numargs -= 0 + except AttributeError: + if not _PY3K: + call_func_code = f.__call__.func_code + else: + call_func_code = f.__call__.__code__ + # not a bound method, get info directly from __call__ method + if call_func_code.co_flags & STAR_ARGS: + return f + numargs = call_func_code.co_argcount + if not _PY3K: + if hasattr(f.__call__,"im_self"): + numargs -= 1 + else: + if hasattr(f.__call__,"__self__"): + numargs -= 1 + + + #~ print ("adding function %s with %d args" % (f.func_name,numargs)) + if numargs == 3: + return f + else: + if numargs > 3: + def tmp(s,l,t): + return f(f.__call__.__self__, s,l,t) + if numargs == 2: + def tmp(s,l,t): + return f(l,t) + elif numargs == 1: + def tmp(s,l,t): + return f(t) + else: #~ numargs == 0: + def tmp(s,l,t): + return f() + try: + tmp.__name__ = f.__name__ + except (AttributeError,TypeError): + # no need for special handling if attribute doesnt exist + pass + try: + tmp.__doc__ = f.__doc__ + except (AttributeError,TypeError): + # no need for special handling if attribute doesnt exist + pass + try: + tmp.__dict__.update(f.__dict__) + except (AttributeError,TypeError): + # no need for special handling if attribute doesnt exist + pass + return tmp + _normalizeParseActionArgs = staticmethod(_normalizeParseActionArgs) + + def setParseAction( self, *fns, **kwargs ): + """Define action to perform when successfully matching parse element definition. + Parse action fn is a callable method with 0-3 arguments, called as fn(s,loc,toks), + fn(loc,toks), fn(toks), or just fn(), where: + - s = the original string being parsed (see note below) + - loc = the location of the matching substring + - toks = a list of the matched tokens, packaged as a ParseResults object + If the functions in fns modify the tokens, they can return them as the return + value from fn, and the modified list of tokens will replace the original. + Otherwise, fn does not need to return any value. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{parseString}} for more information + on parsing strings containing s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + self.parseAction = list(map(self._normalizeParseActionArgs, list(fns))) + self.callDuringTry = ("callDuringTry" in kwargs and kwargs["callDuringTry"]) + return self + + def addParseAction( self, *fns, **kwargs ): + """Add parse action to expression's list of parse actions. See L{I{setParseAction}}.""" + self.parseAction += list(map(self._normalizeParseActionArgs, list(fns))) + self.callDuringTry = self.callDuringTry or ("callDuringTry" in kwargs and kwargs["callDuringTry"]) + return self + + def setFailAction( self, fn ): + """Define action to perform if parsing fails at this expression. + Fail acton fn is a callable function that takes the arguments + fn(s,loc,expr,err) where: + - s = string being parsed + - loc = location where expression match was attempted and failed + - expr = the parse expression that failed + - err = the exception thrown + The function returns no value. It may throw ParseFatalException + if it is desired to stop parsing immediately.""" + self.failAction = fn + return self + + def _skipIgnorables( self, instring, loc ): + exprsFound = True + while exprsFound: + exprsFound = False + for e in self.ignoreExprs: + try: + while 1: + loc,dummy = e._parse( instring, loc ) + exprsFound = True + except ParseException: + pass + return loc + + def preParse( self, instring, loc ): + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + + if self.skipWhitespace: + wt = self.whiteChars + instrlen = len(instring) + while loc < instrlen and instring[loc] in wt: + loc += 1 + + return loc + + def parseImpl( self, instring, loc, doActions=True ): + return loc, [] + + def postParse( self, instring, loc, tokenlist ): + return tokenlist + + #~ @profile + def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ): + debugging = ( self.debug ) #and doActions ) + + if debugging or self.failAction: + #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) + if (self.debugActions[0] ): + self.debugActions[0]( instring, loc, self ) + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = loc + try: + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + except ParseBaseException, err: + #~ print ("Exception raised:", err) + if self.debugActions[2]: + self.debugActions[2]( instring, tokensStart, self, err ) + if self.failAction: + self.failAction( instring, tokensStart, self, err ) + raise + else: + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = loc + if self.mayIndexError or loc >= len(instring): + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + else: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + + tokens = self.postParse( instring, loc, tokens ) + + retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults ) + if self.parseAction and (doActions or self.callDuringTry): + if debugging: + try: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + except ParseBaseException, err: + #~ print "Exception raised in user parse action:", err + if (self.debugActions[2] ): + self.debugActions[2]( instring, tokensStart, self, err ) + raise + else: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + + if debugging: + #~ print ("Matched",self,"->",retTokens.asList()) + if (self.debugActions[1] ): + self.debugActions[1]( instring, tokensStart, loc, self, retTokens ) + + return loc, retTokens + + def tryParse( self, instring, loc ): + try: + return self._parse( instring, loc, doActions=False )[0] + except ParseFatalException: + raise ParseException( instring, loc, self.errmsg, self) + + # this method gets repeatedly called during backtracking with the same arguments - + # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression + def _parseCache( self, instring, loc, doActions=True, callPreParse=True ): + lookup = (self,instring,loc,callPreParse,doActions) + if lookup in ParserElement._exprArgCache: + value = ParserElement._exprArgCache[ lookup ] + if isinstance(value,Exception): + raise value + return value + else: + try: + value = self._parseNoCache( instring, loc, doActions, callPreParse ) + ParserElement._exprArgCache[ lookup ] = (value[0],value[1].copy()) + return value + except ParseBaseException, pe: + ParserElement._exprArgCache[ lookup ] = pe + raise + + _parse = _parseNoCache + + # argument cache for optimizing repeated calls when backtracking through recursive expressions + _exprArgCache = {} + def resetCache(): + ParserElement._exprArgCache.clear() + resetCache = staticmethod(resetCache) + + _packratEnabled = False + def enablePackrat(): + """Enables "packrat" parsing, which adds memoizing to the parsing logic. + Repeated parse attempts at the same string location (which happens + often in many complex grammars) can immediately return a cached value, + instead of re-executing parsing/validating code. Memoizing is done of + both valid results and parsing exceptions. + + This speedup may break existing programs that use parse actions that + have side-effects. For this reason, packrat parsing is disabled when + you first import pyparsing. To activate the packrat feature, your + program must call the class method ParserElement.enablePackrat(). If + your program uses psyco to "compile as you go", you must call + enablePackrat before calling psyco.full(). If you do not do this, + Python will crash. For best results, call enablePackrat() immediately + after importing pyparsing. + """ + if not ParserElement._packratEnabled: + ParserElement._packratEnabled = True + ParserElement._parse = ParserElement._parseCache + enablePackrat = staticmethod(enablePackrat) + + def parseString( self, instring, parseAll=False ): + """Execute the parse expression with the given string. + This is the main interface to the client code, once the complete + expression has been built. + + If you want the grammar to require that the entire input string be + successfully parsed, then set parseAll to True (equivalent to ending + the grammar with StringEnd()). + + Note: parseString implicitly calls expandtabs() on the input string, + in order to report proper column numbers in parse actions. + If the input string contains tabs and + the grammar uses parse actions that use the loc argument to index into the + string being parsed, you can ensure you have a consistent view of the input + string by: + - calling parseWithTabs on your grammar before calling parseString + (see L{I{parseWithTabs}}) + - define your parse action using the full (s,loc,toks) signature, and + reference the input string using the parse action's s argument + - explictly expand the tabs in your input string before calling + parseString + """ + ParserElement.resetCache() + if not self.streamlined: + self.streamline() + #~ self.saveAsList = True + for e in self.ignoreExprs: + e.streamline() + if not self.keepTabs: + instring = instring.expandtabs() + try: + loc, tokens = self._parse( instring, 0 ) + if parseAll: + loc = self.preParse( instring, loc ) + StringEnd()._parse( instring, loc ) + except ParseBaseException, exc: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + else: + return tokens + + def scanString( self, instring, maxMatches=_MAX_INT ): + """Scan the input string for expression matches. Each match will return the + matching tokens, start location, and end location. May be called with optional + maxMatches argument, to clip scanning after 'n' matches are found. + + Note that the start and end locations are reported relative to the string + being parsed. See L{I{parseString}} for more information on parsing + strings with embedded tabs.""" + if not self.streamlined: + self.streamline() + for e in self.ignoreExprs: + e.streamline() + + if not self.keepTabs: + instring = _ustr(instring).expandtabs() + instrlen = len(instring) + loc = 0 + preparseFn = self.preParse + parseFn = self._parse + ParserElement.resetCache() + matches = 0 + try: + while loc <= instrlen and matches < maxMatches: + try: + preloc = preparseFn( instring, loc ) + nextLoc,tokens = parseFn( instring, preloc, callPreParse=False ) + except ParseException: + loc = preloc+1 + else: + matches += 1 + yield tokens, preloc, nextLoc + loc = nextLoc + except ParseBaseException, pe: + raise pe + + def transformString( self, instring ): + """Extension to scanString, to modify matching text with modified tokens that may + be returned from a parse action. To use transformString, define a grammar and + attach a parse action to it that modifies the returned token list. + Invoking transformString() on a target string will then scan for matches, + and replace the matched text patterns according to the logic in the parse + action. transformString() returns the resulting transformed string.""" + out = [] + lastE = 0 + # force preservation of s, to minimize unwanted transformation of string, and to + # keep string locs straight between transformString and scanString + self.keepTabs = True + try: + for t,s,e in self.scanString( instring ): + out.append( instring[lastE:s] ) + if t: + if isinstance(t,ParseResults): + out += t.asList() + elif isinstance(t,list): + out += t + else: + out.append(t) + lastE = e + out.append(instring[lastE:]) + return "".join(map(_ustr,out)) + except ParseBaseException, pe: + raise pe + + def searchString( self, instring, maxMatches=_MAX_INT ): + """Another extension to scanString, simplifying the access to the tokens found + to match the given parse expression. May be called with optional + maxMatches argument, to clip searching after 'n' matches are found. + """ + try: + return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ]) + except ParseBaseException, pe: + raise pe + + def __add__(self, other ): + """Implementation of + operator - returns And""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return And( [ self, other ] ) + + def __radd__(self, other ): + """Implementation of + operator when left operand is not a ParserElement""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other + self + + def __sub__(self, other): + """Implementation of - operator, returns And with error stop""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return And( [ self, And._ErrorStop(), other ] ) + + def __rsub__(self, other ): + """Implementation of - operator when left operand is not a ParserElement""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other - self + + def __mul__(self,other): + if isinstance(other,int): + minElements, optElements = other,0 + elif isinstance(other,tuple): + other = (other + (None, None))[:2] + if other[0] is None: + other = (0, other[1]) + if isinstance(other[0],int) and other[1] is None: + if other[0] == 0: + return ZeroOrMore(self) + if other[0] == 1: + return OneOrMore(self) + else: + return self*other[0] + ZeroOrMore(self) + elif isinstance(other[0],int) and isinstance(other[1],int): + minElements, optElements = other + optElements -= minElements + else: + raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1])) + else: + raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other)) + + if minElements < 0: + raise ValueError("cannot multiply ParserElement by negative value") + if optElements < 0: + raise ValueError("second tuple value must be greater or equal to first tuple value") + if minElements == optElements == 0: + raise ValueError("cannot multiply ParserElement by 0 or (0,0)") + + if (optElements): + def makeOptionalList(n): + if n>1: + return Optional(self + makeOptionalList(n-1)) + else: + return Optional(self) + if minElements: + if minElements == 1: + ret = self + makeOptionalList(optElements) + else: + ret = And([self]*minElements) + makeOptionalList(optElements) + else: + ret = makeOptionalList(optElements) + else: + if minElements == 1: + ret = self + else: + ret = And([self]*minElements) + return ret + + def __rmul__(self, other): + return self.__mul__(other) + + def __or__(self, other ): + """Implementation of | operator - returns MatchFirst""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return MatchFirst( [ self, other ] ) + + def __ror__(self, other ): + """Implementation of | operator when left operand is not a ParserElement""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other | self + + def __xor__(self, other ): + """Implementation of ^ operator - returns Or""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Or( [ self, other ] ) + + def __rxor__(self, other ): + """Implementation of ^ operator when left operand is not a ParserElement""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other ^ self + + def __and__(self, other ): + """Implementation of & operator - returns Each""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Each( [ self, other ] ) + + def __rand__(self, other ): + """Implementation of & operator when left operand is not a ParserElement""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other & self + + def __invert__( self ): + """Implementation of ~ operator - returns NotAny""" + return NotAny( self ) + + def __call__(self, name): + """Shortcut for setResultsName, with listAllMatches=default:: + userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno") + could be written as:: + userdata = Word(alphas)("name") + Word(nums+"-")("socsecno") + """ + return self.setResultsName(name) + + def suppress( self ): + """Suppresses the output of this ParserElement; useful to keep punctuation from + cluttering up returned output. + """ + return Suppress( self ) + + def leaveWhitespace( self ): + """Disables the skipping of whitespace before matching the characters in the + ParserElement's defined pattern. This is normally only used internally by + the pyparsing module, but may be needed in some whitespace-sensitive grammars. + """ + self.skipWhitespace = False + return self + + def setWhitespaceChars( self, chars ): + """Overrides the default whitespace chars + """ + self.skipWhitespace = True + self.whiteChars = chars + self.copyDefaultWhiteChars = False + return self + + def parseWithTabs( self ): + """Overrides default behavior to expand s to spaces before parsing the input string. + Must be called before parseString when the input grammar contains elements that + match characters.""" + self.keepTabs = True + return self + + def ignore( self, other ): + """Define expression to be ignored (e.g., comments) while doing pattern + matching; may be called repeatedly, to define multiple comment or other + ignorable patterns. + """ + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + self.ignoreExprs.append( other ) + else: + self.ignoreExprs.append( Suppress( other ) ) + return self + + def setDebugActions( self, startAction, successAction, exceptionAction ): + """Enable display of debugging messages while doing pattern matching.""" + self.debugActions = (startAction or _defaultStartDebugAction, + successAction or _defaultSuccessDebugAction, + exceptionAction or _defaultExceptionDebugAction) + self.debug = True + return self + + def setDebug( self, flag=True ): + """Enable display of debugging messages while doing pattern matching. + Set flag to True to enable, False to disable.""" + if flag: + self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction ) + else: + self.debug = False + return self + + def __str__( self ): + return self.name + + def __repr__( self ): + return _ustr(self) + + def streamline( self ): + self.streamlined = True + self.strRepr = None + return self + + def checkRecursion( self, parseElementList ): + pass + + def validate( self, validateTrace=[] ): + """Check defined expressions for valid structure, check for infinite recursive definitions.""" + self.checkRecursion( [] ) + + def parseFile( self, file_or_filename, parseAll=False ): + """Execute the parse expression on the given file or filename. + If a filename is specified (instead of a file object), + the entire file is opened, read, and closed before parsing. + """ + try: + file_contents = file_or_filename.read() + except AttributeError: + f = open(file_or_filename, "rb") + file_contents = f.read() + f.close() + try: + return self.parseString(file_contents, parseAll) + except ParseBaseException, exc: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def getException(self): + return ParseException("",0,self.errmsg,self) + + def __getattr__(self,aname): + if aname == "myException": + self.myException = ret = self.getException(); + return ret; + else: + raise AttributeError("no such attribute " + aname) + + def __eq__(self,other): + if isinstance(other, ParserElement): + return self is other or self.__dict__ == other.__dict__ + elif isinstance(other, basestring): + try: + self.parseString(_ustr(other), parseAll=True) + return True + except ParseBaseException: + return False + else: + return super(ParserElement,self)==other + + def __ne__(self,other): + return not (self == other) + + def __hash__(self): + return hash(id(self)) + + def __req__(self,other): + return self == other + + def __rne__(self,other): + return not (self == other) + + +class Token(ParserElement): + """Abstract ParserElement subclass, for defining atomic matching patterns.""" + def __init__( self ): + super(Token,self).__init__( savelist=False ) + #self.myException = ParseException("",0,"",self) + + def setName(self, name): + s = super(Token,self).setName(name) + self.errmsg = "Expected " + self.name + #s.myException.msg = self.errmsg + return s + + +class Empty(Token): + """An empty token, will always match.""" + def __init__( self ): + super(Empty,self).__init__() + self.name = "Empty" + self.mayReturnEmpty = True + self.mayIndexError = False + + +class NoMatch(Token): + """A token that will never match.""" + def __init__( self ): + super(NoMatch,self).__init__() + self.name = "NoMatch" + self.mayReturnEmpty = True + self.mayIndexError = False + self.errmsg = "Unmatchable token" + #self.myException.msg = self.errmsg + + def parseImpl( self, instring, loc, doActions=True ): + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + +class Literal(Token): + """Token to exactly match a specified string.""" + def __init__( self, matchString ): + super(Literal,self).__init__() + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Literal; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.__class__ = Empty + self.name = '"%s"' % _ustr(self.match) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + #self.myException.msg = self.errmsg + self.mayIndexError = False + + # Performance tuning: this routine gets called a *lot* + # if this is a single character match string and the first character matches, + # short-circuit as quickly as possible, and avoid calling startswith + #~ @profile + def parseImpl( self, instring, loc, doActions=True ): + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) ): + return loc+self.matchLen, self.match + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc +_L = Literal + +class Keyword(Token): + """Token to exactly match a specified string as a keyword, that is, it must be + immediately followed by a non-keyword character. Compare with Literal:: + Literal("if") will match the leading 'if' in 'ifAndOnlyIf'. + Keyword("if") will not; it will only match the leading 'if in 'if x=1', or 'if(y==2)' + Accepts two optional constructor arguments in addition to the keyword string: + identChars is a string of characters that would be valid identifier characters, + defaulting to all alphanumerics + "_" and "$"; caseless allows case-insensitive + matching, default is False. + """ + DEFAULT_KEYWORD_CHARS = alphanums+"_$" + + def __init__( self, matchString, identChars=DEFAULT_KEYWORD_CHARS, caseless=False ): + super(Keyword,self).__init__() + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Keyword; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.name = '"%s"' % self.match + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + #self.myException.msg = self.errmsg + self.mayIndexError = False + self.caseless = caseless + if caseless: + self.caselessmatch = matchString.upper() + identChars = identChars.upper() + self.identChars = _str2dict(identChars) + + def parseImpl( self, instring, loc, doActions=True ): + if self.caseless: + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and + (loc == 0 or instring[loc-1].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + else: + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and + (loc == 0 or instring[loc-1] not in self.identChars) ): + return loc+self.matchLen, self.match + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + def copy(self): + c = super(Keyword,self).copy() + c.identChars = Keyword.DEFAULT_KEYWORD_CHARS + return c + + def setDefaultKeywordChars( chars ): + """Overrides the default Keyword chars + """ + Keyword.DEFAULT_KEYWORD_CHARS = chars + setDefaultKeywordChars = staticmethod(setDefaultKeywordChars) + +class CaselessLiteral(Literal): + """Token to match a specified string, ignoring case of letters. + Note: the matched results will always be in the case of the given + match string, NOT the case of the input text. + """ + def __init__( self, matchString ): + super(CaselessLiteral,self).__init__( matchString.upper() ) + # Preserve the defining literal. + self.returnString = matchString + self.name = "'%s'" % self.returnString + self.errmsg = "Expected " + self.name + #self.myException.msg = self.errmsg + + def parseImpl( self, instring, loc, doActions=True ): + if instring[ loc:loc+self.matchLen ].upper() == self.match: + return loc+self.matchLen, self.returnString + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + +class CaselessKeyword(Keyword): + def __init__( self, matchString, identChars=Keyword.DEFAULT_KEYWORD_CHARS ): + super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True ) + + def parseImpl( self, instring, loc, doActions=True ): + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + +class Word(Token): + """Token for matching words composed of allowed character sets. + Defined with string containing all allowed initial characters, + an optional string containing allowed body characters (if omitted, + defaults to the initial character set), and an optional minimum, + maximum, and/or exact length. The default value for min is 1 (a + minimum value < 1 is not valid); the default values for max and exact + are 0, meaning no maximum or exact length restriction. + """ + def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False ): + super(Word,self).__init__() + self.initCharsOrig = initChars + self.initChars = _str2dict(initChars) + if bodyChars : + self.bodyCharsOrig = bodyChars + self.bodyChars = _str2dict(bodyChars) + else: + self.bodyCharsOrig = initChars + self.bodyChars = _str2dict(initChars) + + self.maxSpecified = max > 0 + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + #self.myException.msg = self.errmsg + self.mayIndexError = False + self.asKeyword = asKeyword + + if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0): + if self.bodyCharsOrig == self.initCharsOrig: + self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig) + elif len(self.bodyCharsOrig) == 1: + self.reString = "%s[%s]*" % \ + (re.escape(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + else: + self.reString = "[%s][%s]*" % \ + (_escapeRegexRangeChars(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + if self.asKeyword: + self.reString = r"\b"+self.reString+r"\b" + try: + self.re = re.compile( self.reString ) + except: + self.re = None + + def parseImpl( self, instring, loc, doActions=True ): + if self.re: + result = self.re.match(instring,loc) + if not result: + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + loc = result.end() + return loc,result.group() + + if not(instring[ loc ] in self.initChars): + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + start = loc + loc += 1 + instrlen = len(instring) + bodychars = self.bodyChars + maxloc = start + self.maxLen + maxloc = min( maxloc, instrlen ) + while loc < maxloc and instring[loc] in bodychars: + loc += 1 + + throwException = False + if loc - start < self.minLen: + throwException = True + if self.maxSpecified and loc < instrlen and instring[loc] in bodychars: + throwException = True + if self.asKeyword: + if (start>0 and instring[start-1] in bodychars) or (loc4: + return s[:4]+"..." + else: + return s + + if ( self.initCharsOrig != self.bodyCharsOrig ): + self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) ) + else: + self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig) + + return self.strRepr + + +class Regex(Token): + """Token for matching strings that match a given regular expression. + Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. + """ + def __init__( self, pattern, flags=0): + """The parameters pattern and flags are passed to the re.compile() function as-is. See the Python re module for an explanation of the acceptable patterns and flags.""" + super(Regex,self).__init__() + + if len(pattern) == 0: + warnings.warn("null string passed to Regex; use Empty() instead", + SyntaxWarning, stacklevel=2) + + self.pattern = pattern + self.flags = flags + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % pattern, + SyntaxWarning, stacklevel=2) + raise + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + #self.myException.msg = self.errmsg + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = self.re.match(instring,loc) + if not result: + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + loc = result.end() + d = result.groupdict() + ret = ParseResults(result.group()) + if d: + for k in d: + ret[k] = d[k] + return loc,ret + + def __str__( self ): + try: + return super(Regex,self).__str__() + except: + pass + + if self.strRepr is None: + self.strRepr = "Re:(%s)" % repr(self.pattern) + + return self.strRepr + + +class QuotedString(Token): + """Token for matching strings that are delimited by quoting characters. + """ + def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None): + """ + Defined with the following parameters: + - quoteChar - string of one or more characters defining the quote delimiting string + - escChar - character to escape quotes, typically backslash (default=None) + - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=None) + - multiline - boolean indicating whether quotes can span multiple lines (default=False) + - unquoteResults - boolean indicating whether the matched text should be unquoted (default=True) + - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=None => same as quoteChar) + """ + super(QuotedString,self).__init__() + + # remove white space from quote chars - wont work anyway + quoteChar = quoteChar.strip() + if len(quoteChar) == 0: + warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + if endQuoteChar is None: + endQuoteChar = quoteChar + else: + endQuoteChar = endQuoteChar.strip() + if len(endQuoteChar) == 0: + warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + self.quoteChar = quoteChar + self.quoteCharLen = len(quoteChar) + self.firstQuoteChar = quoteChar[0] + self.endQuoteChar = endQuoteChar + self.endQuoteCharLen = len(endQuoteChar) + self.escChar = escChar + self.escQuote = escQuote + self.unquoteResults = unquoteResults + + if multiline: + self.flags = re.MULTILINE | re.DOTALL + self.pattern = r'%s(?:[^%s%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + else: + self.flags = 0 + self.pattern = r'%s(?:[^%s\n\r%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + if len(self.endQuoteChar) > 1: + self.pattern += ( + '|(?:' + ')|(?:'.join(["%s[^%s]" % (re.escape(self.endQuoteChar[:i]), + _escapeRegexRangeChars(self.endQuoteChar[i])) + for i in range(len(self.endQuoteChar)-1,0,-1)]) + ')' + ) + if escQuote: + self.pattern += (r'|(?:%s)' % re.escape(escQuote)) + if escChar: + self.pattern += (r'|(?:%s.)' % re.escape(escChar)) + self.escCharReplacePattern = re.escape(self.escChar)+"(.)" + self.pattern += (r')*%s' % re.escape(self.endQuoteChar)) + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, + SyntaxWarning, stacklevel=2) + raise + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + #self.myException.msg = self.errmsg + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None + if not result: + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + loc = result.end() + ret = result.group() + + if self.unquoteResults: + + # strip off quotes + ret = ret[self.quoteCharLen:-self.endQuoteCharLen] + + if isinstance(ret,basestring): + # replace escaped characters + if self.escChar: + ret = re.sub(self.escCharReplacePattern,"\g<1>",ret) + + # replace escaped quotes + if self.escQuote: + ret = ret.replace(self.escQuote, self.endQuoteChar) + + return loc, ret + + def __str__( self ): + try: + return super(QuotedString,self).__str__() + except: + pass + + if self.strRepr is None: + self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar) + + return self.strRepr + + +class CharsNotIn(Token): + """Token for matching words composed of characters *not* in a given set. + Defined with string containing all disallowed characters, and an optional + minimum, maximum, and/or exact length. The default value for min is 1 (a + minimum value < 1 is not valid); the default values for max and exact + are 0, meaning no maximum or exact length restriction. + """ + def __init__( self, notChars, min=1, max=0, exact=0 ): + super(CharsNotIn,self).__init__() + self.skipWhitespace = False + self.notChars = notChars + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = ( self.minLen == 0 ) + #self.myException.msg = self.errmsg + self.mayIndexError = False + + def parseImpl( self, instring, loc, doActions=True ): + if instring[loc] in self.notChars: + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + start = loc + loc += 1 + notchars = self.notChars + maxlen = min( start+self.maxLen, len(instring) ) + while loc < maxlen and \ + (instring[loc] not in notchars): + loc += 1 + + if loc - start < self.minLen: + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(CharsNotIn, self).__str__() + except: + pass + + if self.strRepr is None: + if len(self.notChars) > 4: + self.strRepr = "!W:(%s...)" % self.notChars[:4] + else: + self.strRepr = "!W:(%s)" % self.notChars + + return self.strRepr + +class White(Token): + """Special matching class for matching whitespace. Normally, whitespace is ignored + by pyparsing grammars. This class is included when some whitespace structures + are significant. Define with a string containing the whitespace characters to be + matched; default is " \\t\\r\\n". Also takes optional min, max, and exact arguments, + as defined for the Word class.""" + whiteStrs = { + " " : "", + "\t": "", + "\n": "", + "\r": "", + "\f": "", + } + def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0): + super(White,self).__init__() + self.matchWhite = ws + self.setWhitespaceChars( "".join([c for c in self.whiteChars if c not in self.matchWhite]) ) + #~ self.leaveWhitespace() + self.name = ("".join([White.whiteStrs[c] for c in self.matchWhite])) + self.mayReturnEmpty = True + self.errmsg = "Expected " + self.name + #self.myException.msg = self.errmsg + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + def parseImpl( self, instring, loc, doActions=True ): + if not(instring[ loc ] in self.matchWhite): + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + start = loc + loc += 1 + maxloc = start + self.maxLen + maxloc = min( maxloc, len(instring) ) + while loc < maxloc and instring[loc] in self.matchWhite: + loc += 1 + + if loc - start < self.minLen: + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + return loc, instring[start:loc] + + +class _PositionToken(Token): + def __init__( self ): + super(_PositionToken,self).__init__() + self.name=self.__class__.__name__ + self.mayReturnEmpty = True + self.mayIndexError = False + +class GoToColumn(_PositionToken): + """Token to advance to a specific column of input text; useful for tabular report scraping.""" + def __init__( self, colno ): + super(GoToColumn,self).__init__() + self.col = colno + + def preParse( self, instring, loc ): + if col(loc,instring) != self.col: + instrlen = len(instring) + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col : + loc += 1 + return loc + + def parseImpl( self, instring, loc, doActions=True ): + thiscol = col( loc, instring ) + if thiscol > self.col: + raise ParseException( instring, loc, "Text not in expected column", self ) + newloc = loc + self.col - thiscol + ret = instring[ loc: newloc ] + return newloc, ret + +class LineStart(_PositionToken): + """Matches if current position is at the beginning of a line within the parse string""" + def __init__( self ): + super(LineStart,self).__init__() + self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") ) + self.errmsg = "Expected start of line" + #self.myException.msg = self.errmsg + + def preParse( self, instring, loc ): + preloc = super(LineStart,self).preParse(instring,loc) + if instring[preloc] == "\n": + loc += 1 + return loc + + def parseImpl( self, instring, loc, doActions=True ): + if not( loc==0 or + (loc == self.preParse( instring, 0 )) or + (instring[loc-1] == "\n") ): #col(loc, instring) != 1: + #~ raise ParseException( instring, loc, "Expected start of line" ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + return loc, [] + +class LineEnd(_PositionToken): + """Matches if current position is at the end of a line within the parse string""" + def __init__( self ): + super(LineEnd,self).__init__() + self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") ) + self.errmsg = "Expected end of line" + #self.myException.msg = self.errmsg + + def parseImpl( self, instring, loc, doActions=True ): + if loc len(instring): + return loc, [] + else: + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + +class WordStart(_PositionToken): + """Matches if the current position is at the beginning of a Word, and + is not preceded by any character in a given set of wordChars + (default=printables). To emulate the \b behavior of regular expressions, + use WordStart(alphanums). WordStart will also match at the beginning of + the string being parsed, or at the beginning of a line. + """ + def __init__(self, wordChars = printables): + super(WordStart,self).__init__() + self.wordChars = _str2dict(wordChars) + self.errmsg = "Not at the start of a word" + + def parseImpl(self, instring, loc, doActions=True ): + if loc != 0: + if (instring[loc-1] in self.wordChars or + instring[loc] not in self.wordChars): + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + return loc, [] + +class WordEnd(_PositionToken): + """Matches if the current position is at the end of a Word, and + is not followed by any character in a given set of wordChars + (default=printables). To emulate the \b behavior of regular expressions, + use WordEnd(alphanums). WordEnd will also match at the end of + the string being parsed, or at the end of a line. + """ + def __init__(self, wordChars = printables): + super(WordEnd,self).__init__() + self.wordChars = _str2dict(wordChars) + self.skipWhitespace = False + self.errmsg = "Not at the end of a word" + + def parseImpl(self, instring, loc, doActions=True ): + instrlen = len(instring) + if instrlen>0 and loc maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + else: + if loc2 > maxMatchLoc: + maxMatchLoc = loc2 + maxMatchExp = e + + if maxMatchLoc < 0: + if maxException is not None: + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + return maxMatchExp._parse( instring, loc, doActions ) + + def __ixor__(self, other ): + if isinstance( other, basestring ): + other = Literal( other ) + return self.append( other ) #Or( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ^ ".join( [ _ustr(e) for e in self.exprs ] ) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class MatchFirst(ParseExpression): + """Requires that at least one ParseExpression is found. + If two expressions match, the first one listed is the one that will match. + May be constructed using the '|' operator. + """ + def __init__( self, exprs, savelist = False ): + super(MatchFirst,self).__init__(exprs, savelist) + if exprs: + self.mayReturnEmpty = False + for e in self.exprs: + if e.mayReturnEmpty: + self.mayReturnEmpty = True + break + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + maxException = None + for e in self.exprs: + try: + ret = e._parse( instring, loc, doActions ) + return ret + except ParseException, err: + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + + # only got here if no expression matched, raise exception for match that made it the furthest + else: + if maxException is not None: + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + def __ior__(self, other ): + if isinstance( other, basestring ): + other = Literal( other ) + return self.append( other ) #MatchFirst( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " | ".join( [ _ustr(e) for e in self.exprs ] ) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class Each(ParseExpression): + """Requires all given ParseExpressions to be found, but in any order. + Expressions may be separated by whitespace. + May be constructed using the '&' operator. + """ + def __init__( self, exprs, savelist = True ): + super(Each,self).__init__(exprs, savelist) + self.mayReturnEmpty = True + for e in self.exprs: + if not e.mayReturnEmpty: + self.mayReturnEmpty = False + break + self.skipWhitespace = True + self.initExprGroups = True + + def parseImpl( self, instring, loc, doActions=True ): + if self.initExprGroups: + self.optionals = [ e.expr for e in self.exprs if isinstance(e,Optional) ] + self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ] + self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ] + self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] + self.required += self.multirequired + self.initExprGroups = False + tmpLoc = loc + tmpReqd = self.required[:] + tmpOpt = self.optionals[:] + matchOrder = [] + + keepMatching = True + while keepMatching: + tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired + failed = [] + for e in tmpExprs: + try: + tmpLoc = e.tryParse( instring, tmpLoc ) + except ParseException: + failed.append(e) + else: + matchOrder.append(e) + if e in tmpReqd: + tmpReqd.remove(e) + elif e in tmpOpt: + tmpOpt.remove(e) + if len(failed) == len(tmpExprs): + keepMatching = False + + if tmpReqd: + missing = ", ".join( [ _ustr(e) for e in tmpReqd ] ) + raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing ) + + # add any unmatched Optionals, in case they have default values defined + matchOrder += list(e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt) + + resultlist = [] + for e in matchOrder: + loc,results = e._parse(instring,loc,doActions) + resultlist.append(results) + + finalResults = ParseResults([]) + for r in resultlist: + dups = {} + for k in r.keys(): + if k in finalResults.keys(): + tmp = ParseResults(finalResults[k]) + tmp += ParseResults(r[k]) + dups[k] = tmp + finalResults += ParseResults(r) + for k,v in dups.items(): + finalResults[k] = v + return loc, finalResults + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " & ".join( [ _ustr(e) for e in self.exprs ] ) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class ParseElementEnhance(ParserElement): + """Abstract subclass of ParserElement, for combining and post-processing parsed tokens.""" + def __init__( self, expr, savelist=False ): + super(ParseElementEnhance,self).__init__(savelist) + if isinstance( expr, basestring ): + expr = Literal(expr) + self.expr = expr + self.strRepr = None + if expr is not None: + self.mayIndexError = expr.mayIndexError + self.mayReturnEmpty = expr.mayReturnEmpty + self.setWhitespaceChars( expr.whiteChars ) + self.skipWhitespace = expr.skipWhitespace + self.saveAsList = expr.saveAsList + self.callPreparse = expr.callPreparse + self.ignoreExprs.extend(expr.ignoreExprs) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr is not None: + return self.expr._parse( instring, loc, doActions, callPreParse=False ) + else: + raise ParseException("",loc,self.errmsg,self) + + def leaveWhitespace( self ): + self.skipWhitespace = False + self.expr = self.expr.copy() + if self.expr is not None: + self.expr.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + else: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + return self + + def streamline( self ): + super(ParseElementEnhance,self).streamline() + if self.expr is not None: + self.expr.streamline() + return self + + def checkRecursion( self, parseElementList ): + if self in parseElementList: + raise RecursiveGrammarException( parseElementList+[self] ) + subRecCheckList = parseElementList[:] + [ self ] + if self.expr is not None: + self.expr.checkRecursion( subRecCheckList ) + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion( [] ) + + def __str__( self ): + try: + return super(ParseElementEnhance,self).__str__() + except: + pass + + if self.strRepr is None and self.expr is not None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) ) + return self.strRepr + + +class FollowedBy(ParseElementEnhance): + """Lookahead matching of the given parse expression. FollowedBy + does *not* advance the parsing position within the input string, it only + verifies that the specified parse expression matches at the current + position. FollowedBy always returns a null token list.""" + def __init__( self, expr ): + super(FollowedBy,self).__init__(expr) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + self.expr.tryParse( instring, loc ) + return loc, [] + + +class NotAny(ParseElementEnhance): + """Lookahead to disallow matching with the given parse expression. NotAny + does *not* advance the parsing position within the input string, it only + verifies that the specified parse expression does *not* match at the current + position. Also, NotAny does *not* skip over leading whitespace. NotAny + always returns a null token list. May be constructed using the '~' operator.""" + def __init__( self, expr ): + super(NotAny,self).__init__(expr) + #~ self.leaveWhitespace() + self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs + self.mayReturnEmpty = True + self.errmsg = "Found unwanted token, "+_ustr(self.expr) + #self.myException = ParseException("",0,self.errmsg,self) + + def parseImpl( self, instring, loc, doActions=True ): + try: + self.expr.tryParse( instring, loc ) + except (ParseException,IndexError): + pass + else: + #~ raise ParseException(instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "~{" + _ustr(self.expr) + "}" + + return self.strRepr + + +class ZeroOrMore(ParseElementEnhance): + """Optional repetition of zero or more of the given expression.""" + def __init__( self, expr ): + super(ZeroOrMore,self).__init__(expr) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + tokens = [] + try: + loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) + hasIgnoreExprs = ( len(self.ignoreExprs) > 0 ) + while 1: + if hasIgnoreExprs: + preloc = self._skipIgnorables( instring, loc ) + else: + preloc = loc + loc, tmptokens = self.expr._parse( instring, preloc, doActions ) + if tmptokens or tmptokens.keys(): + tokens += tmptokens + except (ParseException,IndexError): + pass + + return loc, tokens + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]..." + + return self.strRepr + + def setResultsName( self, name, listAllMatches=False ): + ret = super(ZeroOrMore,self).setResultsName(name,listAllMatches) + ret.saveAsList = True + return ret + + +class OneOrMore(ParseElementEnhance): + """Repetition of one or more of the given expression.""" + def parseImpl( self, instring, loc, doActions=True ): + # must be at least one + loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) + try: + hasIgnoreExprs = ( len(self.ignoreExprs) > 0 ) + while 1: + if hasIgnoreExprs: + preloc = self._skipIgnorables( instring, loc ) + else: + preloc = loc + loc, tmptokens = self.expr._parse( instring, preloc, doActions ) + if tmptokens or tmptokens.keys(): + tokens += tmptokens + except (ParseException,IndexError): + pass + + return loc, tokens + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + _ustr(self.expr) + "}..." + + return self.strRepr + + def setResultsName( self, name, listAllMatches=False ): + ret = super(OneOrMore,self).setResultsName(name,listAllMatches) + ret.saveAsList = True + return ret + +class _NullToken(object): + def __bool__(self): + return False + __nonzero__ = __bool__ + def __str__(self): + return "" + +_optionalNotMatched = _NullToken() +class Optional(ParseElementEnhance): + """Optional matching of the given expression. + A default return string can also be specified, if the optional expression + is not found. + """ + def __init__( self, exprs, default=_optionalNotMatched ): + super(Optional,self).__init__( exprs, savelist=False ) + self.defaultValue = default + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) + except (ParseException,IndexError): + if self.defaultValue is not _optionalNotMatched: + if self.expr.resultsName: + tokens = ParseResults([ self.defaultValue ]) + tokens[self.expr.resultsName] = self.defaultValue + else: + tokens = [ self.defaultValue ] + else: + tokens = [] + return loc, tokens + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]" + + return self.strRepr + + +class SkipTo(ParseElementEnhance): + """Token for skipping over all undefined text until the matched expression is found. + If include is set to true, the matched expression is also parsed (the skipped text + and matched expression are returned as a 2-element list). The ignore + argument is used to define grammars (typically quoted strings and comments) that + might contain false matches. + """ + def __init__( self, other, include=False, ignore=None, failOn=None ): + super( SkipTo, self ).__init__( other ) + self.ignoreExpr = ignore + self.mayReturnEmpty = True + self.mayIndexError = False + self.includeMatch = include + self.asList = False + if failOn is not None and isinstance(failOn, basestring): + self.failOn = Literal(failOn) + else: + self.failOn = failOn + self.errmsg = "No match found for "+_ustr(self.expr) + #self.myException = ParseException("",0,self.errmsg,self) + + def parseImpl( self, instring, loc, doActions=True ): + startLoc = loc + instrlen = len(instring) + expr = self.expr + failParse = False + while loc <= instrlen: + try: + if self.failOn: + try: + self.failOn.tryParse(instring, loc) + except ParseBaseException: + pass + else: + failParse = True + raise ParseException(instring, loc, "Found expression " + str(self.failOn)) + failParse = False + if self.ignoreExpr is not None: + while 1: + try: + loc = self.ignoreExpr.tryParse(instring,loc) + print "found ignoreExpr, advance to", loc + except ParseBaseException: + break + expr._parse( instring, loc, doActions=False, callPreParse=False ) + skipText = instring[startLoc:loc] + if self.includeMatch: + loc,mat = expr._parse(instring,loc,doActions,callPreParse=False) + if mat: + skipRes = ParseResults( skipText ) + skipRes += mat + return loc, [ skipRes ] + else: + return loc, [ skipText ] + else: + return loc, [ skipText ] + except (ParseException,IndexError): + if failParse: + raise + else: + loc += 1 + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + +class Forward(ParseElementEnhance): + """Forward declaration of an expression to be defined later - + used for recursive grammars, such as algebraic infix notation. + When the expression is known, it is assigned to the Forward variable using the '<<' operator. + + Note: take care when assigning to Forward not to overlook precedence of operators. + Specifically, '|' has a lower precedence than '<<', so that:: + fwdExpr << a | b | c + will actually be evaluated as:: + (fwdExpr << a) | b | c + thereby leaving b and c out as parseable alternatives. It is recommended that you + explicitly group the values inserted into the Forward:: + fwdExpr << (a | b | c) + """ + def __init__( self, other=None ): + super(Forward,self).__init__( other, savelist=False ) + + def __lshift__( self, other ): + if isinstance( other, basestring ): + other = Literal(other) + self.expr = other + self.mayReturnEmpty = other.mayReturnEmpty + self.strRepr = None + self.mayIndexError = self.expr.mayIndexError + self.mayReturnEmpty = self.expr.mayReturnEmpty + self.setWhitespaceChars( self.expr.whiteChars ) + self.skipWhitespace = self.expr.skipWhitespace + self.saveAsList = self.expr.saveAsList + self.ignoreExprs.extend(self.expr.ignoreExprs) + return None + + def leaveWhitespace( self ): + self.skipWhitespace = False + return self + + def streamline( self ): + if not self.streamlined: + self.streamlined = True + if self.expr is not None: + self.expr.streamline() + return self + + def validate( self, validateTrace=[] ): + if self not in validateTrace: + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion([]) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + self._revertClass = self.__class__ + self.__class__ = _ForwardNoRecurse + try: + if self.expr is not None: + retString = _ustr(self.expr) + else: + retString = "None" + finally: + self.__class__ = self._revertClass + return self.__class__.__name__ + ": " + retString + + def copy(self): + if self.expr is not None: + return super(Forward,self).copy() + else: + ret = Forward() + ret << self + return ret + +class _ForwardNoRecurse(Forward): + def __str__( self ): + return "..." + +class TokenConverter(ParseElementEnhance): + """Abstract subclass of ParseExpression, for converting parsed results.""" + def __init__( self, expr, savelist=False ): + super(TokenConverter,self).__init__( expr )#, savelist ) + self.saveAsList = False + +class Upcase(TokenConverter): + """Converter to upper case all matching tokens.""" + def __init__(self, *args): + super(Upcase,self).__init__(*args) + warnings.warn("Upcase class is deprecated, use upcaseTokens parse action instead", + DeprecationWarning,stacklevel=2) + + def postParse( self, instring, loc, tokenlist ): + return list(map( string.upper, tokenlist )) + + +class Combine(TokenConverter): + """Converter to concatenate all matching tokens to a single string. + By default, the matching patterns must also be contiguous in the input string; + this can be disabled by specifying 'adjacent=False' in the constructor. + """ + def __init__( self, expr, joinString="", adjacent=True ): + super(Combine,self).__init__( expr ) + # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself + if adjacent: + self.leaveWhitespace() + self.adjacent = adjacent + self.skipWhitespace = True + self.joinString = joinString + + def ignore( self, other ): + if self.adjacent: + ParserElement.ignore(self, other) + else: + super( Combine, self).ignore( other ) + return self + + def postParse( self, instring, loc, tokenlist ): + retToks = tokenlist.copy() + del retToks[:] + retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults) + + if self.resultsName and len(retToks.keys())>0: + return [ retToks ] + else: + return retToks + +class Group(TokenConverter): + """Converter to return the matched tokens as a list - useful for returning tokens of ZeroOrMore and OneOrMore expressions.""" + def __init__( self, expr ): + super(Group,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + return [ tokenlist ] + +class Dict(TokenConverter): + """Converter to return a repetitive expression as a list, but also as a dictionary. + Each element can also be referenced using the first token in the expression as its key. + Useful for tabular report scraping when the first column can be used as a item key. + """ + def __init__( self, exprs ): + super(Dict,self).__init__( exprs ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + for i,tok in enumerate(tokenlist): + if len(tok) == 0: + continue + ikey = tok[0] + if isinstance(ikey,int): + ikey = _ustr(tok[0]).strip() + if len(tok)==1: + tokenlist[ikey] = _ParseResultsWithOffset("",i) + elif len(tok)==2 and not isinstance(tok[1],ParseResults): + tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i) + else: + dictvalue = tok.copy() #ParseResults(i) + del dictvalue[0] + if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.keys()): + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i) + else: + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i) + + if self.resultsName: + return [ tokenlist ] + else: + return tokenlist + + +class Suppress(TokenConverter): + """Converter for ignoring the results of a parsed expression.""" + def postParse( self, instring, loc, tokenlist ): + return [] + + def suppress( self ): + return self + + +class OnlyOnce(object): + """Wrapper for parse actions, to ensure they are only called once.""" + def __init__(self, methodCall): + self.callable = ParserElement._normalizeParseActionArgs(methodCall) + self.called = False + def __call__(self,s,l,t): + if not self.called: + results = self.callable(s,l,t) + self.called = True + return results + raise ParseException(s,l,"") + def reset(self): + self.called = False + +def traceParseAction(f): + """Decorator for debugging parse actions.""" + f = ParserElement._normalizeParseActionArgs(f) + def z(*paArgs): + thisFunc = f.func_name + s,l,t = paArgs[-3:] + if len(paArgs)>3: + thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc + sys.stderr.write( ">>entering %s(line: '%s', %d, %s)\n" % (thisFunc,line(l,s),l,t) ) + try: + ret = f(*paArgs) + except Exception, exc: + sys.stderr.write( "<", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )) + try: + if len(symbols)==len("".join(symbols)): + return Regex( "[%s]" % "".join( [ _escapeRegexRangeChars(sym) for sym in symbols] ) ) + else: + return Regex( "|".join( [ re.escape(sym) for sym in symbols] ) ) + except: + warnings.warn("Exception creating Regex for oneOf, building MatchFirst", + SyntaxWarning, stacklevel=2) + + + # last resort, just use MatchFirst + return MatchFirst( [ parseElementClass(sym) for sym in symbols ] ) + +def dictOf( key, value ): + """Helper to easily and clearly define a dictionary by specifying the respective patterns + for the key and value. Takes care of defining the Dict, ZeroOrMore, and Group tokens + in the proper order. The key pattern can include delimiting markers or punctuation, + as long as they are suppressed, thereby leaving the significant key text. The value + pattern can include named results, so that the Dict results can include named token + fields. + """ + return Dict( ZeroOrMore( Group ( key + value ) ) ) + +def originalTextFor(expr, asString=True): + """Helper to return the original, untokenized text for a given expression. Useful to + restore the parsed fields of an HTML start tag into the raw tag text itself, or to + revert separate tokens with intervening whitespace back to the original matching + input text. Simpler to use than the parse action keepOriginalText, and does not + require the inspect module to chase up the call stack. By default, returns a + string containing the original parsed text. + + If the optional asString argument is passed as False, then the return value is a + ParseResults containing any results names that were originally matched, and a + single token containing the original matched text from the input string. So if + the expression passed to originalTextFor contains expressions with defined + results names, you must set asString to False if you want to preserve those + results name values.""" + locMarker = Empty().setParseAction(lambda s,loc,t: loc) + matchExpr = locMarker("_original_start") + expr + locMarker("_original_end") + if asString: + extractText = lambda s,l,t: s[t._original_start:t._original_end] + else: + def extractText(s,l,t): + del t[:] + t.insert(0, s[t._original_start:t._original_end]) + del t["_original_start"] + del t["_original_end"] + matchExpr.setParseAction(extractText) + return matchExpr + +# convenience constants for positional expressions +empty = Empty().setName("empty") +lineStart = LineStart().setName("lineStart") +lineEnd = LineEnd().setName("lineEnd") +stringStart = StringStart().setName("stringStart") +stringEnd = StringEnd().setName("stringEnd") + +_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1]) +_printables_less_backslash = "".join([ c for c in printables if c not in r"\]" ]) +_escapedHexChar = Combine( Suppress(_bslash + "0x") + Word(hexnums) ).setParseAction(lambda s,l,t:unichr(int(t[0],16))) +_escapedOctChar = Combine( Suppress(_bslash) + Word("0","01234567") ).setParseAction(lambda s,l,t:unichr(int(t[0],8))) +_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | Word(_printables_less_backslash,exact=1) +_charRange = Group(_singleChar + Suppress("-") + _singleChar) +_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]" + +_expanded = lambda p: (isinstance(p,ParseResults) and ''.join([ unichr(c) for c in range(ord(p[0]),ord(p[1])+1) ]) or p) + +def srange(s): + r"""Helper to easily define string ranges for use in Word construction. Borrows + syntax from regexp '[]' string range definitions:: + srange("[0-9]") -> "0123456789" + srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" + srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" + The input string must be enclosed in []'s, and the returned string is the expanded + character set joined into a single string. + The values enclosed in the []'s may be:: + a single character + an escaped character with a leading backslash (such as \- or \]) + an escaped hex character with a leading '\0x' (\0x21, which is a '!' character) + an escaped octal character with a leading '\0' (\041, which is a '!' character) + a range of any of the above, separated by a dash ('a-z', etc.) + any combination of the above ('aeiouy', 'a-zA-Z0-9_$', etc.) + """ + try: + return "".join([_expanded(part) for part in _reBracketExpr.parseString(s).body]) + except: + return "" + +def matchOnlyAtCol(n): + """Helper method for defining parse actions that require matching at a specific + column in the input text. + """ + def verifyCol(strg,locn,toks): + if col(locn,strg) != n: + raise ParseException(strg,locn,"matched token not at column %d" % n) + return verifyCol + +def replaceWith(replStr): + """Helper method for common parse actions that simply return a literal value. Especially + useful when used with transformString(). + """ + def _replFunc(*args): + return [replStr] + return _replFunc + +def removeQuotes(s,l,t): + """Helper parse action for removing quotation marks from parsed quoted strings. + To use, add this parse action to quoted string using:: + quotedString.setParseAction( removeQuotes ) + """ + return t[0][1:-1] + +def upcaseTokens(s,l,t): + """Helper parse action to convert tokens to upper case.""" + return [ tt.upper() for tt in map(_ustr,t) ] + +def downcaseTokens(s,l,t): + """Helper parse action to convert tokens to lower case.""" + return [ tt.lower() for tt in map(_ustr,t) ] + +def keepOriginalText(s,startLoc,t): + """Helper parse action to preserve original parsed text, + overriding any nested parse actions.""" + try: + endloc = getTokensEndLoc() + except ParseException: + raise ParseFatalException("incorrect usage of keepOriginalText - may only be called as a parse action") + del t[:] + t += ParseResults(s[startLoc:endloc]) + return t + +def getTokensEndLoc(): + """Method to be called from within a parse action to determine the end + location of the parsed tokens.""" + import inspect + fstack = inspect.stack() + try: + # search up the stack (through intervening argument normalizers) for correct calling routine + for f in fstack[2:]: + if f[3] == "_parseNoCache": + endloc = f[0].f_locals["loc"] + return endloc + else: + raise ParseFatalException("incorrect usage of getTokensEndLoc - may only be called from within a parse action") + finally: + del fstack + +def _makeTags(tagStr, xml): + """Internal helper to construct opening and closing tag expressions, given a tag name""" + if isinstance(tagStr,basestring): + resname = tagStr + tagStr = Keyword(tagStr, caseless=not xml) + else: + resname = tagStr.name + + tagAttrName = Word(alphas,alphanums+"_-:") + if (xml): + tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes ) + openTag = Suppress("<") + tagStr + \ + Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + else: + printablesLessRAbrack = "".join( [ c for c in printables if c not in ">" ] ) + tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack) + openTag = Suppress("<") + tagStr + \ + Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \ + Optional( Suppress("=") + tagAttrValue ) ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + closeTag = Combine(_L("") + + openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % tagStr) + closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("" % tagStr) + + return openTag, closeTag + +def makeHTMLTags(tagStr): + """Helper to construct opening and closing tag expressions for HTML, given a tag name""" + return _makeTags( tagStr, False ) + +def makeXMLTags(tagStr): + """Helper to construct opening and closing tag expressions for XML, given a tag name""" + return _makeTags( tagStr, True ) + +def withAttribute(*args,**attrDict): + """Helper to create a validating parse action to be used with start tags created + with makeXMLTags or makeHTMLTags. Use withAttribute to qualify a starting tag + with a required attribute value, to avoid false matches on common tags such as + or

. + + Call withAttribute with a series of attribute names and values. Specify the list + of filter attributes names and values as: + - keyword arguments, as in (class="Customer",align="right"), or + - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) + For attribute names with a namespace prefix, you must use the second form. Attribute + names are matched insensitive to upper/lower case. + + To verify that the attribute exists, but without specifying a value, pass + withAttribute.ANY_VALUE as the value. + """ + if args: + attrs = args[:] + else: + attrs = attrDict.items() + attrs = [(k,v) for k,v in attrs] + def pa(s,l,tokens): + for attrName,attrValue in attrs: + if attrName not in tokens: + raise ParseException(s,l,"no matching attribute " + attrName) + if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: + raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % + (attrName, tokens[attrName], attrValue)) + return pa +withAttribute.ANY_VALUE = object() + +opAssoc = _Constants() +opAssoc.LEFT = object() +opAssoc.RIGHT = object() + +def operatorPrecedence( baseExpr, opList ): + """Helper method for constructing grammars of expressions made up of + operators working in a precedence hierarchy. Operators may be unary or + binary, left- or right-associative. Parse actions can also be attached + to operator expressions. + + Parameters: + - baseExpr - expression representing the most basic element for the nested + - opList - list of tuples, one for each operator precedence level in the + expression grammar; each tuple is of the form + (opExpr, numTerms, rightLeftAssoc, parseAction), where: + - opExpr is the pyparsing expression for the operator; + may also be a string, which will be converted to a Literal; + if numTerms is 3, opExpr is a tuple of two expressions, for the + two operators separating the 3 terms + - numTerms is the number of terms for this operator (must + be 1, 2, or 3) + - rightLeftAssoc is the indicator whether the operator is + right or left associative, using the pyparsing-defined + constants opAssoc.RIGHT and opAssoc.LEFT. + - parseAction is the parse action to be associated with + expressions matching this operator expression (the + parse action tuple member may be omitted) + """ + ret = Forward() + lastExpr = baseExpr | ( Suppress('(') + ret + Suppress(')') ) + for i,operDef in enumerate(opList): + opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] + if arity == 3: + if opExpr is None or len(opExpr) != 2: + raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") + opExpr1, opExpr2 = opExpr + thisExpr = Forward()#.setName("expr%d" % i) + if rightLeftAssoc == opAssoc.LEFT: + if arity == 1: + matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) + else: + matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ + Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + elif rightLeftAssoc == opAssoc.RIGHT: + if arity == 1: + # try to avoid LR with this extra test + if not isinstance(opExpr, Optional): + opExpr = Optional(opExpr) + matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) + else: + matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ + Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + else: + raise ValueError("operator must indicate right or left associativity") + if pa: + matchExpr.setParseAction( pa ) + thisExpr << ( matchExpr | lastExpr ) + lastExpr = thisExpr + ret << lastExpr + return ret + +dblQuotedString = Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\x[0-9a-fA-F]+)|(?:\\.))*"').setName("string enclosed in double quotes") +sglQuotedString = Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\x[0-9a-fA-F]+)|(?:\\.))*'").setName("string enclosed in single quotes") +quotedString = Regex(r'''(?:"(?:[^"\n\r\\]|(?:"")|(?:\\x[0-9a-fA-F]+)|(?:\\.))*")|(?:'(?:[^'\n\r\\]|(?:'')|(?:\\x[0-9a-fA-F]+)|(?:\\.))*')''').setName("quotedString using single or double quotes") +unicodeString = Combine(_L('u') + quotedString.copy()) + +def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString): + """Helper method for defining nested lists enclosed in opening and closing + delimiters ("(" and ")" are the default). + + Parameters: + - opener - opening character for a nested list (default="("); can also be a pyparsing expression + - closer - closing character for a nested list (default=")"); can also be a pyparsing expression + - content - expression for items within the nested lists (default=None) + - ignoreExpr - expression for ignoring opening and closing delimiters (default=quotedString) + + If an expression is not provided for the content argument, the nested + expression will capture all whitespace-delimited content between delimiters + as a list of separate values. + + Use the ignoreExpr argument to define expressions that may contain + opening or closing characters that should not be treated as opening + or closing characters for nesting, such as quotedString or a comment + expression. Specify multiple expressions using an Or or MatchFirst. + The default is quotedString, but if no expressions are to be ignored, + then pass None for this argument. + """ + if opener == closer: + raise ValueError("opening and closing strings cannot be the same") + if content is None: + if isinstance(opener,basestring) and isinstance(closer,basestring): + if len(opener) == 1 and len(closer)==1: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (empty+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS + ).setParseAction(lambda t:t[0].strip())) + else: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + ~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + raise ValueError("opening and closing arguments must be strings if no content expression is given") + ret = Forward() + if ignoreExpr is not None: + ret << Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) + else: + ret << Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) + return ret + +def indentedBlock(blockStatementExpr, indentStack, indent=True): + """Helper method for defining space-delimited indentation blocks, such as + those used to define block statements in Python source code. + + Parameters: + - blockStatementExpr - expression defining syntax of statement that + is repeated within the indented block + - indentStack - list created by caller to manage indentation stack + (multiple statementWithIndentedBlock expressions within a single grammar + should share a common indentStack) + - indent - boolean indicating whether block must be indented beyond the + the current level; set to False for block of left-most statements + (default=True) + + A valid block must contain at least one blockStatement. + """ + def checkPeerIndent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if curCol != indentStack[-1]: + if curCol > indentStack[-1]: + raise ParseFatalException(s,l,"illegal nesting") + raise ParseException(s,l,"not a peer entry") + + def checkSubIndent(s,l,t): + curCol = col(l,s) + if curCol > indentStack[-1]: + indentStack.append( curCol ) + else: + raise ParseException(s,l,"not a subentry") + + def checkUnindent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): + raise ParseException(s,l,"not an unindent") + indentStack.pop() + + NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) + INDENT = Empty() + Empty().setParseAction(checkSubIndent) + PEER = Empty().setParseAction(checkPeerIndent) + UNDENT = Empty().setParseAction(checkUnindent) + if indent: + smExpr = Group( Optional(NL) + + FollowedBy(blockStatementExpr) + + INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) + else: + smExpr = Group( Optional(NL) + + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) + blockStatementExpr.ignore(_bslash + LineEnd()) + return smExpr + +alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") +punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") + +anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:")) +commonHTMLEntity = Combine(_L("&") + oneOf("gt lt amp nbsp quot").setResultsName("entity") +";").streamline() +_htmlEntityMap = dict(zip("gt lt amp nbsp quot".split(),'><& "')) +replaceHTMLEntity = lambda t : t.entity in _htmlEntityMap and _htmlEntityMap[t.entity] or None + +# it's easy to get these comment structures wrong - they're very common, so may as well make them available +cStyleComment = Regex(r"/\*(?:[^*]*\*+)+?/").setName("C style comment") + +htmlComment = Regex(r"") +restOfLine = Regex(r".*").leaveWhitespace() +dblSlashComment = Regex(r"\/\/(\\\n|.)*").setName("// comment") +cppStyleComment = Regex(r"/(?:\*(?:[^*]*\*+)+?/|/[^\n]*(?:\n[^\n]*)*?(?:(?" + str(tokenlist)) + print ("tokens = " + str(tokens)) + print ("tokens.columns = " + str(tokens.columns)) + print ("tokens.tables = " + str(tokens.tables)) + print (tokens.asXML("SQL",True)) + except ParseBaseException,err: + print (teststring + "->") + print (err.line) + print (" "*(err.column-1) + "^") + print (err) + print() + + selectToken = CaselessLiteral( "select" ) + fromToken = CaselessLiteral( "from" ) + + ident = Word( alphas, alphanums + "_$" ) + columnName = delimitedList( ident, ".", combine=True ).setParseAction( upcaseTokens ) + columnNameList = Group( delimitedList( columnName ) )#.setName("columns") + tableName = delimitedList( ident, ".", combine=True ).setParseAction( upcaseTokens ) + tableNameList = Group( delimitedList( tableName ) )#.setName("tables") + simpleSQL = ( selectToken + \ + ( '*' | columnNameList ).setResultsName( "columns" ) + \ + fromToken + \ + tableNameList.setResultsName( "tables" ) ) + + test( "SELECT * from XYZZY, ABC" ) + test( "select * from SYS.XYZZY" ) + test( "Select A from Sys.dual" ) + test( "Select AA,BB,CC from Sys.dual" ) + test( "Select A, B, C from Sys.dual" ) + test( "Select A, B, C from Sys.dual" ) + test( "Xelect A, B, C from Sys.dual" ) + test( "Select A, B, C frox Sys.dual" ) + test( "Select" ) + test( "Select ^^^ frox Sys.dual" ) + test( "Select A, B, C from Sys.dual, Table2 " ) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyperclip.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyperclip.py new file mode 100644 index 0000000..c2515da --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyperclip.py @@ -0,0 +1,169 @@ +# Pyperclip v1.0 +# A cross-platform clipboard module for Python. (only handles plain text for now) +# By Al Sweigart al@coffeeghost.net + +# Usage: +# import pyperclip +# pyperclip.setcb('The text to be copied to the clipboard.') +# spam = pyperclip.getcb() + +# On Mac, this module makes use of the pbcopy and pbpaste commands, which should come with the os. +# On Linux, this module makes use of the xclip command, which should come with the os. Otherwise run "sudo apt-get install xclip" + + +# Copyright (c) 2010, Albert Sweigart +# All rights reserved. +# +# BSD-style license: +# +# 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 the pyperclip 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 Albert Sweigart "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 Albert Sweigart 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. + + +import os +import subprocess + +def winGetClipboard(): + try: + ctypes.windll.user32.OpenClipboard(None) + except: + ctypes.windll.user32.OpenClipboard(0) + pcontents = ctypes.windll.user32.GetClipboardData(1) # 1 is CF_TEXT + data = ctypes.c_char_p(pcontents).value + #ctypes.windll.kernel32.GlobalUnlock(pcontents) + ctypes.windll.user32.CloseClipboard() + return data + +def winSetClipboard(text): + GMEM_DDESHARE = 0x2000 + try: + ctypes.windll.user32.OpenClipboard(None) + except: + ctypes.windll.user32.OpenClipboard(0) + ctypes.windll.user32.EmptyClipboard() + try: + # works on Python 2 (bytes() only takes one argument) + hCd = ctypes.windll.kernel32.GlobalAlloc(GMEM_DDESHARE, len(bytes(text))+1) + except TypeError: + # works on Python 3 (bytes() requires an encoding) + hCd = ctypes.windll.kernel32.GlobalAlloc(GMEM_DDESHARE, len(bytes(text, 'ascii'))+1) + pchData = ctypes.windll.kernel32.GlobalLock(hCd) + try: + # works on Python 2 (bytes() only takes one argument) + ctypes.cdll.msvcrt.strcpy(ctypes.c_char_p(pchData), bytes(text)) + except TypeError: + # works on Python 3 (bytes() requires an encoding) + ctypes.cdll.msvcrt.strcpy(ctypes.c_char_p(pchData), bytes(text, 'ascii')) + ctypes.windll.kernel32.GlobalUnlock(hCd) + ctypes.windll.user32.SetClipboardData(1,hCd) + ctypes.windll.user32.CloseClipboard() + +def macSetClipboard(text): + outf = os.popen('pbcopy', 'w') + outf.write(text) + outf.close() + +def macGetClipboard(): + outf = os.popen('pbpaste', 'r') + content = outf.read() + outf.close() + return content + +def gtkGetClipboard(): + return gtk.Clipboard().wait_for_text() + +def gtkSetClipboard(text): + cb = gtk.Clipboard() + cb.set_text(text) + cb.store() + +def qtGetClipboard(): + return str(cb.text()) + +def qtSetClipboard(text): + cb.setText(text) + +def xclipSetClipboard(text): + outf = os.popen('xclip -selection c', 'w') + outf.write(text) + outf.close() + +def xclipGetClipboard(): + outf = os.popen('xclip -selection c -o', 'r') + content = outf.read() + outf.close() + return content + +def xselSetClipboard(text): + outf = os.popen('xsel -i -b', 'w') + outf.write(text) + outf.close() + +def xselGetClipboard(): + outf = os.popen('xsel -o -b', 'r') + content = outf.read() + outf.close() + return content + +if os.name == 'nt': + import ctypes + getcb = winGetClipboard + setcb = winSetClipboard +elif os.uname()[0].lower() == 'darwin' or os.name=='mac': + getcb = macGetClipboard + setcb = macSetClipboard +elif os.name == 'posix': + xselExists = False + try: + xselExists = (subprocess.check_output(['which', 'xsel']) != '') + except: + pass + if xselExists: + getcb = xselGetClipboard + setcb = xselSetClipboard + else: + xclipExists = False + try: + xclipExists = (subprocess.check_output(['which', 'xclip']) != '') + except: + pass + if xclipExists: + getcb = xclipGetClipboard + setcb = xclipSetClipboard + try: + import gtk + signal.signal(signal.SIGINT, signal.SIG_DFL) + getcb = gtkGetClipboard + setcb = gtkSetClipboard + except: + try: + import PyQt4.QtCore + import PyQt4.QtGui + app = QApplication([]) + cb = PyQt4.QtGui.QApplication.clipboard() + getcb = qtGetClipboard + setcb = qtSetClipboard + except: + raise Exception('Pyperclip requires the gtk or PyQt4 module installed, or the xclip command.') + +copy = setcb +paste = getcb \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/__init__.py new file mode 100644 index 0000000..361bdb9 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2003-2006 Gary Bishop. +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +import unicode_helper,logger,clipboard,lineeditor,modes +from rlmain import * +import rlmain +__all__ = [ 'parse_and_bind', + 'get_line_buffer', + 'insert_text', + 'clear_history', + 'read_init_file', + 'read_history_file', + 'write_history_file', + 'get_history_length', + 'set_history_length', + 'set_startup_hook', + 'set_pre_input_hook', + 'set_completer', + 'get_completer', + 'get_begidx', + 'get_endidx', + 'set_completer_delims', + 'get_completer_delims', + 'add_history', + 'GetOutputFile', + 'rl', + 'rlmain'] + +import release diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/clipboard/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/clipboard/__init__.py new file mode 100644 index 0000000..66a8419 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/clipboard/__init__.py @@ -0,0 +1,73 @@ +import sys +success=False +in_ironpython="IronPython" in sys.version +if in_ironpython: + try: + from ironpython_clipboard import GetClipboardText,SetClipboardText + success=True + except ImportError: + pass +else: + try: + from win32_clipboard import GetClipboardText,SetClipboardText + success=True + except ImportError: + raise + + +def send_data(lists): + SetClipboardText(make_tab(lists)) + + +def set_clipboard_text(toclipboard): + SetClipboardText(str(toclipboard)) + +def make_tab(lists): + if hasattr(lists,"tolist"): + lists=lists.tolist() + ut=[] + for rad in lists: + if type(rad) in [list,tuple]: + ut.append("\t".join(["%s"%x for x in rad])) + else: + ut.append("%s"%rad) + return "\n".join(ut) + +def make_list_of_list(txt): + def make_num(x): + try: + return int(x) + except ValueError: + try: + return float(x) + except ValueError: + try: + return complex(x) + except ValueError: + return x + return x + ut=[] + flag=False + for rad in [x for x in txt.split("\r\n") if x!=""]: + raden=[make_num(x) for x in rad.split("\t")] + if str in map(type,raden): + flag=True + ut.append(raden) + return ut,flag + + +def get_clipboard_text_and_convert(paste_list=False): + """Get txt from clipboard. if paste_list==True the convert tab separated + data to list of lists. Enclose list of list in array() if all elements are + numeric""" + txt=GetClipboardText() + if txt: + if paste_list and "\t" in txt: + array,flag=make_list_of_list(txt) + if flag: + txt=repr(array) + else: + txt="array(%s)"%repr(array) + txt="".join([c for c in txt if c not in " \t\r\n"]) + return txt + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/clipboard/win32_clipboard.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/clipboard/win32_clipboard.py new file mode 100644 index 0000000..b075f6f --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/clipboard/win32_clipboard.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2003-2006 Jack Trainor. +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +################################### +# +# Based on recipe posted to ctypes-users +# see archive +# http://aspn.activestate.com/ASPN/Mail/Message/ctypes-users/1771866 +# +# + +################################################################################### +# +# The Python win32clipboard lib functions work well enough ... except that they +# can only cut and paste items from within one application, not across +# applications or processes. +# +# I've written a number of Python text filters I like to run on the contents of +# the clipboard so I need to call the Windows clipboard API with global memory +# for my filters to work properly. +# +# Here's some sample code solving this problem using ctypes. +# +# This is my first work with ctypes. It's powerful stuff, but passing arguments +# in and out of functions is tricky. More sample code would have been helpful, +# hence this contribution. +# +################################################################################### + +from ctypes import * +from pyreadline.keysyms.winconstants import CF_TEXT, GHND +from pyreadline.unicode_helper import ensure_unicode,ensure_str + +OpenClipboard = windll.user32.OpenClipboard +EmptyClipboard = windll.user32.EmptyClipboard +GetClipboardData = windll.user32.GetClipboardData +GetClipboardFormatName = windll.user32.GetClipboardFormatNameA +SetClipboardData = windll.user32.SetClipboardData +EnumClipboardFormats = windll.user32.EnumClipboardFormats +CloseClipboard = windll.user32.CloseClipboard +OpenClipboard.argtypes=[c_int] +EnumClipboardFormats.argtypes=[c_int] +CloseClipboard.argtypes=[] +GetClipboardFormatName.argtypes=[c_uint,c_char_p,c_int] +GetClipboardData.argtypes=[c_int] +SetClipboardData.argtypes=[c_int,c_int] + +GlobalLock = windll.kernel32.GlobalLock +GlobalAlloc = windll.kernel32.GlobalAlloc +GlobalUnlock = windll.kernel32.GlobalUnlock +GlobalLock.argtypes=[c_int] +GlobalUnlock.argtypes=[c_int] +memcpy = cdll.msvcrt.memcpy + +def enum(): + OpenClipboard(0) + q=EnumClipboardFormats(0) + while q: + print q, + q=EnumClipboardFormats(q) + CloseClipboard() + +def getformatname(format): + buffer = c_buffer(" "*100) + bufferSize = sizeof(buffer) + OpenClipboard(0) + GetClipboardFormatName(format,buffer,bufferSize) + CloseClipboard() + return buffer.value + +def GetClipboardText(): + text = "" + if OpenClipboard(0): + hClipMem = GetClipboardData(CF_TEXT) + if hClipMem: + GlobalLock.restype = c_char_p + text = GlobalLock(hClipMem) + GlobalUnlock(hClipMem) + CloseClipboard() + return ensure_unicode(text) + +def SetClipboardText(text): + buffer = c_buffer(ensure_str(text)) + bufferSize = sizeof(buffer) + hGlobalMem = GlobalAlloc(c_int(GHND), c_int(bufferSize)) + GlobalLock.restype = c_void_p + lpGlobalMem = GlobalLock(c_int(hGlobalMem)) + memcpy(lpGlobalMem, addressof(buffer), c_int(bufferSize)) + GlobalUnlock(c_int(hGlobalMem)) + if OpenClipboard(0): + EmptyClipboard() + SetClipboardData(c_int(CF_TEXT), c_int(hGlobalMem)) + CloseClipboard() + +if __name__ == '__main__': + txt=GetClipboardText() # display last text clipped + print txt diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/configuration/pyreadlineconfig.ini b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/configuration/pyreadlineconfig.ini new file mode 100644 index 0000000..2c007a1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/configuration/pyreadlineconfig.ini @@ -0,0 +1,86 @@ +#Bind keys for exit (keys only work on empty lines +debug_output("off") #"on" saves log info to./pyreadline_debug_log.txt + #"on_nologfile" only enables print warning messages +bind_exit_key("Control-d") +bind_exit_key("Control-z") + +#Commands for moving +bind_key("Home", "beginning_of_line") +bind_key("End", "end_of_line") +bind_key("Left", "backward_char") +bind_key("Control-b", "backward_char") +bind_key("Right", "forward_char") +bind_key("Control-f", "forward_char") +bind_key("Alt-f", "forward_word") +bind_key("Alt-b", "backward_word") +bind_key("Clear", "clear_screen") +bind_key("Control-l", "clear_screen") +bind_key("Control-a", "beginning_of_line") +bind_key("Control-e", "end_of_line") +#bind_key("Control-l", "redraw_current_line") + +#Commands for Manipulating the History +bind_key("Return", "accept_line") +bind_key("Control-p", "previous_history") +bind_key("Control-n", "next_history") +bind_key("Up", "history_search_backward") +bind_key("Down", "history_search_forward") +bind_key("Alt-<", "beginning_of_history") +bind_key("Alt->", "end_of_history") +bind_key("Control-r", "reverse_search_history") +bind_key("Control-s", "forward_search_history") +bind_key("Alt-p", "non_incremental_reverse_search_history") +bind_key("Alt-n", "non_incremental_forward_search_history") + +bind_key("Control-z", "undo") +bind_key("Control-_", "undo") + +#Commands for Changing Text +bind_key("Delete", "delete_char") +bind_key("Control-d", "delete_char") +bind_key("BackSpace", "backward_delete_char") +#bind_key("Control-Shift-v", "quoted_insert") +bind_key("Control-space", "self_insert") +bind_key("Control-BackSpace", "backward_delete_word") + +#Killing and Yanking +bind_key("Control-k", "kill_line") +bind_key("Control-shift-k", "kill_whole_line") +bind_key("Escape", "kill_whole_line") +bind_key("Meta-d", "kill_word") +bind_key("Control-w", "unix_word_rubout") +#bind_key("Control-Delete", "forward_kill_word") + +#Copy paste +bind_key("Shift-Right", "forward_char_extend_selection") +bind_key("Shift-Left", "backward_char_extend_selection") +bind_key("Shift-Control-Right", "forward_word_extend_selection") +bind_key("Shift-Control-Left", "backward_word_extend_selection") +bind_key("Control-m", "set_mark") + +bind_key("Control-Shift-x", "copy_selection_to_clipboard") +bind_key("Control-Shift-c", "copy_selection_to_clipboard") #Needs allow_ctrl_c(True) below to be uncommented +bind_key("Control-q", "copy_region_to_clipboard") +bind_key('Control-Shift-v', "paste_mulitline_code") +bind_key("Control-x", "cut_selection_to_clipboard") + +bind_key("Control-Shift-v", "paste") +bind_key("Control-y", "yank") +bind_key("Alt-v", "ipython_paste") + +#Unbinding keys: +#un_bind_key("Home") + +#Other +bell_style("none") #modes: none, audible, visible(not implemented) +show_all_if_ambiguous("on") +mark_directories("on") +completer_delims(" \t\n\"\\'`@$><=;|&{(?") +debug_output("off") +#allow_ctrl_c(True) #(Allows use of ctrl-c as copy key, still propagate keyboardinterrupt when not waiting for input) + +history_filename("~/.pythonhistory") +history_length(200) #value of -1 means no limit + +#set_mode("vi") #will cause following bind_keys to bind to vi mode as well as activate vi mode +#ctrl_c_tap_time_interval(0.3) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/configuration/startup.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/configuration/startup.py new file mode 100644 index 0000000..42493b0 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/configuration/startup.py @@ -0,0 +1,22 @@ +# -*- coding: UTF-8 -*- +# Example snippet to use in a PYTHONSTARTUP file +try: + import pyreadline.rlmain + #pyreadline.rlmain.config_path=r"c:\xxx\pyreadlineconfig.ini" + import readline,atexit + import pyreadline.unicode_helper + # + # + #Normally the codepage for pyreadline is set to be sys.stdout.encoding + #if you need to change this uncomment the following line + #pyreadline.unicode_helper.pyreadline_codepage="utf8" +except ImportError: + print "Module readline not available." +else: + #import tab completion functionality + import rlcompleter + #activate tab completion + readline.parse_and_bind("tab: complete") + readline.read_history_file() + atexit.register(readline.write_history_file) + del readline,rlcompleter,atexit diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/__init__.py new file mode 100644 index 0000000..f5ea1ab --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/__init__.py @@ -0,0 +1,21 @@ +import glob,sys + +success=False +in_ironpython="IronPython" in sys.version + +if in_ironpython: + try: + from ironpython_console import * + success=True + except ImportError: + raise +else: + try: + from console import * + success=True + except ImportError: + pass + + +if not success: + raise ImportError("Could not find a console implementation for your platform") diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/ansi.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/ansi.py new file mode 100644 index 0000000..16697cb --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/ansi.py @@ -0,0 +1,181 @@ +# -*- coding: ISO-8859-1 -*- +import re,sys,os + +terminal_escape = re.compile('(\001?\033\\[[0-9;]*m\002?)') +escape_parts = re.compile('\001?\033\\[([0-9;]*)m\002?') + + +class AnsiState(object): + def __init__(self,bold=False,inverse=False,color="white",background="black",backgroundbold=False): + self.bold=bold + self.inverse=inverse + self.color=color + self.background=background + self.backgroundbold=backgroundbold + + trtable={"black":0,"red":4,"green":2,"yellow":6,"blue":1,"magenta":5,"cyan":3,"white":7} + revtable=dict(zip(trtable.values(),trtable.keys())) + def get_winattr(self): + attr=0 + if self.bold: + attr|=0x0008 + if self.backgroundbold: + attr|=0x0080 + if self.inverse: + attr|=0x4000 + attr|=self.trtable[self.color] + attr|=(self.trtable[self.background]<<4) + return attr + + def set_winattr(self,attr): + self.bold=bool(attr&0x0008) + self.backgroundbold=bool(attr&0x0080) + self.inverse=bool(attr&0x4000) + self.color=self.revtable[attr&0x0007] + self.background=self.revtable[(attr&0x0070)>>4] + + winattr=property(get_winattr,set_winattr) + def __repr__(self): + return 'AnsiState(bold=%s,inverse=%s,color=%9s,background=%9s,backgroundbold=%s)# 0x%x'%(self.bold, + self.inverse, + '"%s"'%self.color, + '"%s"'%self.background, + self.backgroundbold, + self.winattr) + + def copy(self): + x=AnsiState() + x.bold=self.bold + x.inverse=self.inverse + x.color=self.color + x.background=self.background + x.backgroundbold=self.backgroundbold + return x +defaultstate=AnsiState(False,False,"white") + +trtable={0:"black",1:"red",2:"green",3:"yellow",4:"blue",5:"magenta",6:"cyan",7:"white"} + +class AnsiWriter(object): + def __init__(self,default=defaultstate): + if isinstance(defaultstate,AnsiState): + self.defaultstate=default + else: + self.defaultstate=AnsiState() + self.defaultstate.winattr=defaultstate + + + def write_color(self,text, attr=None): + '''write text at current cursor position and interpret color escapes. + + return the number of characters written. + ''' + if isinstance(attr,AnsiState): + defaultstate=attr + elif attr is None: #use attribute form initial console + attr = self.defaultstate.copy() + else: + defaultstate=AnsiState() + defaultstate.winattr=attr + attr=defaultstate + chunks = terminal_escape.split(text) + n = 0 # count the characters we actually write, omitting the escapes + res=[] + for chunk in chunks: + m = escape_parts.match(chunk) + if m: + parts=m.group(1).split(";") + if len(parts)==1 and parts[0]=="0": + attr = self.defaultstate.copy() + continue + for part in parts: + if part == "0": # No text attribute + attr = self.defaultstate.copy() + attr.bold=False + elif part == "7": # switch on reverse + attr.inverse=True + elif part == "1": # switch on bold (i.e. intensify foreground color) + attr.bold=True + elif len(part) == 2 and "30" <= part <= "37": # set foreground color + attr.color = trtable[int(part)-30] + elif len(part) == 2 and "40" <= part <= "47": # set background color + attr.color = trtable[int(part)-40] + continue + n += len(chunk) + if True: + res.append((attr.copy(),chunk)) + return n,res + + def parse_color(self,text, attr=None): + n,res=self.write_color(text,attr) + return n,[attr.winattr for attr,text in res] + +def write_color(text,attr=None): + a=AnsiWriter(defaultstate) + return a.write_color(text,attr) + +def write_color_old( text, attr=None): + '''write text at current cursor position and interpret color escapes. + + return the number of characters written. + ''' + res=[] + chunks = terminal_escape.split(text) + n = 0 # count the characters we actually write, omitting the escapes + if attr is None:#use attribute from initial console + attr = 15 + for chunk in chunks: + m = escape_parts.match(chunk) + if m: + for part in m.group(1).split(";"): + if part == "0": # No text attribute + attr = 0 + elif part == "7": # switch on reverse + attr |= 0x4000 + if part == "1": # switch on bold (i.e. intensify foreground color) + attr |= 0x08 + elif len(part) == 2 and "30" <= part <= "37": # set foreground color + part = int(part)-30 + # we have to mirror bits + attr = (attr & ~0x07) | ((part & 0x1) << 2) | (part & 0x2) | ((part & 0x4) >> 2) + elif len(part) == 2 and "40" <= part <= "47": # set background color + part = int(part)-40 + # we have to mirror bits + attr = (attr & ~0x70) | ((part & 0x1) << 6) | ((part & 0x2) << 4) | ((part & 0x4) << 2) + # ignore blink, underline and anything we don't understand + continue + n += len(chunk) + if chunk: + res.append(("0x%x"%attr,chunk)) + return res + + +#trtable={0:"black",1:"red",2:"green",3:"yellow",4:"blue",5:"magenta",6:"cyan",7:"white"} + +if __name__=="__main__": + import pprint + pprint=pprint.pprint + + s="\033[0;31mred\033[0;32mgreen\033[0;33myellow\033[0;34mblue\033[0;35mmagenta\033[0;36mcyan\033[0;37mwhite\033[0m" + pprint (write_color(s)) + pprint (write_color_old(s)) + s="\033[1;31mred\033[1;32mgreen\033[1;33myellow\033[1;34mblue\033[1;35mmagenta\033[1;36mcyan\033[1;37mwhite\033[0m" + pprint (write_color(s)) + pprint (write_color_old(s)) + + s="\033[0;7;31mred\033[0;7;32mgreen\033[0;7;33myellow\033[0;7;34mblue\033[0;7;35mmagenta\033[0;7;36mcyan\033[0;7;37mwhite\033[0m" + pprint (write_color(s)) + pprint (write_color_old(s)) + s="\033[1;7;31mred\033[1;7;32mgreen\033[1;7;33myellow\033[1;7;34mblue\033[1;7;35mmagenta\033[1;7;36mcyan\033[1;7;37mwhite\033[0m" + pprint (write_color(s)) + pprint (write_color_old(s)) + + +if __name__=="__main__": + import console + + c=console.Console() + c.write_color("dhsjdhs") + c.write_color("\033[0;32mIn [\033[1;32m1\033[0;32m]:") + print + pprint (write_color("\033[0;32mIn [\033[1;32m1\033[0;32m]:")) + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/console.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/console.py new file mode 100644 index 0000000..921f064 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/console.py @@ -0,0 +1,749 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2003-2006 Gary Bishop. +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +'''Cursor control and color for the Windows console. + +This was modeled after the C extension of the same name by Fredrik Lundh. +''' + +# primitive debug printing that won't interfere with the screen + +import sys +import traceback +import re +from pyreadline.logger import log,log_sock +from pyreadline.unicode_helper import ensure_unicode,ensure_str +import pyreadline.unicode_helper as unicode_helper +try: + from ctypes import * + from _ctypes import call_function +except ImportError: + raise ImportError("You need ctypes to run this code") + +# my code +from pyreadline.keysyms import make_KeyPress +from pyreadline.console.ansi import AnsiState,AnsiWriter + +# some constants we need +STD_INPUT_HANDLE = -10 +STD_OUTPUT_HANDLE = -11 +ENABLE_WINDOW_INPUT = 0x0008 +ENABLE_MOUSE_INPUT = 0x0010 +ENABLE_PROCESSED_INPUT = 0x0001 +WHITE = 0x7 +BLACK = 0 +MENU_EVENT = 0x0008 +KEY_EVENT = 0x0001 +MOUSE_MOVED = 0x0001 +MOUSE_EVENT = 0x0002 +WINDOW_BUFFER_SIZE_EVENT = 0x0004 +FOCUS_EVENT = 0x0010 +MENU_EVENT = 0x0008 +VK_SHIFT = 0x10 +VK_CONTROL = 0x11 +VK_MENU = 0x12 +GENERIC_READ = int(0x80000000L) +GENERIC_WRITE = 0x40000000 + +# Windows structures we'll need later +class COORD(Structure): + _fields_ = [("X", c_short), + ("Y", c_short)] + +class SMALL_RECT(Structure): + _fields_ = [("Left", c_short), + ("Top", c_short), + ("Right", c_short), + ("Bottom", c_short)] + +class CONSOLE_SCREEN_BUFFER_INFO(Structure): + _fields_ = [("dwSize", COORD), + ("dwCursorPosition", COORD), + ("wAttributes", c_short), + ("srWindow", SMALL_RECT), + ("dwMaximumWindowSize", COORD)] + +class CHAR_UNION(Union): + _fields_ = [("UnicodeChar", c_wchar), + ("AsciiChar", c_char)] + +class CHAR_INFO(Structure): + _fields_ = [("Char", CHAR_UNION), + ("Attributes", c_short)] + +class KEY_EVENT_RECORD(Structure): + _fields_ = [("bKeyDown", c_byte), + ("pad2", c_byte), + ('pad1', c_short), + ("wRepeatCount", c_short), + ("wVirtualKeyCode", c_short), + ("wVirtualScanCode", c_short), + ("uChar", CHAR_UNION), + ("dwControlKeyState", c_int)] + +class MOUSE_EVENT_RECORD(Structure): + _fields_ = [("dwMousePosition", COORD), + ("dwButtonState", c_int), + ("dwControlKeyState", c_int), + ("dwEventFlags", c_int)] + +class WINDOW_BUFFER_SIZE_RECORD(Structure): + _fields_ = [("dwSize", COORD)] + +class MENU_EVENT_RECORD(Structure): + _fields_ = [("dwCommandId", c_uint)] + +class FOCUS_EVENT_RECORD(Structure): + _fields_ = [("bSetFocus", c_byte)] + +class INPUT_UNION(Union): + _fields_ = [("KeyEvent", KEY_EVENT_RECORD), + ("MouseEvent", MOUSE_EVENT_RECORD), + ("WindowBufferSizeEvent", WINDOW_BUFFER_SIZE_RECORD), + ("MenuEvent", MENU_EVENT_RECORD), + ("FocusEvent", FOCUS_EVENT_RECORD)] + +class INPUT_RECORD(Structure): + _fields_ = [("EventType", c_short), + ("Event", INPUT_UNION)] + +class CONSOLE_CURSOR_INFO(Structure): + _fields_ = [("dwSize", c_int), + ("bVisible", c_byte)] + + +# I didn't want to have to individually import these so I made a list, they are +# added to the Console class later in this file. + +funcs = [ + 'AllocConsole', + 'CreateConsoleScreenBuffer', + 'FillConsoleOutputAttribute', + 'FillConsoleOutputCharacterW', + 'FreeConsole', + 'GetConsoleCursorInfo', + 'GetConsoleMode', + 'GetConsoleScreenBufferInfo', + 'GetConsoleTitleW', + 'GetProcAddress', + 'GetStdHandle', + 'PeekConsoleInputW', + 'ReadConsoleInputW', + 'ScrollConsoleScreenBufferW', + 'SetConsoleActiveScreenBuffer', + 'SetConsoleCursorInfo', + 'SetConsoleCursorPosition', + 'SetConsoleMode', + 'SetConsoleScreenBufferSize', + 'SetConsoleTextAttribute', + 'SetConsoleTitleW', + 'SetConsoleWindowInfo', + 'WriteConsoleW', + 'WriteConsoleOutputCharacterW', + ] + +# I don't want events for these keys, they are just a bother for my application +key_modifiers = { VK_SHIFT:1, + VK_CONTROL:1, + VK_MENU:1, # alt key + 0x5b:1, # windows key + } + +class Console(object): + '''Console driver for Windows. + + ''' + + def __init__(self, newbuffer=0): + '''Initialize the Console object. + + newbuffer=1 will allocate a new buffer so the old content will be restored + on exit. + ''' + #Do I need the following line? It causes a console to be created whenever + #readline is imported into a pythonw application which seems wrong. Things + #seem to work without it... + #self.AllocConsole() + + if newbuffer: + self.hout = self.CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, + 0, None, 1, None) + self.SetConsoleActiveScreenBuffer(self.hout) + else: + self.hout = self.GetStdHandle(STD_OUTPUT_HANDLE) + + self.hin = self.GetStdHandle(STD_INPUT_HANDLE) + self.inmode = c_int(0) + self.GetConsoleMode(self.hin, byref(self.inmode)) + self.SetConsoleMode(self.hin, 0xf) + info = CONSOLE_SCREEN_BUFFER_INFO() + self.GetConsoleScreenBufferInfo(self.hout, byref(info)) + self.attr = info.wAttributes + self.saveattr = info.wAttributes # remember the initial colors + + self.defaultstate=AnsiState() + self.defaultstate.winattr=info.wAttributes + self.ansiwriter=AnsiWriter(self.defaultstate) +# self.ansiwriter.defaultstate.bold=False + + background = self.attr & 0xf0 + for escape in self.escape_to_color: + if self.escape_to_color[escape] is not None: + self.escape_to_color[escape] |= background + log('initial attr=%x' % self.attr) + self.softspace = 0 # this is for using it as a file-like object + self.serial = 0 + + self.pythondll = CDLL('python%s%s' % (sys.version[0], sys.version[2])) + self.inputHookPtr = c_int.from_address(addressof(self.pythondll.PyOS_InputHook)).value + setattr(Console, 'PyMem_Malloc', self.pythondll.PyMem_Malloc) + + def __del__(self): + '''Cleanup the console when finished.''' + # I don't think this ever gets called + self.SetConsoleTextAttribute(self.hout, self.saveattr) + self.SetConsoleMode(self.hin, self.inmode) + self.FreeConsole() + + def _get_top_bot(self): + info = CONSOLE_SCREEN_BUFFER_INFO() + self.GetConsoleScreenBufferInfo(self.hout, byref(info)) + rect = info.srWindow + top = rect.Top + bot = rect.Bottom + return top,bot + + def fixcoord(self, x, y): + '''Return a long with x and y packed inside, also handle negative x and y.''' + if x < 0 or y < 0: + info = CONSOLE_SCREEN_BUFFER_INFO() + self.GetConsoleScreenBufferInfo(self.hout, byref(info)) + if x < 0: + x = info.srWindow.Right - x + y = info.srWindow.Bottom + y + + # this is a hack! ctypes won't pass structures but COORD is just like a + # long, so this works. + return c_int(y << 16 | x) + + def pos(self, x=None, y=None): + '''Move or query the window cursor.''' + if x is None: + info = CONSOLE_SCREEN_BUFFER_INFO() + self.GetConsoleScreenBufferInfo(self.hout, byref(info)) + return (info.dwCursorPosition.X, info.dwCursorPosition.Y) + else: + return self.SetConsoleCursorPosition(self.hout, self.fixcoord(x, y)) + + def home(self): + '''Move to home.''' + self.pos(0,0) + +# Map ANSI color escape sequences into Windows Console Attributes + + terminal_escape = re.compile('(\001?\033\\[[0-9;]+m\002?)') + escape_parts = re.compile('\001?\033\\[([0-9;]+)m\002?') + escape_to_color = { '0;30': 0x0, #black + '0;31': 0x4, #red + '0;32': 0x2, #green + '0;33': 0x4+0x2, #brown? + '0;34': 0x1, #blue + '0;35': 0x1+0x4, #purple + '0;36': 0x2+0x4, #cyan + '0;37': 0x1+0x2+0x4, #grey + '1;30': 0x1+0x2+0x4, #dark gray + '1;31': 0x4+0x8, #red + '1;32': 0x2+0x8, #light green + '1;33': 0x4+0x2+0x8, #yellow + '1;34': 0x1+0x8, #light blue + '1;35': 0x1+0x4+0x8, #light purple + '1;36': 0x1+0x2+0x8, #light cyan + '1;37': 0x1+0x2+0x4+0x8, #white + '0': None, + } + + # This pattern should match all characters that change the cursor position differently + # than a normal character. + motion_char_re = re.compile('([\n\r\t\010\007])') + + def write_scrolling(self, text, attr=None): + '''write text at current cursor position while watching for scrolling. + + If the window scrolls because you are at the bottom of the screen + buffer, all positions that you are storing will be shifted by the + scroll amount. For example, I remember the cursor position of the + prompt so that I can redraw the line but if the window scrolls, + the remembered position is off. + + This variant of write tries to keep track of the cursor position + so that it will know when the screen buffer is scrolled. It + returns the number of lines that the buffer scrolled. + + ''' + x, y = self.pos() + w, h = self.size() + scroll = 0 # the result + # split the string into ordinary characters and funny characters + chunks = self.motion_char_re.split(text) + for chunk in chunks: + log('C:'+chunk) + n = self.write_color(chunk, attr) + if len(chunk) == 1: # the funny characters will be alone + if chunk[0] == '\n': # newline + x = 0 + y += 1 + elif chunk[0] == '\r': # carriage return + x = 0 + elif chunk[0] == '\t': # tab + x = 8*(int(x/8)+1) + if x > w: # newline + x -= w + y += 1 + elif chunk[0] == '\007': # bell + pass + elif chunk[0] == '\010': + x -= 1 + if x < 0: + y -= 1 # backed up 1 line + else: # ordinary character + x += 1 + if x == w: # wrap + x = 0 + y += 1 + if y == h: # scroll + scroll += 1 + y = h - 1 + else: # chunk of ordinary characters + x += n + l = int(x / w) # lines we advanced + x = x % w # new x value + y += l + if y >= h: # scroll + scroll += y - h + 1 + y = h - 1 + return scroll + + def write_color(self, text, attr=None): + '''write text at current cursor position and interpret color escapes. + + return the number of characters written. + ''' + log('write_color("%s", %s)' % (text, attr)) + chunks = self.terminal_escape.split(text) + log('chunks=%s' % repr(chunks)) + junk = c_int(0) + n = 0 # count the characters we actually write, omitting the escapes + for chunk in chunks: + m = self.escape_parts.match(chunk) + if m: + attr = self.escape_to_color[m.group(1)] + continue + n += len(chunk) + log('attr=%s' % attr) + if attr is None: + attr = self.attr + self.SetConsoleTextAttribute(self.hout, attr) + #self.WriteConsoleW(self.hout, ensure_str(chunk), len(chunk), byref(junk), None) + return n + + def write_color(self, text, attr=None): + text = ensure_unicode(text) + n,res= self.ansiwriter.write_color(text,attr) + junk = c_int(0) + for attr,chunk in res: + log(unicode(attr)) + log(unicode(chunk)) + self.SetConsoleTextAttribute(self.hout, attr.winattr) + self.WriteConsoleW(self.hout, chunk, len(chunk), byref(junk), None) + return n + + + def write_plain(self, text, attr=None): + '''write text at current cursor position.''' + log('write("%s", %s)' %(text,attr)) + if attr is None: + attr = self.attr + n = c_int(0) + self.SetConsoleTextAttribute(self.hout, attr) + self.WriteConsoleW(self.hout, ensure_unicode(chunk), len(chunk), byref(junk), None) + return len(text) + + # make this class look like a file object + def write(self, text): + log('write("%s")' % text) + return self.write_color(text) + + #write = write_scrolling + + def isatty(self): + return True + + def flush(self): + pass + + def page(self, attr=None, fill=' '): + '''Fill the entire screen.''' + if attr is None: + attr = self.attr + if len(fill) != 1: + raise ValueError + info = CONSOLE_SCREEN_BUFFER_INFO() + self.GetConsoleScreenBufferInfo(self.hout, byref(info)) + if info.dwCursorPosition.X != 0 or info.dwCursorPosition.Y != 0: + self.SetConsoleCursorPosition(self.hout, self.fixcoord(0, 0)) + + w = info.dwSize.X + n = c_int(0) + for y in range(info.dwSize.Y): + self.FillConsoleOutputAttribute(self.hout, attr, w, self.fixcoord(0, y), byref(n)) + self.FillConsoleOutputCharacterW(self.hout, ord(fill[0]), w, self.fixcoord(0, y), byref(n)) + + self.attr = attr + + def text(self, x, y, text, attr=None): + '''Write text at the given position.''' + if attr is None: + attr = self.attr + + pos = self.fixcoord(x, y) + n = c_int(0) + self.WriteConsoleOutputCharacterW(self.hout, text, len(text), pos, byref(n)) + self.FillConsoleOutputAttribute(self.hout, attr, n, pos, byref(n)) + + def clear_to_end_of_window(self): + top,bot=self._get_top_bot() + pos=self.pos() + w,h=self.size() + self.rectangle( (pos[0],pos[1],w,pos[1]+1)) + if pos[1] maxbot: + bot = maxbot + top = bot - h + + nrect = SMALL_RECT() + nrect.Top = top + nrect.Bottom = bot + nrect.Left = rect.Left + nrect.Right = rect.Right + log('sn: top=%d bot=%d' % (top,bot)) + r=self.SetConsoleWindowInfo(self.hout, True, byref(nrect)) + log('r=%d' % r) + + def get(self): + '''Get next event from queue.''' + inputHookFunc = c_int.from_address(self.inputHookPtr).value + + Cevent = INPUT_RECORD() + count = c_int(0) + while 1: + if inputHookFunc: + call_function(inputHookFunc, ()) + status = self.ReadConsoleInputW(self.hin, byref(Cevent), 1, byref(count)) + if status and count.value == 1: + e = event(self, Cevent) + log_sock(ensure_unicode(e.keyinfo),"keypress") + return e + + def getkeypress(self): + '''Return next key press event from the queue, ignoring others.''' + while 1: + e = self.get() + if e.type == 'KeyPress' and e.keycode not in key_modifiers: + log(e) + if e.keyinfo.keyname == 'next': + self.scroll_window(12) + elif e.keyinfo.keyname == 'prior': + self.scroll_window(-12) + else: + return e + elif e.type == 'KeyRelease' and e.keyinfo==(True, False, False, 83): + log("getKeypress:%s,%s,%s"%(e.keyinfo,e.keycode,e.type)) + return e + + def getchar(self): + '''Get next character from queue.''' + + Cevent = INPUT_RECORD() + count = c_int(0) + while 1: + status = self.ReadConsoleInputW(self.hin, byref(Cevent), 1, byref(count)) + if (status and count.value==1 and Cevent.EventType == 1 and + Cevent.Event.KeyEvent.bKeyDown): + sym = keysym(Cevent.Event.KeyEvent.wVirtualKeyCode) + if len(sym) == 0: + sym = Cevent.Event.KeyEvent.uChar.AsciiChar + return sym + + def peek(self): + '''Check event queue.''' + Cevent = INPUT_RECORD() + count = c_int(0) + status = self.PeekConsoleInputW(self.hin, byref(Cevent), 1, byref(count)) + if status and count == 1: + return event(self, Cevent) + + def title(self, txt=None): + '''Set/get title.''' + if txt: + self.SetConsoleTitleW(txt) + else: + buffer = create_unicode_buffer(200) + n = self.GetConsoleTitleW(buffer, 200) + if n > 0: + return buffer.value[:n] + + def size(self, width=None, height=None): + '''Set/get window size.''' + info = CONSOLE_SCREEN_BUFFER_INFO() + status = self.GetConsoleScreenBufferInfo(self.hout, byref(info)) + if not status: + return None + if width is not None and height is not None: + wmin = info.srWindow.Right - info.srWindow.Left + 1 + hmin = info.srWindow.Bottom - info.srWindow.Top + 1 + #print wmin, hmin + width = max(width, wmin) + height = max(height, hmin) + #print width, height + self.SetConsoleScreenBufferSize(self.hout, self.fixcoord(width, height)) + else: + return (info.dwSize.X, info.dwSize.Y) + + def cursor(self, visible=None, size=None): + '''Set cursor on or off.''' + info = CONSOLE_CURSOR_INFO() + if self.GetConsoleCursorInfo(self.hout, byref(info)): + if visible is not None: + info.bVisible = visible + if size is not None: + info.dwSize = size + self.SetConsoleCursorInfo(self.hout, byref(info)) + + def bell(self): + self.write('\007') + + def next_serial(self): + '''Get next event serial number.''' + self.serial += 1 + return self.serial + +# add the functions from the dll to the class +for func in funcs: + setattr(Console, func, getattr(windll.kernel32, func)) +windll.kernel32.SetConsoleTitleW.argtypes=[c_wchar_p] +windll.kernel32.GetConsoleTitleW.argtypes=[c_wchar_p,c_short] + +from event import Event + +VkKeyScan = windll.user32.VkKeyScanA + + +class event(Event): + '''Represent events from the console.''' + def __init__(self, console, input): + '''Initialize an event from the Windows input structure.''' + self.type = '??' + self.serial = console.next_serial() + self.width = 0 + self.height = 0 + self.x = 0 + self.y = 0 + self.char = '' + self.keycode = 0 + self.keysym = '??' + self.keyinfo = None # a tuple with (control, meta, shift, keycode) for dispatch + self.width = None + + if input.EventType == KEY_EVENT: + if input.Event.KeyEvent.bKeyDown: + self.type = "KeyPress" + else: + self.type = "KeyRelease" + self.char = input.Event.KeyEvent.uChar.UnicodeChar + self.keycode = input.Event.KeyEvent.wVirtualKeyCode + self.state = input.Event.KeyEvent.dwControlKeyState + self.keyinfo=make_KeyPress(self.char,self.state,self.keycode) + + elif input.EventType == MOUSE_EVENT: + if input.Event.MouseEvent.dwEventFlags & MOUSE_MOVED: + self.type = "Motion" + else: + self.type = "Button" + self.x = input.Event.MouseEvent.dwMousePosition.X + self.y = input.Event.MouseEvent.dwMousePosition.Y + self.state = input.Event.MouseEvent.dwButtonState + elif input.EventType == WINDOW_BUFFER_SIZE_EVENT: + self.type = "Configure" + self.width = input.Event.WindowBufferSizeEvent.dwSize.X + self.height = input.Event.WindowBufferSizeEvent.dwSize.Y + elif input.EventType == FOCUS_EVENT: + if input.Event.FocusEvent.bSetFocus: + self.type = "FocusIn" + else: + self.type = "FocusOut" + elif input.EventType == MENU_EVENT: + self.type = "Menu" + self.state = input.Event.MenuEvent.dwCommandId + +def getconsole(buffer=1): + """Get a console handle. + + If buffer is non-zero, a new console buffer is allocated and + installed. Otherwise, this returns a handle to the current + console buffer""" + + c = Console(buffer) + + return c + +# The following code uses ctypes to allow a Python callable to +# substitute for GNU readline within the Python interpreter. Calling +# raw_input or other functions that do input, inside your callable +# might be a bad idea, then again, it might work. + +# The Python callable can raise EOFError or KeyboardInterrupt and +# these will be translated into the appropriate outputs from readline +# so that they will then be translated back! + +# If the Python callable raises any other exception, a traceback will +# be printed and readline will appear to return an empty line. + +# I use ctypes to create a C-callable from a Python wrapper that +# handles the exceptions and gets the result into the right form. + +# the type for our C-callable wrapper +HOOKFUNC22 = CFUNCTYPE(c_char_p, c_char_p) +HOOKFUNC23 = CFUNCTYPE(c_char_p, c_void_p, c_void_p, c_char_p) + +readline_hook = None # the python hook goes here +readline_ref = None # this holds a reference to the c-callable to keep it alive + +def hook_wrapper_23(stdin, stdout, prompt): + '''Wrap a Python readline so it behaves like GNU readline.''' + try: + # call the Python hook + res = ensure_str(readline_hook(prompt)) + # make sure it returned the right sort of thing + if res and not isinstance(res, str): + raise TypeError, 'readline must return a string.' + except KeyboardInterrupt: + # GNU readline returns 0 on keyboard interrupt + return 0 + except EOFError: + # It returns an empty string on EOF + res = '' + except: + print >>sys.stderr, 'Readline internal error' + traceback.print_exc() + res = '\n' + # we have to make a copy because the caller expects to free the result + n = len(res) + p = Console.PyMem_Malloc(n+1) + cdll.msvcrt.strncpy(p, res, n+1) + return p + +def hook_wrapper(prompt): + '''Wrap a Python readline so it behaves like GNU readline.''' + try: + # call the Python hook + res = ensure_str(readline_hook(prompt)) + # make sure it returned the right sort of thing + if res and not isinstance(res, str): + raise TypeError, 'readline must return a string.' + except KeyboardInterrupt: + # GNU readline returns 0 on keyboard interrupt + return 0 + except EOFError: + # It returns an empty string on EOF + res = '' + except: + print >>sys.stderr, 'Readline internal error' + traceback.print_exc() + res = '\n' + # we have to make a copy because the caller expects to free the result + p = cdll.msvcrt._strdup(res) + return p + +def install_readline(hook): + '''Set up things for the interpreter to call our function like GNU readline.''' + global readline_hook, readline_ref + # save the hook so the wrapper can call it + readline_hook = hook + # get the address of PyOS_ReadlineFunctionPointer so we can update it + PyOS_RFP = c_int.from_address(Console.GetProcAddress(sys.dllhandle, + "PyOS_ReadlineFunctionPointer")) + # save a reference to the generated C-callable so it doesn't go away + if sys.version < '2.3': + readline_ref = HOOKFUNC22(hook_wrapper) + else: + readline_ref = HOOKFUNC23(hook_wrapper_23) + # get the address of the function + func_start = c_int.from_address(addressof(readline_ref)).value + # write the function address into PyOS_ReadlineFunctionPointer + PyOS_RFP.value = func_start + +if __name__ == '__main__': + import time, sys + + + def p(char): + return chr(VkKeyScan(ord(char)) & 0xff) + + c = Console(0) + sys.stdout = c + sys.stderr = c + c.page() + print p("d"),p("D") + c.pos(5, 10) + c.write('hi there') + print 'some printed output' + for i in range(10): + q=c.getkeypress() + print q + del c diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/console_attributes.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/console_attributes.py new file mode 100644 index 0000000..9262331 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/console_attributes.py @@ -0,0 +1,16 @@ + +FOREGROUND_BLUE = 0x0001 +FOREGROUND_GREEN = 0x0002 +FOREGROUND_RED = 0x0004 +FOREGROUND_INTENSITY = 0x0008 +BACKGROUND_BLUE = 0x0010 +BACKGROUND_GREEN = 0x0020 +BACKGROUND_RED = 0x0040 +BACKGROUND_INTENSITY = 0x0080 +COMMON_LVB_LEADING_BYTE = 0x0100 +COMMON_LVB_TRAILING_BYTE = 0x0200 +COMMON_LVB_GRID_HORIZONTAL= 0x0400 +COMMON_LVB_GRID_LVERTICAL = 0x0800 +COMMON_LVB_GRID_RVERTICAL = 0x1000 +COMMON_LVB_REVERSE_VIDEO = 0x2000 +COMMON_LVB_UNDERSCORE = 0x4000 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/consolebase.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/consolebase.py new file mode 100644 index 0000000..79afd24 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/consolebase.py @@ -0,0 +1,52 @@ +class baseconsole: + def __init__(self): + pass + + def bell(self): + raise NotImplementedError + + def pos(self, x=None, y=None): + '''Move or query the window cursor.''' + raise NotImplementedError + + def size(self): + raise NotImplementedError + + def rectangle(self, rect, attr=None, fill=' '): + '''Fill Rectangle.''' + raise NotImplementedError + + def write_scrolling(self, text, attr=None): + '''write text at current cursor position while watching for scrolling. + + If the window scrolls because you are at the bottom of the screen + buffer, all positions that you are storing will be shifted by the + scroll amount. For example, I remember the cursor position of the + prompt so that I can redraw the line but if the window scrolls, + the remembered position is off. + + This variant of write tries to keep track of the cursor position + so that it will know when the screen buffer is scrolled. It + returns the number of lines that the buffer scrolled. + + ''' + raise NotImplementedError + + def getkeypress(self): + '''Return next key press event from the queue, ignoring others.''' + raise NotImplementedError + + def write(self, text): + raise NotImplementedError + + def page(self, attr=None, fill=' '): + '''Fill the entire screen.''' + raise NotImplementedError + + def isatty(self): + return True + + def flush(self): + pass + + \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/event.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/event.py new file mode 100644 index 0000000..bb7f014 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/console/event.py @@ -0,0 +1,28 @@ +class Event(object): + '''Represent events from the console.''' + def __init__(self, console, input): + pass + def __repr__(self): + '''Display an event for debugging.''' + if self.type in ['KeyPress', 'KeyRelease']: + chr=self.char + if ord(chr) +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +'''Cursor control and color for the .NET console. +''' + +# +# Ironpython requires a patch to work do: +# +# In file PythonCommandLine.cs patch line: +# class PythonCommandLine +# { + +# to: +# public class PythonCommandLine +# { +# +# +# +# primitive debug printing that won't interfere with the screen + +import clr,sys +clr.AddReferenceToFileAndPath(sys.executable) +import IronPythonConsole + +import sys +import re +import os + +import System + +from event import Event +from pyreadline.logger import log,log_sock + +#print "Codepage",System.Console.InputEncoding.CodePage +from pyreadline.keysyms import make_keysym, make_keyinfo,make_KeyPress,make_KeyPress_from_keydescr +from pyreadline.console.ansi import AnsiState +color=System.ConsoleColor + +ansicolor={"0;30": color.Black, + "0;31": color.DarkRed, + "0;32": color.DarkGreen, + "0;33": color.DarkYellow, + "0;34": color.DarkBlue, + "0;35": color.DarkMagenta, + "0;36": color.DarkCyan, + "0;37": color.DarkGray, + "1;30": color.Gray, + "1;31": color.Red, + "1;32": color.Green, + "1;33": color.Yellow, + "1;34": color.Blue, + "1;35": color.Magenta, + "1;36": color.Cyan, + "1;37": color.White + } + +winattr={"black":0,"darkgray":0+8, + "darkred":4,"red":4+8, + "darkgreen":2,"green":2+8, + "darkyellow":6,"yellow":6+8, + "darkblue":1,"blue":1+8, + "darkmagenta":5, "magenta":5+8, + "darkcyan":3,"cyan":3+8, + "gray":7,"white":7+8} + +class Console(object): + '''Console driver for Windows. + + ''' + + def __init__(self, newbuffer=0): + '''Initialize the Console object. + + newbuffer=1 will allocate a new buffer so the old content will be restored + on exit. + ''' + self.serial=0 + self.attr = System.Console.ForegroundColor + self.saveattr = winattr[str(System.Console.ForegroundColor).lower()] + self.savebg=System.Console.BackgroundColor + log('initial attr=%s' % self.attr) + log_sock("%s"%self.saveattr) + + def _get(self): + top=System.Console.WindowTop + log_sock("WindowTop:%s"%top,"console") + return top + def _set(self,value): + top=System.Console.WindowTop + log_sock("Set WindowTop:old:%s,new:%s"%(top,value),"console") + WindowTop=property(_get,_set) + del _get,_set + + def __del__(self): + '''Cleanup the console when finished.''' + # I don't think this ever gets called + pass + + def pos(self, x=None, y=None): + '''Move or query the window cursor.''' + if x is not None: + System.Console.CursorLeft=x + else: + x=System.Console.CursorLeft + if y is not None: + System.Console.CursorTop=y + else: + y=System.Console.CursorTop + return x,y + + def home(self): + '''Move to home.''' + self.pos(0,0) + +# Map ANSI color escape sequences into Windows Console Attributes + + terminal_escape = re.compile('(\001?\033\\[[0-9;]*m\002?)') + escape_parts = re.compile('\001?\033\\[([0-9;]*)m\002?') + + # This pattern should match all characters that change the cursor position differently + # than a normal character. + motion_char_re = re.compile('([\n\r\t\010\007])') + + def write_scrolling(self, text, attr=None): + '''write text at current cursor position while watching for scrolling. + + If the window scrolls because you are at the bottom of the screen + buffer, all positions that you are storing will be shifted by the + scroll amount. For example, I remember the cursor position of the + prompt so that I can redraw the line but if the window scrolls, + the remembered position is off. + + This variant of write tries to keep track of the cursor position + so that it will know when the screen buffer is scrolled. It + returns the number of lines that the buffer scrolled. + + ''' + x, y = self.pos() + w, h = self.size() + scroll = 0 # the result + + # split the string into ordinary characters and funny characters + chunks = self.motion_char_re.split(text) + for chunk in chunks: + log('C:'+chunk) + n = self.write_color(chunk, attr) + if len(chunk) == 1: # the funny characters will be alone + if chunk[0] == '\n': # newline + x = 0 + y += 1 + elif chunk[0] == '\r': # carriage return + x = 0 + elif chunk[0] == '\t': # tab + x = 8*(int(x/8)+1) + if x > w: # newline + x -= w + y += 1 + elif chunk[0] == '\007': # bell + pass + elif chunk[0] == '\010': + x -= 1 + if x < 0: + y -= 1 # backed up 1 line + else: # ordinary character + x += 1 + if x == w: # wrap + x = 0 + y += 1 + if y == h: # scroll + scroll += 1 + y = h - 1 + else: # chunk of ordinary characters + x += n + l = int(x / w) # lines we advanced + x = x % w # new x value + y += l + if y >= h: # scroll + scroll += y - h + 1 + y = h - 1 + return scroll + + trtable={0:color.Black,4:color.DarkRed,2:color.DarkGreen,6:color.DarkYellow, + 1:color.DarkBlue,5:color.DarkMagenta,3:color.DarkCyan,7:color.Gray, + 8:color.DarkGray,4+8:color.Red,2+8:color.Green,6+8:color.Yellow, + 1+8:color.Blue,5+8:color.Magenta,3+8:color.Cyan,7+8:color.White} + + def write_color(self, text, attr=None): + '''write text at current cursor position and interpret color escapes. + + return the number of characters written. + ''' + log('write_color("%s", %s)' % (text, attr)) + chunks = self.terminal_escape.split(text) + log('chunks=%s' % repr(chunks)) + bg=self.savebg + n = 0 # count the characters we actually write, omitting the escapes + if attr is None:#use attribute from initial console + attr = self.attr + try: + fg=self.trtable[(0x000f&attr)] + bg=self.trtable[(0x00f0&attr)>>4] + except TypeError: + fg=attr + + for chunk in chunks: + m = self.escape_parts.match(chunk) + if m: + log(m.group(1)) + attr=ansicolor.get(m.group(1),self.attr) + n += len(chunk) + System.Console.ForegroundColor=fg + System.Console.BackgroundColor=bg + #self.WriteConsoleA(self.hout, chunk, len(chunk), byref(junk), None) + System.Console.Write(chunk) + return n + + def write_plain(self, text, attr=None): + '''write text at current cursor position.''' + log('write("%s", %s)' %(text,attr)) + if attr is None: + attr = self.attr + n = c_int(0) + self.SetConsoleTextAttribute(self.hout, attr) + self.WriteConsoleA(self.hout, text, len(text), byref(n), None) + return len(text) + + if os.environ.has_key("EMACS"): + def write_color(self, text, attr=None): + junk = c_int(0) + self.WriteFile(self.hout, text, len(text), byref(junk), None) + return len(text) + write_plain = write_color + + # make this class look like a file object + def write(self, text): + log('write("%s")' % text) + return self.write_color(text) + + #write = write_scrolling + + def isatty(self): + return True + + def flush(self): + pass + + def page(self, attr=None, fill=' '): + '''Fill the entire screen.''' + System.Console.Clear() + + def text(self, x, y, text, attr=None): + '''Write text at the given position.''' + self.pos(x,y) + self.write_color(text,attr) + + def clear_to_end_of_window(self): + oldtop=self.WindowTop + lastline=self.WindowTop+System.Console.WindowHeight + pos=self.pos() + w,h=self.size() + length=w-pos[0]+min((lastline-pos[1]-1),5)*w-1 + self.write_color(length*" ") + self.pos(*pos) + self.WindowTop=oldtop + + def rectangle(self, rect, attr=None, fill=' '): + '''Fill Rectangle.''' + pass + oldtop=self.WindowTop + oldpos=self.pos() + #raise NotImplementedError + x0, y0, x1, y1 = rect + if attr is None: + attr = self.attr + if fill: + rowfill=fill[:1]*abs(x1-x0) + else: + rowfill=' '*abs(x1-x0) + for y in range(y0, y1): + System.Console.SetCursorPosition(x0,y) + self.write_color(rowfill,attr) + self.pos(*oldpos) + + def scroll(self, rect, dx, dy, attr=None, fill=' '): + '''Scroll a rectangle.''' + pass + raise NotImplementedError + + def scroll_window(self, lines): + '''Scroll the window by the indicated number of lines.''' + top=self.WindowTop+lines + if top<0: + top=0 + if top+System.Console.WindowHeight>System.Console.BufferHeight: + top=System.Console.BufferHeight + self.WindowTop=top + + def getkeypress(self): + '''Return next key press event from the queue, ignoring others.''' + ck=System.ConsoleKey + while 1: + e = System.Console.ReadKey(True) + if e.Key == System.ConsoleKey.PageDown: #PageDown + self.scroll_window(12) + elif e.Key == System.ConsoleKey.PageUp:#PageUp + self.scroll_window(-12) + elif str(e.KeyChar)=="\000":#Drop deadkeys + log_sock("Deadkey: %s"%e) + return event(self,e) + pass + else: + return event(self,e) + + def title(self, txt=None): + '''Set/get title.''' + if txt: + System.Console.Title=txt + else: + return System.Console.Title + + def size(self, width=None, height=None): + '''Set/get window size.''' + sc=System.Console + + + if width is not None and height is not None: + sc.BufferWidth,sc.BufferHeight=width,height + else: + return sc.BufferWidth,sc.BufferHeight + + if width is not None and height is not None: + sc.WindowWidth,sc.WindowHeight=width,height + else: + return sc.WindowWidth-1,sc.WindowHeight-1 + + def cursor(self, visible=True, size=None): + '''Set cursor on or off.''' + System.Console.CursorVisible=visible + + def bell(self): + System.Console.Beep() + + def next_serial(self): + '''Get next event serial number.''' + self.serial += 1 + return self.serial + +class event(Event): + '''Represent events from the console.''' + def __init__(self, console, input): + '''Initialize an event from the Windows input structure.''' + self.type = '??' + self.serial = console.next_serial() + self.width = 0 + self.height = 0 + self.x = 0 + self.y = 0 + self.char = str(input.KeyChar) + self.keycode = input.Key + self.state = input.Modifiers + log_sock("%s,%s,%s"%(input.Modifiers,input.Key,input.KeyChar),"console") + self.type="KeyRelease" + self.keysym = make_keysym(self.keycode) + self.keyinfo = make_KeyPress(self.char, self.state, self.keycode) + +def make_event_from_keydescr(keydescr): + def input(): + return 1 + input.KeyChar="a" + input.Key=System.ConsoleKey.A + input.Modifiers=System.ConsoleModifiers.Shift + input.next_serial=input + e=event(input,input) + del input.next_serial + keyinfo=make_KeyPress_from_keydescr(keydescr) + e.keyinfo=keyinfo + return e + +CTRL_C_EVENT=make_event_from_keydescr("Control-c") + +def install_readline(hook): + def hook_wrap(): + try: + res=hook() + except KeyboardInterrupt,x: #this exception does not seem to be caught + res="" + except EOFError: + return None + if res[-1:]=="\n": + return res[:-1] + else: + return res + class IronPythonWrapper(IronPythonConsole.IConsole): + def ReadLine(self,autoIndentSize): + return hook_wrap() + def Write(self,text, style): + System.Console.Write(text) + def WriteLine(self,text, style): + System.Console.WriteLine(text) + IronPythonConsole.PythonCommandLine.MyConsole = IronPythonWrapper() + + + +if __name__ == '__main__': + import time, sys + c = Console(0) + sys.stdout = c + sys.stderr = c + c.page() + c.pos(5, 10) + c.write('hi there') + c.title("Testing console") +# c.bell() + print + print "size",c.size() + print ' some printed output' + for i in range(10): + e=c.getkeypress() + print e.Key,chr(e.KeyChar),ord(e.KeyChar),e.Modifiers + del c + + System.Console.Clear() diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/error.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/error.py new file mode 100644 index 0000000..be2c24e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/error.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + + +class ReadlineError(Exception): + pass + +class GetSetError(ReadlineError): + pass diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/get_doc.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/get_doc.py new file mode 100644 index 0000000..111761f --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/get_doc.py @@ -0,0 +1,18 @@ +import sys,textwrap + +rlmain=sys.modules["pyreadline.rlmain"] +rl=rlmain.rl + +def get_doc(rl): + methods=[(x,getattr(rl,x)) for x in dir(rl) if callable(getattr(rl,x))] + return [ (x,m.__doc__ )for x,m in methods if m.__doc__] + + +def get_rest(rl): + q=get_doc(rl) + out=[] + for funcname,doc in q: + out.append(funcname) + out.append("\n".join(textwrap.wrap(doc,80,initial_indent=" "))) + out.append("") + return out \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/keysyms/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/keysyms/__init__.py new file mode 100644 index 0000000..bbb82b1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/keysyms/__init__.py @@ -0,0 +1,20 @@ +import sys + +success=False +in_ironpython="IronPython" in sys.version + +if in_ironpython: + try: + from ironpython_keysyms import * + success=True + except ImportError,x: + raise +else: + try: + from keysyms import * + success=True + except ImportError,x: + pass + +if not success: + raise ImportError("Could not import keysym for local pythonversion",x) \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/keysyms/common.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/keysyms/common.py new file mode 100644 index 0000000..a40caf4 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/keysyms/common.py @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2003-2006 Gary Bishop. +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +# table for translating virtual keys to X windows key symbols + +try: + set +except NameError: + from sets import Set as set + +from pyreadline.unicode_helper import ensure_unicode + +validkey =set(['cancel', 'backspace', 'tab', 'clear', + 'return', 'shift_l', 'control_l', 'alt_l', + 'pause', 'caps_lock', 'escape', 'space', + 'prior', 'next', 'end', 'home', + 'left', 'up', 'right', 'down', + 'select', 'print', 'execute', 'snapshot', + 'insert', 'delete', 'help', 'f1', + 'f2', 'f3', 'f4', 'f5', + 'f6', 'f7', 'f8', 'f9', + 'f10', 'f11', 'f12', 'f13', + 'f14', 'f15', 'f16', 'f17', + 'f18', 'f19', 'f20', 'f21', + 'f22', 'f23', 'f24', 'num_lock', + 'scroll_lock', 'vk_apps', 'vk_processkey','vk_attn', + 'vk_crsel', 'vk_exsel', 'vk_ereof', 'vk_play', + 'vk_zoom', 'vk_noname', 'vk_pa1', 'vk_oem_clear', + 'numpad0', 'numpad1', 'numpad2', 'numpad3', + 'numpad4', 'numpad5', 'numpad6', 'numpad7', + 'numpad8', 'numpad9', 'divide', 'multiply', + 'add', 'subtract', 'vk_decimal']) + +escape_sequence_to_special_key={"\\e[a":"up","\\e[b":"down","del":"delete"} + +class KeyPress(object): + def __init__(self,char="",shift=False,control=False,meta=False,keyname=""): + if control or meta or shift: + char=char.upper() + self.info=dict(char=char, + shift=shift, + control=control, + meta=meta, + keyname=keyname) + + def create(name): + def get(self): + return self.info[name] + def set(self,value): + self.info[name]=value + return property(get,set) + char=create("char") + shift=create("shift") + control=create("control") + meta=create("meta") + keyname=create("keyname") + + def __repr__(self): + return u"(%s,%s,%s,%s)"%tuple(map(ensure_unicode,self.tuple())) + + def tuple(self): + if self.keyname: + return (self.control,self.meta,self.shift,self.keyname) + else: + if self.control or self.meta or self.shift: + return (self.control,self.meta,self.shift,self.char.upper()) + else: + return (self.control,self.meta,self.shift,self.char) + +def make_KeyPress_from_keydescr(keydescr): + keyinfo=KeyPress() + if len(keydescr)>2 and keydescr[:1]=='"' and keydescr[-1:]=='"': + keydescr=keydescr[1:-1] + + while 1: + lkeyname = keydescr.lower() + if lkeyname.startswith('control-'): + keyinfo.control = True + keydescr = keydescr[8:] + elif lkeyname.startswith('ctrl-'): + keyinfo.control = True + keydescr = keydescr[5:] + elif keydescr.lower().startswith('\\c-'): + keyinfo.control = True + keydescr = keydescr[3:] + elif keydescr.lower().startswith('\\m-'): + keyinfo.meta = True + keydescr = keydescr[3:] + elif keydescr in escape_sequence_to_special_key: + keydescr = escape_sequence_to_special_key[keydescr] + elif lkeyname.startswith('meta-'): + keyinfo.meta = True + keydescr = keydescr[5:] + elif lkeyname.startswith('alt-'): + keyinfo.meta = True + keydescr = keydescr[4:] + elif lkeyname.startswith('shift-'): + keyinfo.shift = True + keydescr = keydescr[6:] + else: + if len(keydescr) > 1: + if keydescr.strip().lower() in validkey: + keyinfo.keyname=keydescr.strip().lower() + keyinfo.char="" + else: + raise IndexError("Not a valid key: '%s'"%keydescr) + else: + keyinfo.char=keydescr + return keyinfo + +if __name__=="__main__": + import startup + \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/keysyms/keysyms.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/keysyms/keysyms.py new file mode 100644 index 0000000..6d62de7 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/keysyms/keysyms.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2003-2006 Gary Bishop. +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +import winconstants as c32 +from ctypes import windll +import ctypes +# table for translating virtual keys to X windows key symbols + +from common import validkey,KeyPress,make_KeyPress_from_keydescr + +code2sym_map = {c32.VK_CANCEL: 'cancel', + c32.VK_BACK: 'backspace', + c32.VK_TAB: 'tab', + c32.VK_CLEAR: 'clear', + c32.VK_RETURN: 'return', + c32.VK_SHIFT: 'shift_l', + c32.VK_CONTROL: 'control_l', + c32.VK_MENU: 'alt_l', + c32.VK_PAUSE: 'pause', + c32.VK_CAPITAL: 'caps_lock', + c32.VK_ESCAPE: 'escape', + c32.VK_SPACE: 'space', + c32.VK_PRIOR: 'prior', + c32.VK_NEXT: 'next', + c32.VK_END: 'end', + c32.VK_HOME: 'home', + c32.VK_LEFT: 'left', + c32.VK_UP: 'up', + c32.VK_RIGHT: 'right', + c32.VK_DOWN: 'down', + c32.VK_SELECT: 'select', + c32.VK_PRINT: 'print', + c32.VK_EXECUTE: 'execute', + c32.VK_SNAPSHOT: 'snapshot', + c32.VK_INSERT: 'insert', + c32.VK_DELETE: 'delete', + c32.VK_HELP: 'help', + c32.VK_F1: 'f1', + c32.VK_F2: 'f2', + c32.VK_F3: 'f3', + c32.VK_F4: 'f4', + c32.VK_F5: 'f5', + c32.VK_F6: 'f6', + c32.VK_F7: 'f7', + c32.VK_F8: 'f8', + c32.VK_F9: 'f9', + c32.VK_F10: 'f10', + c32.VK_F11: 'f11', + c32.VK_F12: 'f12', + c32.VK_F13: 'f13', + c32.VK_F14: 'f14', + c32.VK_F15: 'f15', + c32.VK_F16: 'f16', + c32.VK_F17: 'f17', + c32.VK_F18: 'f18', + c32.VK_F19: 'f19', + c32.VK_F20: 'f20', + c32.VK_F21: 'f21', + c32.VK_F22: 'f22', + c32.VK_F23: 'f23', + c32.VK_F24: 'f24', + c32.VK_NUMLOCK: 'num_lock,', + c32.VK_SCROLL: 'scroll_lock', + c32.VK_APPS: 'vk_apps', + c32.VK_PROCESSKEY: 'vk_processkey', + c32.VK_ATTN: 'vk_attn', + c32.VK_CRSEL: 'vk_crsel', + c32.VK_EXSEL: 'vk_exsel', + c32.VK_EREOF: 'vk_ereof', + c32.VK_PLAY: 'vk_play', + c32.VK_ZOOM: 'vk_zoom', + c32.VK_NONAME: 'vk_noname', + c32.VK_PA1: 'vk_pa1', + c32.VK_OEM_CLEAR :'vk_oem_clear', + c32.VK_NUMPAD0: 'numpad0', + c32.VK_NUMPAD1: 'numpad1', + c32.VK_NUMPAD2: 'numpad2', + c32.VK_NUMPAD3: 'numpad3', + c32.VK_NUMPAD4: 'numpad4', + c32.VK_NUMPAD5: 'numpad5', + c32.VK_NUMPAD6: 'numpad6', + c32.VK_NUMPAD7: 'numpad7', + c32.VK_NUMPAD8: 'numpad8', + c32.VK_NUMPAD9: 'numpad9', + c32.VK_DIVIDE: 'divide', + c32.VK_MULTIPLY: 'multiply', + c32.VK_ADD: 'add', + c32.VK_SUBTRACT: 'subtract', + c32.VK_DECIMAL: 'vk_decimal' + } + +VkKeyScan = windll.user32.VkKeyScanA + +def char_to_keyinfo(char, control=False, meta=False, shift=False): + k=KeyPress() + vk = VkKeyScan(ord(char)) + if vk & 0xffff == 0xffff: + print 'VkKeyScan("%s") = %x' % (char, vk) + raise ValueError, 'bad key' + if vk & 0x100: + k.shift = True + if vk & 0x200: + k.control = True + if vk & 0x400: + k.meta = True + k.char=chr(vk & 0xff) + return k + +def make_KeyPress(char,state,keycode): + control = (state & (4+8)) != 0 + meta = (state & (1+2)) != 0 + shift = (state & 0x10) != 0 + if control and char !="\x00": + char = chr(VkKeyScan(ord(char)) & 0xff) + elif control: + char=chr(keycode) + try: + keyname=code2sym_map[keycode] + except KeyError: + keyname="" + return KeyPress(char,shift,control,meta,keyname) + +if __name__=="__main__": + import startup + \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/keysyms/winconstants.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/keysyms/winconstants.py new file mode 100644 index 0000000..5e0ed63 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/keysyms/winconstants.py @@ -0,0 +1,171 @@ +#This file contains constants that are normally found in win32all +#But included here to avoid the dependency + +VK_LBUTTON=1 +VK_RBUTTON=2 +VK_CANCEL=3 +VK_MBUTTON=4 +VK_XBUTTON1=5 +VK_XBUTTON2=6 +VK_BACK=8 +VK_TAB=9 +VK_CLEAR=12 +VK_RETURN=13 +VK_SHIFT=16 +VK_CONTROL=17 +VK_MENU=18 +VK_PAUSE=19 +VK_CAPITAL=20 +VK_KANA=0x15 +VK_HANGEUL=0x15 +VK_HANGUL=0x15 +VK_JUNJA=0x17 +VK_FINAL=0x18 +VK_HANJA=0x19 +VK_KANJI=0x19 +VK_ESCAPE=0x1B +VK_CONVERT=0x1C +VK_NONCONVERT=0x1D +VK_ACCEPT=0x1E +VK_MODECHANGE=0x1F +VK_SPACE=32 +VK_PRIOR=33 +VK_NEXT=34 +VK_END=35 +VK_HOME=36 +VK_LEFT=37 +VK_UP=38 +VK_RIGHT=39 +VK_DOWN=40 +VK_SELECT=41 +VK_PRINT=42 +VK_EXECUTE=43 +VK_SNAPSHOT=44 +VK_INSERT=45 +VK_DELETE=46 +VK_HELP=47 +VK_LWIN=0x5B +VK_RWIN=0x5C +VK_APPS=0x5D +VK_SLEEP=0x5F +VK_NUMPAD0=0x60 +VK_NUMPAD1=0x61 +VK_NUMPAD2=0x62 +VK_NUMPAD3=0x63 +VK_NUMPAD4=0x64 +VK_NUMPAD5=0x65 +VK_NUMPAD6=0x66 +VK_NUMPAD7=0x67 +VK_NUMPAD8=0x68 +VK_NUMPAD9=0x69 +VK_MULTIPLY=0x6A +VK_ADD=0x6B +VK_SEPARATOR=0x6C +VK_SUBTRACT=0x6D +VK_DECIMAL=0x6E +VK_DIVIDE=0x6F +VK_F1=0x70 +VK_F2=0x71 +VK_F3=0x72 +VK_F4=0x73 +VK_F5=0x74 +VK_F6=0x75 +VK_F7=0x76 +VK_F8=0x77 +VK_F9=0x78 +VK_F10=0x79 +VK_F11=0x7A +VK_F12=0x7B +VK_F13=0x7C +VK_F14=0x7D +VK_F15=0x7E +VK_F16=0x7F +VK_F17=0x80 +VK_F18=0x81 +VK_F19=0x82 +VK_F20=0x83 +VK_F21=0x84 +VK_F22=0x85 +VK_F23=0x86 +VK_F24=0x87 +VK_NUMLOCK=0x90 +VK_SCROLL=0x91 +VK_LSHIFT=0xA0 +VK_RSHIFT=0xA1 +VK_LCONTROL=0xA2 +VK_RCONTROL=0xA3 +VK_LMENU=0xA4 +VK_RMENU=0xA5 +VK_BROWSER_BACK=0xA6 +VK_BROWSER_FORWARD=0xA7 +VK_BROWSER_REFRESH=0xA8 +VK_BROWSER_STOP=0xA9 +VK_BROWSER_SEARCH=0xAA +VK_BROWSER_FAVORITES=0xAB +VK_BROWSER_HOME=0xAC +VK_VOLUME_MUTE=0xAD +VK_VOLUME_DOWN=0xAE +VK_VOLUME_UP=0xAF +VK_MEDIA_NEXT_TRACK=0xB0 +VK_MEDIA_PREV_TRACK=0xB1 +VK_MEDIA_STOP=0xB2 +VK_MEDIA_PLAY_PAUSE=0xB3 +VK_LAUNCH_MAIL=0xB4 +VK_LAUNCH_MEDIA_SELECT=0xB5 +VK_LAUNCH_APP1=0xB6 +VK_LAUNCH_APP2=0xB7 +VK_OEM_1=0xBA +VK_OEM_PLUS=0xBB +VK_OEM_COMMA=0xBC +VK_OEM_MINUS=0xBD +VK_OEM_PERIOD=0xBE +VK_OEM_2=0xBF +VK_OEM_3=0xC0 +VK_OEM_4=0xDB +VK_OEM_5=0xDC +VK_OEM_6=0xDD +VK_OEM_7=0xDE +VK_OEM_8=0xDF +VK_OEM_102=0xE2 +VK_PROCESSKEY=0xE5 +VK_PACKET=0xE7 +VK_ATTN=0xF6 +VK_CRSEL=0xF7 +VK_EXSEL=0xF8 +VK_EREOF=0xF9 +VK_PLAY=0xFA +VK_ZOOM=0xFB +VK_NONAME=0xFC +VK_PA1=0xFD +VK_OEM_CLEAR=0xFE + +CF_TEXT=1 +CF_BITMAP=2 +CF_METAFILEPICT=3 +CF_SYLK=4 +CF_DIF=5 +CF_TIFF=6 +CF_OEMTEXT=7 +CF_DIB=8 +CF_PALETTE=9 +CF_PENDATA=10 +CF_RIFF=11 +CF_WAVE=12 +CF_UNICODETEXT=13 +CF_ENHMETAFILE=14 +CF_HDROP=15 +CF_LOCALE=16 +CF_MAX=17 +CF_OWNERDISPLAY=128 +CF_DSPTEXT=129 +CF_DSPBITMAP=130 +CF_DSPMETAFILEPICT=131 +CF_DSPENHMETAFILE=142 +CF_PRIVATEFIRST=512 +CF_PRIVATELAST=767 +CF_GDIOBJFIRST=768 +CF_GDIOBJLAST=1023 + + +GPTR=64 +GHND=66 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/lineeditor/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/lineeditor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/lineeditor/history.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/lineeditor/history.py new file mode 100644 index 0000000..bd7ef8c --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/lineeditor/history.py @@ -0,0 +1,247 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +import re,operator,string,sys,os + +#import wordmatcher +#import pyreadline.clipboard as clipboard +from pyreadline.unicode_helper import ensure_unicode,ensure_str +if "pyreadline" in sys.modules: + pyreadline= sys.modules["pyreadline"] +else: + import pyreadline + +import lineobj + +import exceptions + +class EscapeHistory(exceptions.Exception): + pass + +from pyreadline.logger import log_sock + +_ignore_leading_spaces=False + +class LineHistory(object): + def __init__(self): + self.history=[] + self._history_length=100 + self._history_cursor=0 + self.history_filename=os.path.expanduser('~/.history') + self.lastcommand=None + self.query="" + + def get_history_length(self): + value=self._history_length + log_sock("get_history_length:%d"%value,"history") + return value + + def set_history_length(self,value): + log_sock("set_history_length: old:%d new:%d"%(self._history_length,value),"history") + self._history_length=value + + def get_history_cursor(self): + value=self._history_cursor + log_sock("get_history_cursor:%d"%value,"history") + return value + + def set_history_cursor(self,value): + log_sock("set_history_cursor: old:%d new:%d"%(self._history_cursor,value),"history") + self._history_cursor=value + + history_length=property(get_history_length,set_history_length) + history_cursor=property(get_history_cursor,set_history_cursor) + + def clear_history(self): + '''Clear readline history.''' + self.history[:] = [] + self.history_cursor = 0 + + def read_history_file(self, filename=None): + '''Load a readline history file.''' + if filename is None: + filename=self.history_filename + try: + for line in open(filename, 'r'): + self.add_history(lineobj.ReadLineTextBuffer(ensure_unicode(line.rstrip()))) + except IOError: + self.history = [] + self.history_cursor = 0 + + def write_history_file(self, filename=None): + '''Save a readline history file.''' + if filename is None: + filename=self.history_filename + fp = open(filename, 'wb') + for line in self.history[-self.history_length:]: + fp.write(ensure_str(line.get_line_text())) + fp.write('\n') + fp.close() + + + def add_history(self, line): + '''Append a line to the history buffer, as if it was the last line typed.''' + if not line.get_line_text(): + pass + elif len(self.history) > 0 and self.history[-1].get_line_text() == line.get_line_text(): + pass + else: + self.history.append(line) + self.history_cursor = len(self.history) + + def previous_history(self,current): # (C-p) + '''Move back through the history list, fetching the previous command. ''' + if self.history_cursor==len(self.history): + self.history.append(current.copy()) #do not use add_history since we do not want to increment cursor + + if self.history_cursor > 0: + self.history_cursor -= 1 + current.set_line(self.history[self.history_cursor].get_line_text()) + current.point=lineobj.EndOfLine + + def next_history(self,current): # (C-n) + '''Move forward through the history list, fetching the next command. ''' + if self.history_cursor < len(self.history)-1: + self.history_cursor += 1 + current.set_line(self.history[self.history_cursor].get_line_text()) + + def beginning_of_history(self): # (M-<) + '''Move to the first line in the history.''' + self.history_cursor = 0 + if len(self.history) > 0: + self.l_buffer = self.history[0] + + def end_of_history(self,current): # (M->) + '''Move to the end of the input history, i.e., the line currently + being entered.''' + self.history_cursor=len(self.history) + current.set_line(self.history[-1].get_line_text()) + + def reverse_search_history(self,searchfor,startpos=None): + if startpos is None: + startpos=self.history_cursor + if _ignore_leading_spaces: + res=[(idx,line.lstrip()) for idx,line in enumerate(self.history[startpos:0:-1]) if line.lstrip().startswith(searchfor.lstrip())] + else: + res=[(idx,line) for idx,line in enumerate(self.history[startpos:0:-1]) if line.startswith(searchfor)] + if res: + self.history_cursor-=res[0][0] + return res[0][1].get_line_text() + return "" + + def forward_search_history(self,searchfor,startpos=None): + if startpos is None: + startpos=self.history_cursor + if _ignore_leading_spaces: + res=[(idx,line.lstrip()) for idx,line in enumerate(self.history[startpos:]) if line.lstrip().startswith(searchfor.lstrip())] + else: + res=[(idx,line) for idx,line in enumerate(self.history[startpos:]) if line.startswith(searchfor)] + if res: + self.history_cursor+=res[0][0] + return res[0][1].get_line_text() + return "" + + def _non_i_search(self, direction, current): + c = pyreadline.rl.console + line = current.get_line_text() + query = '' + while 1: + c.pos(*pyreadline.rl.prompt_end_pos) + scroll = c.write_scrolling(":%s" % query) + pyreadline.rl._update_prompt_pos(scroll) + pyreadline.rl._clear_after() + + event = c.getkeypress() + + if event.keyinfo.keyname == 'backspace': + if len(query) > 0: + query = query[:-1] + else: + break + elif event.char in string.letters + string.digits + string.punctuation + ' ': + query += event.char + elif event.keyinfo.keyname == 'return': + break + else: + pyreadline.rl._bell() + res="" + if query: + if direction==-1: + res=self.reverse_search_history(query) + + else: + res=self.forward_search_history(query) + return lineobj.ReadLineTextBuffer(res,point=0) + + def non_incremental_reverse_search_history(self,current): # (M-p) + '''Search backward starting at the current line and moving up + through the history as necessary using a non-incremental search for + a string supplied by the user.''' + return self._non_i_search(-1,current) + + def non_incremental_forward_search_history(self,current): # (M-n) + '''Search forward starting at the current line and moving down + through the the history as necessary using a non-incremental search + for a string supplied by the user.''' + return self._non_i_search(1,current) + + def _search(self, direction, partial): + try: + if (self.lastcommand != self.history_search_forward and + self.lastcommand != self.history_search_backward): + self.query = ''.join(partial[0:partial.point].get_line_text()) + hcstart=max(self.history_cursor,0) + hc = self.history_cursor + direction + while (direction < 0 and hc >= 0) or (direction > 0 and hc < len(self.history)): + h = self.history[hc] + if not self.query: + self.history_cursor = hc + result=lineobj.ReadLineTextBuffer(h,point=len(h.get_line_text())) + return result + elif (h.get_line_text().startswith(self.query) and (h != partial.get_line_text())): + self.history_cursor = hc + result=lineobj.ReadLineTextBuffer(h,point=partial.point) + return result + hc += direction + else: + if len(self.history)==0: + pass + elif hc>=len(self.history) and not self.query: + self.history_cursor=len(self.history) + return lineobj.ReadLineTextBuffer("",point=0) + elif self.history[max(min(hcstart,len(self.history)-1),0)].get_line_text().startswith(self.query) and self.query: + return lineobj.ReadLineTextBuffer(self.history[max(min(hcstart,len(self.history)-1),0)],point=partial.point) + else: + return lineobj.ReadLineTextBuffer(partial,point=partial.point) + return lineobj.ReadLineTextBuffer(self.query,point=min(len(self.query),partial.point)) + except IndexError: + raise + + def history_search_forward(self,partial): # () + '''Search forward through the history for the string of characters + between the start of the current line and the point. This is a + non-incremental search. By default, this command is unbound.''' + q= self._search(1,partial) + return q + + def history_search_backward(self,partial): # () + '''Search backward through the history for the string of characters + between the start of the current line and the point. This is a + non-incremental search. By default, this command is unbound.''' + + q= self._search(-1,partial) + return q + +if __name__=="__main__": + q=LineHistory() + RL=lineobj.ReadLineTextBuffer + q.add_history(RL("aaaa")) + q.add_history(RL("aaba")) + q.add_history(RL("aaca")) + q.add_history(RL("akca")) + q.add_history(RL("bbb")) + q.add_history(RL("ako")) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/lineeditor/lineobj.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/lineeditor/lineobj.py new file mode 100644 index 0000000..fef6d24 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/lineeditor/lineobj.py @@ -0,0 +1,801 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +import re,operator,sys + +import wordmatcher +import pyreadline.clipboard as clipboard +from pyreadline.logger import log,log_sock +from pyreadline.unicode_helper import ensure_unicode + +kill_ring_to_clipboard=False #set to true to copy every addition to kill ring to clipboard + + +class NotAWordError(IndexError): + pass + + +def quote_char(c): + if ord(c)>0: + return c + +############## Line positioner ######################## + +class LinePositioner(object): + def __call__(self,line): + NotImplementedError("Base class !!!") + +class NextChar(LinePositioner): + def __call__(self,line): + if line.point0: + return line.point-1 + else: + return line.point +PrevChar=PrevChar() + +class NextWordStart(LinePositioner): + def __call__(self,line): + return line.next_start_segment(line.line_buffer,line.is_word_token)[line.point] +NextWordStart=NextWordStart() + +class NextWordEnd(LinePositioner): + def __call__(self,line): + return line.next_end_segment(line.line_buffer,line.is_word_token)[line.point] +NextWordEnd=NextWordEnd() + +class PrevWordStart(LinePositioner): + def __call__(self,line): + return line.prev_start_segment(line.line_buffer,line.is_word_token)[line.point] +PrevWordStart=PrevWordStart() + + +class WordStart(LinePositioner): + def __call__(self,line): + if line.is_word_token(line.get_line_text()[Point(line):Point(line)+1]): + if Point(line)>0 and line.is_word_token(line.get_line_text()[Point(line)-1:Point(line)]): + return PrevWordStart(line) + else: + return line.point + else: + raise NotAWordError("Point is not in a word") +WordStart=WordStart() + +class WordEnd(LinePositioner): + def __call__(self,line): + if line.is_word_token(line.get_line_text()[Point(line):Point(line)+1]): + if line.is_word_token(line.get_line_text()[Point(line)+1:Point(line)+2]): + return NextWordEnd(line) + else: + return line.point + else: + raise NotAWordError("Point is not in a word") +WordEnd=WordEnd() + +class PrevWordEnd(LinePositioner): + def __call__(self,line): + return line.prev_end_segment(line.line_buffer,line.is_word_token)[line.point] +PrevWordEnd=PrevWordEnd() + +class PrevSpace(LinePositioner): + def __call__(self,line): + point=line.point + if line[point-1:point].get_line_text()==" ": + while point>0 and line[point-1:point].get_line_text()==" ": + point-=1 + while point>0 and line[point-1:point].get_line_text()!=" ": + point-=1 + return point +PrevSpace=PrevSpace() + + +class StartOfLine(LinePositioner): + def __call__(self,line): + return 0 +StartOfLine=StartOfLine() + +class EndOfLine(LinePositioner): + def __call__(self,line): + return len(line.line_buffer) +EndOfLine=EndOfLine() + +class Point(LinePositioner): + def __call__(self,line): + return line.point +Point=Point() + +class Mark(LinePositioner): + def __call__(self,line): + return line.mark +Mark=Mark() + +all_positioners=[(value.__class__.__name__,value) for key,value in globals().items() if isinstance(value,LinePositioner)] +all_positioners.sort() + +############### LineSlice ################# + +class LineSlice(object): + def __call__(self,line): + NotImplementedError("Base class !!!") + + +class CurrentWord(LineSlice): + def __call__(self,line): + return slice(WordStart(line),WordEnd(line),None) +CurrentWord=CurrentWord() + +class NextWord(LineSlice): + def __call__(self,line): + work=TextLine(line) + work.point=NextWordStart + start=work.point + stop=NextWordEnd(work) + return slice(start,stop) +NextWord=NextWord() + +class PrevWord(LineSlice): + def __call__(self,line): + work=TextLine(line) + work.point=PrevWordEnd + stop=work.point + start=PrevWordStart(work) + return slice(start,stop) +PrevWord=PrevWord() + +class PointSlice(LineSlice): + def __call__(self,line): + return slice(Point(line),Point(line)+1,None) +PointSlice=PointSlice() + + +############### TextLine ###################### + +class TextLine(object): + def __init__(self,txtstr,point=None,mark=None): + self.line_buffer=[] + self._point=0 + self.mark=-1 + self.undo_stack=[] + self.overwrite=False + if isinstance(txtstr,TextLine): #copy + self.line_buffer=txtstr.line_buffer[:] + if point is None: + self.point=txtstr.point + else: + self.point=point + if mark is None: + self.mark=txtstr.mark + else: + self.mark=mark + else: + self._insert_text(txtstr) + if point is None: + self.point=0 + else: + self.point=point + if mark is None: + self.mark=-1 + else: + self.mark=mark + + self.is_word_token=wordmatcher.is_word_token + self.next_start_segment=wordmatcher.next_start_segment + self.next_end_segment=wordmatcher.next_end_segment + self.prev_start_segment=wordmatcher.prev_start_segment + self.prev_end_segment=wordmatcher.prev_end_segment + + def push_undo(self): + ltext = self.get_line_text() + if self.undo_stack and ltext == self.undo_stack[-1].get_line_text(): + self.undo_stack[-1].point = self.point + else: + self.undo_stack.append(self.copy()) + + def pop_undo(self): + if len(self.undo_stack) >= 2: + self.undo_stack.pop() + self.set_top_undo() + self.undo_stack.pop() + else: + self.reset_line() + self.undo_stack = [] + + def set_top_undo(self): + if self.undo_stack: + undo=self.undo_stack[-1] + self.line_buffer=undo.line_buffer + self.point=undo.point + self.mark=undo.mark + else: + pass + + def __repr__(self): + return 'TextLine("%s",point=%s,mark=%s)'%(self.line_buffer,self.point,self.mark) + + def copy(self): + return self.__class__(self) + + def set_point(self,value): + if isinstance(value,LinePositioner): + value=value(self) + assert (value <= len(self.line_buffer)) + if value>len(self.line_buffer): + value=len(self.line_buffer) + self._point=value + def get_point(self): + return self._point + point=property(get_point,set_point) + + + def visible_line_width(self,position=Point): + """Return the visible width of the text in line buffer up to position.""" + extra_char_width = len([ None for c in self[:position].line_buffer if 0x2013 <= ord(c) <= 0xFFFD]) + return len(self[:position].quoted_text())+self[:position].line_buffer.count("\t")*7 + extra_char_width + + def quoted_text(self): + quoted = [ quote_char(c) for c in self.line_buffer ] + self.line_char_width = [ len(c) for c in quoted ] + return u''.join(map(ensure_unicode,quoted)) + + def get_line_text(self): + buf=self.line_buffer + buf=map(ensure_unicode,buf) + return u''.join(buf) + + def set_line(self, text, cursor=None): + self.line_buffer = [ c for c in str(text) ] + if cursor is None: + self.point = len(self.line_buffer) + else: + self.point = cursor + + def reset_line(self): + self.line_buffer = [] + self.point = 0 + + def end_of_line(self): + self.point = len(self.line_buffer) + + def _insert_text(self, text): + if self.overwrite: + for c in text: + #if self.point: + self.line_buffer[self.point]= c + self.point += 1 + else: + for c in text: + self.line_buffer.insert(self.point, c) + self.point += 1 + + def __getitem__(self,key): + #Check if key is LineSlice, convert to regular slice + #and continue processing + if isinstance(key,LineSlice): + key=key(self) + if isinstance(key,slice): + if key.step is None: + pass + else: + raise Error + if key.start is None: + start=StartOfLine(self) + elif isinstance(key.start,LinePositioner): + start=key.start(self) + else: + start=key.start + if key.stop is None: + stop=EndOfLine(self) + elif isinstance(key.stop,LinePositioner): + stop=key.stop(self) + else: + stop=key.stop + return self.__class__(self.line_buffer[start:stop],point=0) + elif isinstance(key,LinePositioner): + return self.line_buffer[key(self)] + elif isinstance(key,tuple): + raise IndexError("Cannot use step in line buffer indexing") #Multiple slice not allowed + else: + # return TextLine(self.line_buffer[key]) + return self.line_buffer[key] + + def __delitem__(self,key): + point=self.point + if isinstance(key,LineSlice): + key=key(self) + if isinstance(key,slice): + start=key.start + stop=key.stop + if isinstance(start,LinePositioner): + start=start(self) + elif start is None: + start=0 + if isinstance(stop,LinePositioner): + stop=stop(self) + elif stop is None: + stop=EndOfLine(self) + elif isinstance(key,LinePositioner): + start=key(self) + stop=start+1 + else: + start=key + stop=key+1 + prev=self.line_buffer[:start] + rest=self.line_buffer[stop:] + self.line_buffer=prev+rest + if point>stop: + self.point=point-(stop-start) + elif point>=start and point <=stop: + self.point=start + + + def __setitem__(self,key,value): + if isinstance(key,LineSlice): + key=key(self) + if isinstance(key,slice): + start=key.start + stop=key.stop + elif isinstance(key,LinePositioner): + start=key(self) + stop=start+1 + else: + start=key + stop=key+1 + prev=self.line_buffer[:start] + value=self.__class__(value).line_buffer + rest=self.line_buffer[stop:] + out=prev+value+rest + if len(out)>=len(self): + self.point=len(self) + self.line_buffer=out + + def __len__(self): + return len(self.line_buffer) + + def upper(self): + self.line_buffer=[x.upper() for x in self.line_buffer] + return self + + def lower(self): + self.line_buffer=[x.lower() for x in self.line_buffer] + return self + + def capitalize(self): + self.set_line(self.get_line_text().capitalize(),self.point) + return self + + def startswith(self,txt): + return self.get_line_text().startswith(txt) + + def endswith(self,txt): + return self.get_line_text().endswith(txt) + + def __contains__(self,txt): + return txt in self.get_line_text() + + +lines=[TextLine("abc"), + TextLine("abc def"), + TextLine("abc def ghi"), + TextLine(" abc def "), + ] +l=lines[2] +l.point=5 + + + +class ReadLineTextBuffer(TextLine): + def __init__(self,txtstr,point=None,mark=None): + super(ReadLineTextBuffer,self).__init__(txtstr,point,mark) + self.enable_win32_clipboard=True + self.selection_mark=-1 + self.enable_selection=True + self.kill_ring=[] + + def __repr__(self): + return 'ReadLineTextBuffer("%s",point=%s,mark=%s,selection_mark=%s)'%(self.line_buffer,self.point,self.mark,self.selection_mark) + + + def insert_text(self,char): + self.delete_selection() + self.selection_mark=-1 + self._insert_text(char) + + def to_clipboard(self): + if self.enable_win32_clipboard: + clipboard.set_clipboard_text(self.get_line_text()) + +######### Movement + + def beginning_of_line(self): + self.selection_mark=-1 + self.point=StartOfLine + + def end_of_line(self): + self.selection_mark=-1 + self.point=EndOfLine + + def forward_char(self,argument=1): + if argument<0: + self.backward_char(-argument) + self.selection_mark=-1 + for x in range(argument): + self.point=NextChar + + def backward_char(self,argument=1): + if argument<0: + self.forward_char(-argument) + self.selection_mark=-1 + for x in range(argument): + self.point=PrevChar + + def forward_word(self,argument=1): + if argument<0: + self.backward_word(-argument) + self.selection_mark=-1 + for x in range(argument): + self.point=NextWordStart + + def backward_word(self,argument=1): + if argument<0: + self.forward_word(-argument) + self.selection_mark=-1 + for x in range(argument): + self.point=PrevWordStart + + def forward_word_end(self,argument=1): + if argument<0: + self.backward_word_end(-argument) + self.selection_mark=-1 + for x in range(argument): + self.point=NextWordEnd + + def backward_word_end(self,argument=1): + if argument<0: + self.forward_word_end(-argument) + self.selection_mark=-1 + for x in range(argument): + self.point=NextWordEnd + +######### Movement select + def beginning_of_line_extend_selection(self): + if self.enable_selection and self.selection_mark<0: + self.selection_mark=self.point + self.point=StartOfLine + + def end_of_line_extend_selection(self): + if self.enable_selection and self.selection_mark<0: + self.selection_mark=self.point + self.point=EndOfLine + + def forward_char_extend_selection(self,argument=1): + if argument<0: + self.backward_char_extend_selection(-argument) + if self.enable_selection and self.selection_mark<0: + self.selection_mark=self.point + for x in range(argument): + self.point=NextChar + + def backward_char_extend_selection(self,argument=1): + if argument<0: + self.forward_char_extend_selection(-argument) + if self.enable_selection and self.selection_mark<0: + self.selection_mark=self.point + for x in range(argument): + self.point=PrevChar + + def forward_word_extend_selection(self,argument=1): + if argument<0: + self.backward_word_extend_selection(-argument) + if self.enable_selection and self.selection_mark<0: + self.selection_mark=self.point + for x in range(argument): + self.point=NextWordStart + + def backward_word_extend_selection(self,argument=1): + if argument<0: + self.forward_word_extend_selection(-argument) + if self.enable_selection and self.selection_mark<0: + self.selection_mark=self.point + for x in range(argument): + self.point=PrevWordStart + + + def forward_word_end_extend_selection(self,argument=1): + if argument<0: + self.backward_word_end_extend_selection(-argument) + if self.enable_selection and self.selection_mark<0: + self.selection_mark=self.point + for x in range(argument): + self.point=NextWordEnd + + def backward_word_end_extend_selection(self,argument=1): + if argument<0: + self.forward_word_end_extend_selection(-argument) + if self.enable_selection and self.selection_mark<0: + self.selection_mark=self.point + for x in range(argument): + self.point=PrevWordEnd + + +######### delete + + def delete_selection(self): + if self.enable_selection and self.selection_mark>=0: + if self.selection_mark0: + self.backward_char() + self.delete_char() + + def forward_delete_word(self,argument=1): + if argument<0: + self.backward_delete_word(-argument) + if self.delete_selection(): + argument-=1 + for x in range(argument): + del self[Point:NextWordStart] + + def backward_delete_word(self,argument=1): + if argument<0: + self.forward_delete_word(-argument) + if self.delete_selection(): + argument-=1 + for x in range(argument): + del self[PrevWordStart:Point] + + def delete_current_word(self): + if not self.delete_selection(): + del self[CurrentWord] + self.selection_mark=-1 + + def delete_horizontal_space(self): + if self[Point] in " \t": + del self[PrevWordEnd:NextWordStart] + self.selection_mark=-1 +######### Case + + def upcase_word(self): + p=self.point + try: + self[CurrentWord]=self[CurrentWord].upper() + self.point=p + except NotAWordError: + pass + + def downcase_word(self): + p=self.point + try: + self[CurrentWord]=self[CurrentWord].lower() + self.point=p + except NotAWordError: + pass + + def capitalize_word(self): + p=self.point + try: + self[CurrentWord]=self[CurrentWord].capitalize() + self.point=p + except NotAWordError: + pass +########### Transpose + def transpose_chars(self): + p2=Point(self) + if p2==0: + return + elif p2==len(self): + p2=p2-1 + p1=p2-1 + self[p2],self[p1]=self[p1],self[p2] + self.point=p2+1 + + def transpose_words(self): + word1=TextLine(self) + word2=TextLine(self) + if self.point==len(self): + word2.point=PrevWordStart + word1.point=PrevWordStart(word2) + else: + word1.point=PrevWordStart + word2.point=NextWordStart + stop1=NextWordEnd(word1) + stop2=NextWordEnd(word2) + start1=word1.point + start2=word2.point + self[start2:stop2]=word1[Point:NextWordEnd] + self[start1:stop1]=word2[Point:NextWordEnd] + self.point=stop2 + + +############ Kill + + def kill_line(self): + #self[self.point:].to_clipboard() + self.add_to_kill_ring(self[self.point:]) + del self.line_buffer[self.point:] + + def kill_whole_line(self): + #self[:].to_clipboard() + self.add_to_kill_ring(self[:]) + del self[:] + + def backward_kill_line(self): + #self[StartOfLine:Point].to_clipboard() + del self[StartOfLine:Point] + + def unix_line_discard(self): + del self[StartOfLine:Point] + pass + + def kill_word(self): + """Kills to next word ending""" + #self[Point:NextWordEnd].to_clipboard() + del self[Point:NextWordEnd] + + def backward_kill_word(self): + """Kills to next word ending""" + #self[PrevWordStart:Point].to_clipboard() + if not self.delete_selection(): + del self[PrevWordStart:Point] + self.selection_mark=-1 + + def forward_kill_word(self): + """Kills to next word ending""" + #self[Point:NextWordEnd].to_clipboard() + if not self.delete_selection(): + del self[Point:NextWordEnd] + self.selection_mark=-1 + + def unix_word_rubout(self): + if not self.delete_selection(): + del self[PrevSpace:Point] + self.selection_mark=-1 + + def kill_region(self): + pass + + def copy_region_as_kill(self): + pass + + def copy_backward_word(self): + pass + + def copy_forward_word(self): + pass + + + def yank(self): + self.paste_from_kill_ring() + + def yank_pop(self): + pass + +############## Mark + + def set_mark(self): + self.mark=self.point + + def exchange_point_and_mark(self): + pass + + + def copy_region_to_clipboard(self): # () + '''Copy the text in the region to the windows clipboard.''' + if self.enable_win32_clipboard: + mark=min(self.mark,len(self.line_buffer)) + cursor=min(self.point,len(self.line_buffer)) + if self.mark==-1: + return + begin=min(cursor,mark) + end=max(cursor,mark) + toclipboard="".join(self.line_buffer[begin:end]) + clipboard.SetClipboardText(toclipboard) + + def copy_selection_to_clipboard(self): # () + '''Copy the text in the region to the windows clipboard.''' + if self.enable_win32_clipboard and self.enable_selection and self.selection_mark>=0: + selection_mark=min(self.selection_mark,len(self.line_buffer)) + cursor=min(self.point,len(self.line_buffer)) + if self.selection_mark==-1: + return + begin=min(cursor,selection_mark) + end=max(cursor,selection_mark) + toclipboard="".join(self.line_buffer[begin:end]) + clipboard.SetClipboardText(toclipboard) + + + def cut_selection_to_clipboard(self): # () + self.copy_selection_to_clipboard() + self.delete_selection() +############## Paste + + +############## Kill ring + def add_to_kill_ring(self,txt): + self.kill_ring=[txt] + if kill_ring_to_clipboard: + clipboard.SetClipboardText(txt.get_line_text()) + + + def paste_from_kill_ring(self): + if self.kill_ring: + self.insert_text(self.kill_ring[0]) + + +################################################################## +q=ReadLineTextBuffer("asff asFArw ewrWErhg",point=8) +q=TextLine("asff asFArw ewrWErhg",point=8) + +def show_pos(buff,pos,chr="."): + l=len(buff.line_buffer) + def choice(bool): + if bool: + return chr + else: + return " " + return "".join([choice(pos==idx) for idx in range(l+1)]) + + +def test_positioner(buff,points,positioner): + print (" %s "%positioner.__class__.__name__).center(40,"-") + buffstr=buff.line_buffer + + print '"%s"'%(buffstr) + for point in points: + b=TextLine(buff,point=point) + out=[" "]*(len(buffstr)+1) + pos=positioner(b) + if pos==point: + out[pos]="&" + else: + out[point]="." + out[pos]="^" + print '"%s"'%("".join(out)) + +if __name__=="__main__": + import startup + + print '%-15s "%s"'%("Position",q.get_line_text()) + print '%-15s "%s"'%("Point",show_pos(q,q.point)) + + + for name,positioner in all_positioners: + pos=positioner(q) + [] + print '%-15s "%s"'%(name,show_pos(q,pos,"^")) + + l=ReadLineTextBuffer("kjjk asads asad") + l.point=EndOfLine diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/lineeditor/wordmatcher.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/lineeditor/wordmatcher.py new file mode 100644 index 0000000..fa41a46 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/lineeditor/wordmatcher.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +import re,operator + + +def str_find_all(str,ch): + result=[] + index=0 + while index>=0: + index=str.find(ch,index) + if index>=0: + result.append(index) + index+=1 + return result + + +word_pattern=re.compile("(x*)") + +def markwords(str,iswordfun): + markers={True:"x",False:"o"} + return "".join([markers[iswordfun(ch)] for ch in str]) + +def split_words(str,iswordfun): + return [x for x in word_pattern.split(markwords(str,iswordfun)) if x !=""] + +def mark_start_segment(str,is_segment): + def mark_start(s): + if s[0:1]=="x": + return "s"+s[1:] + else: + return s + return "".join(map(mark_start,split_words(str,is_segment))) + +def mark_end_segment(str,is_segment): + def mark_start(s): + if s[0:1]=="x": + return s[:-1]+"s" + else: + return s + return "".join(map(mark_start,split_words(str,is_segment))) + +def mark_start_segment_index(str,is_segment): + return str_find_all(mark_start_segment(str,is_segment),"s") + +def mark_end_segment_index(str,is_segment): + return [x+1 for x in str_find_all(mark_end_segment(str,is_segment),"s")] + + +################ Following are used in lineobj ########################### + +def is_word_token(str): + return not is_non_word_token(str) + +def is_non_word_token(str): + if len(str)!=1 or str in " \t\n": + return True + else: + return False + +def next_start_segment(str,is_segment): + str="".join(str) + result=[] + for start in mark_start_segment_index(str,is_segment): + result[len(result):start]=[start for x in range(start-len(result))] + result[len(result):len(str)]=[len(str) for x in range(len(str)-len(result)+1)] + return result + +def next_end_segment(str,is_segment): + str="".join(str) + result=[] + for start in mark_end_segment_index(str,is_segment): + result[len(result):start]=[start for x in range(start-len(result))] + result[len(result):len(str)]=[len(str) for x in range(len(str)-len(result)+1)] + return result + + +def prev_start_segment(str,is_segment): + str="".join(str) + result=[] + prev=0 + for start in mark_start_segment_index(str,is_segment): + result[len(result):start+1]=[prev for x in range(start-len(result)+1)] + prev=start + result[len(result):len(str)]=[prev for x in range(len(str)-len(result)+1)] + return result + +def prev_end_segment(str,is_segment): + str="".join(str) + result=[] + prev=0 + for start in mark_end_segment_index(str,is_segment): + result[len(result):start+1]=[prev for x in range(start-len(result)+1)] + prev=start + result[len(result):len(str)]=[len(str) for x in range(len(str)-len(result)+1)] + return result + + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/logger.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/logger.py new file mode 100644 index 0000000..af2a90a --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/logger.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +import socket +from pyreadline.unicode_helper import ensure_str +_logfile=False + +def start_log(on,filename): + global _logfile + if on=="on": + _logfile=open(filename,"w") + else: + _logfile=False + +def log(s): + if _logfile: + s = ensure_str(s) + print >>_logfile, s + _logfile.flush() + + +host="localhost" +port=8081 +logsocket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) + +show_event=["keypress","bound_function","bind_key","console"] +show_event=["bound_function"] + +sock_silent=True + +def log_sock(s,event_type=None): + if sock_silent: + pass + else: + if event_type is None: + logsocket.sendto(ensure_str(s),(host,port)) + elif event_type in show_event: + logsocket.sendto(ensure_str(s),(host,port)) + else: + pass + + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/logserver.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/logserver.py new file mode 100644 index 0000000..65f260d --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/logserver.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +import socket + + +try: + import msvcrt +except ImportError: + msvcrt=None + print "problem" + + + +port =8081 + +s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) + +s.bind(("",port)) +s.settimeout(0.05) + +print "Starting logserver on port:",port +print "Press q to quit logserver",port +singleline=False + + +def check_key(): + if msvcrt is None: + return False + else: + if msvcrt.kbhit()!=0: + q=msvcrt.getch() + + return q in "q" + else: + return False + + +while 1: + try: + data,addr=s.recvfrom(1024) + except socket.timeout: + if check_key(): + print "Quitting logserver" + break + else: + continue + if data.startswith("@@"): + continue + if singleline: + print "\r"," "*78,"\r",data,#,addr + else: + print data + + + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/modes/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/modes/__init__.py new file mode 100644 index 0000000..8b1ec1e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/modes/__init__.py @@ -0,0 +1,5 @@ +__all__=["emacs","notemacs","vi"] +import emacs,notemacs,vi +editingmodes=[emacs.EmacsMode,notemacs.NotEmacsMode,vi.ViMode] + +#add check to ensure all modes have unique mode names \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/modes/basemode.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/modes/basemode.py new file mode 100644 index 0000000..939da19 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/modes/basemode.py @@ -0,0 +1,458 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2003-2006 Gary Bishop. +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +import os,re,math,glob,sys +import pyreadline.logger as logger +from pyreadline.logger import log,log_sock +from pyreadline.keysyms.common import make_KeyPress_from_keydescr +import pyreadline.lineeditor.lineobj as lineobj +import pyreadline.lineeditor.history as history +import pyreadline.clipboard as clipboard +from pyreadline.error import ReadlineError,GetSetError +from pyreadline.unicode_helper import ensure_str, ensure_unicode +in_ironpython="IronPython" in sys.version + +class BaseMode(object): + mode="base" + def __init__(self,rlobj): + self.rlobj=rlobj + self.exit_dispatch = {} + self.key_dispatch = {} + self.argument=1 + self.prevargument=None + + def __repr__(self): + return "" + + def _gs(x): + def g(self): + return getattr(self.rlobj,x) + def s(self,q): + setattr(self.rlobj,x,q) + return g,s + + def _g(x): + def g(self): + return getattr(self.rlobj,x) + return g + + def _argreset(self): + val=self.argument + self.argument=1 + return val + argument_reset=property(_argreset) + + ctrl_c_tap_time_interval=property(*_gs("ctrl_c_tap_time_interval")) + allow_ctrl_c=property(*_gs("allow_ctrl_c")) + l_buffer=property(*_gs("l_buffer")) + next_meta=property(*_gs("next_meta")) + first_prompt=property(*_gs("first_prompt")) + prompt=property(*_gs("prompt")) + paste_line_buffer=property(*_gs("paste_line_buffer")) + completer_delims=property(*_gs("completer_delims")) + show_all_if_ambiguous=property(*_gs("show_all_if_ambiguous")) + mark_directories=property(*_gs("mark_directories")) + completer=property(*_gs("completer")) + begidx=property(*_gs("begidx")) + startup_hook=property(*_gs("startup_hook")) + pre_input_hook=property(*_gs("pre_input_hook")) + endidx=property(*_gs("endidx")) + + console=property(_g("console")) + insert_text=property(_g("insert_text")) + _print_prompt=property(_g("_print_prompt")) + _update_line=property(_g("_update_line")) + add_history=property(_g("add_history")) + _bell=property(_g("_bell")) + _clear_after=property(_g("_clear_after")) + _set_cursor=property(_g("_set_cursor")) + _update_prompt_pos=property(_g("_update_prompt_pos")) + _update_line=property(_g("_update_line")) + enable_win32_clipboard=property(_g("enable_win32_clipboard")) + enable_ipython_paste_list_of_lists=property(_g("enable_ipython_paste_list_of_lists")) + enable_ipython_paste_for_paths=property(_g("enable_ipython_paste_for_paths")) + _bell=property(_g("_bell")) + _history=property(_g("_history")) + prompt_end_pos=property(_g("prompt_end_pos")) + prompt_begin_pos=property(_g("prompt_begin_pos")) + + rl_settings_to_string=property(_g("rl_settings_to_string")) + + def _readline_from_keyboard(self): + raise NotImplementedError + + def readline(self, prompt=''): + raise NotImplementedError + + #Create key bindings: + + def _bind_key(self, key, func): + '''setup the mapping from key to call the function.''' + if type(func) != type(self._bind_key): + print "Trying to bind non method to keystroke:%s,%s"%(key,func) + raise PyreadlineError("Trying to bind non method to keystroke:%s,%s,%s,%s"%(key,func,type(func),type(self._bind_key))) + keyinfo = make_KeyPress_from_keydescr(key.lower()).tuple() + log(">>>%s -> %s<<<"%(keyinfo,func.__name__)) + self.key_dispatch[keyinfo] = func + + def _bind_exit_key(self, key): + '''setup the mapping from key to call the function.''' + keyinfo = make_KeyPress_from_keydescr(key.lower()).tuple() + self.exit_dispatch[keyinfo] = None + + def init_editing_mode(self, e): # (C-e) + '''When in vi command mode, this causes a switch to emacs editing + mode.''' + + raise NotImplementedError +#completion commands + + def _get_completions(self): + + '''Return a list of possible completions for the string ending at the point. + + Also set begidx and endidx in the process.''' + completions = [] + self.begidx = self.l_buffer.point + self.endidx = self.l_buffer.point + buf=self.l_buffer.line_buffer + if self.completer: + # get the string to complete + while self.begidx > 0: + self.begidx -= 1 + if buf[self.begidx] in self.completer_delims: + self.begidx += 1 + break + text = ensure_str(''.join(buf[self.begidx:self.endidx])) + log('complete text="%s"' % text) + i = 0 + while 1: + try: + r = ensure_unicode(self.completer(text, i)) + except: + break + i += 1 + if r and r not in completions: + completions.append(r) + else: + break + log('text completions=%s' % completions) + if not completions: + # get the filename to complete + while self.begidx > 0: + self.begidx -= 1 + if buf[self.begidx] in ' \t\n': + self.begidx += 1 + break + text = ensure_str(''.join(buf[self.begidx:self.endidx])) + log('file complete text="%s"' % text) + completions = map(ensure_unicode, glob.glob(os.path.expanduser(text) + '*')) + if self.mark_directories == 'on': + mc = [] + for f in completions: + if os.path.isdir(f): + mc.append(f + os.sep) + else: + mc.append(f) + completions = mc + log('fnames=%s' % completions) + return completions + + + def _display_completions(self, completions): + if not completions: + return + self.console.write('\n') + wmax = max(map(len, completions)) + w, h = self.console.size() + cols = max(1, int((w-1) / (wmax+1))) + rows = int(math.ceil(float(len(completions)) / cols)) + for row in range(rows): + s = '' + for col in range(cols): + i = col*rows + row + if i < len(completions): + self.console.write(completions[i].ljust(wmax+1)) + self.console.write('\n') + if in_ironpython: + self.prompt=sys.ps1 + self._print_prompt() + + def complete(self, e): # (TAB) + '''Attempt to perform completion on the text before point. The + actual completion performed is application-specific. The default is + filename completion.''' + completions = self._get_completions() + if completions: + cprefix = commonprefix(completions) + rep = [ c for c in cprefix ] + point=self.l_buffer.point + self.l_buffer[self.begidx:self.endidx] = rep + self.l_buffer.point = point + len(rep) - (self.endidx - self.begidx) + if len(completions) > 1: + if self.show_all_if_ambiguous == 'on': + self._display_completions(completions) + else: + self._bell() + else: + self._bell() + + def possible_completions(self, e): # (M-?) + '''List the possible completions of the text before point. ''' + completions = self._get_completions() + self._display_completions(completions) + + def insert_completions(self, e): # (M-*) + '''Insert all completions of the text before point that would have + been generated by possible-completions.''' + completions = self._get_completions() + b = self.begidx + e = self.endidx + for comp in completions: + rep = [ c for c in comp ] + rep.append(' ') + self.l_buffer[b:e] = rep + b += len(rep) + e = b + self.line_cursor = b + + def menu_complete(self, e): # () + '''Similar to complete, but replaces the word to be completed with a + single match from the list of possible completions. Repeated + execution of menu-complete steps through the list of possible + completions, inserting each match in turn. At the end of the list of + completions, the bell is rung (subject to the setting of bell-style) + and the original text is restored. An argument of n moves n + positions forward in the list of matches; a negative argument may be + used to move backward through the list. This command is intended to + be bound to TAB, but is unbound by default.''' + pass + + ### Methods below here are bindable emacs functions + + def beginning_of_line(self, e): # (C-a) + '''Move to the start of the current line. ''' + self.l_buffer.beginning_of_line() + + def end_of_line(self, e): # (C-e) + '''Move to the end of the line. ''' + self.l_buffer.end_of_line() + + def forward_char(self, e): # (C-f) + '''Move forward a character. ''' + self.l_buffer.forward_char(self.argument_reset) + + def backward_char(self, e): # (C-b) + '''Move back a character. ''' + self.l_buffer.backward_char(self.argument_reset) + + def forward_word(self, e): # (M-f) + '''Move forward to the end of the next word. Words are composed of + letters and digits.''' + self.l_buffer.forward_word(self.argument_reset) + + def backward_word(self, e): # (M-b) + '''Move back to the start of the current or previous word. Words are + composed of letters and digits.''' + self.l_buffer.backward_word(self.argument_reset) + + def forward_word_end(self, e): # () + '''Move forward to the end of the next word. Words are composed of + letters and digits.''' + self.l_buffer.forward_word_end(self.argument_reset) + + def backward_word_end(self, e): # () + '''Move forward to the end of the next word. Words are composed of + letters and digits.''' + self.l_buffer.backward_word_end(self.argument_reset) + +### Movement with extend selection + def beginning_of_line_extend_selection(self, e): # + '''Move to the start of the current line. ''' + self.l_buffer.beginning_of_line_extend_selection() + + def end_of_line_extend_selection(self, e): # + '''Move to the end of the line. ''' + self.l_buffer.end_of_line_extend_selection() + + def forward_char_extend_selection(self, e): # + '''Move forward a character. ''' + self.l_buffer.forward_char_extend_selection(self.argument_reset) + + def backward_char_extend_selection(self, e): # + '''Move back a character. ''' + self.l_buffer.backward_char_extend_selection(self.argument_reset) + + def forward_word_extend_selection(self, e): # + '''Move forward to the end of the next word. Words are composed of + letters and digits.''' + self.l_buffer.forward_word_extend_selection(self.argument_reset) + + def backward_word_extend_selection(self, e): # + '''Move back to the start of the current or previous word. Words are + composed of letters and digits.''' + self.l_buffer.backward_word_extend_selection(self.argument_reset) + + def forward_word_end_extend_selection(self, e): # + '''Move forward to the end of the next word. Words are composed of + letters and digits.''' + self.l_buffer.forward_word_end_extend_selection(self.argument_reset) + + def backward_word_end_extend_selection(self, e): # + '''Move forward to the end of the next word. Words are composed of + letters and digits.''' + self.l_buffer.forward_word_end_extend_selection(self.argument_reset) + + +######## Change case + + def upcase_word(self, e): # (M-u) + '''Uppercase the current (or following) word. With a negative + argument, uppercase the previous word, but do not move the cursor.''' + self.l_buffer.upcase_word() + + def downcase_word(self, e): # (M-l) + '''Lowercase the current (or following) word. With a negative + argument, lowercase the previous word, but do not move the cursor.''' + self.l_buffer.downcase_word() + + def capitalize_word(self, e): # (M-c) + '''Capitalize the current (or following) word. With a negative + argument, capitalize the previous word, but do not move the cursor.''' + self.l_buffer.capitalize_word() + + +######## + def clear_screen(self, e): # (C-l) + '''Clear the screen and redraw the current line, leaving the current + line at the top of the screen.''' + self.console.page() + + def redraw_current_line(self, e): # () + '''Refresh the current line. By default, this is unbound.''' + pass + + def accept_line(self, e): # (Newline or Return) + '''Accept the line regardless of where the cursor is. If this line + is non-empty, it may be added to the history list for future recall + with add_history(). If this line is a modified history line, the + history line is restored to its original state.''' + return True + + + def delete_char(self, e): # (C-d) + '''Delete the character at point. If point is at the beginning of + the line, there are no characters in the line, and the last + character typed was not bound to delete-char, then return EOF.''' + self.l_buffer.delete_char(self.argument_reset) + + def backward_delete_char(self, e): # (Rubout) + '''Delete the character behind the cursor. A numeric argument means + to kill the characters instead of deleting them.''' + self.l_buffer.backward_delete_char(self.argument_reset) + + def backward_delete_word(self, e): # (Control-Rubout) + '''Delete the character behind the cursor. A numeric argument means + to kill the characters instead of deleting them.''' + self.l_buffer.backward_delete_word(self.argument_reset) + + def forward_delete_word(self, e): # (Control-Delete) + '''Delete the character behind the cursor. A numeric argument means + to kill the characters instead of deleting them.''' + self.l_buffer.forward_delete_word(self.argument_reset) + + def delete_horizontal_space(self, e): # () + '''Delete all spaces and tabs around point. By default, this is unbound. ''' + self.l_buffer.delete_horizontal_space() + + def self_insert(self, e): # (a, b, A, 1, !, ...) + '''Insert yourself. ''' + + if e.char and ord(e.char)!=0: #don't insert null character in buffer, can happen with dead keys. + self.insert_text(e.char) + + +# Paste from clipboard + + def paste(self,e): + '''Paste windows clipboard. + Assume single line strip other lines and end of line markers and trailing spaces''' #(Control-v) + if self.enable_win32_clipboard: + txt=clipboard.get_clipboard_text_and_convert(False) + txt=txt.split("\n")[0].strip("\r").strip("\n") + log("paste: >%s<"%map(ord,txt)) + self.insert_text(txt) + + def paste_mulitline_code(self,e): + '''Paste windows clipboard as multiline code. + Removes any empty lines in the code''' + reg=re.compile("\r?\n") + if self.enable_win32_clipboard: + txt=clipboard.get_clipboard_text_and_convert(False) + t=reg.split(txt) + t=[row for row in t if row.strip()!=""] #remove empty lines + if t!=[""]: + self.insert_text(t[0]) + self.add_history(self.l_buffer.copy()) + self.paste_line_buffer=t[1:] + log("multi: %s"%self.paste_line_buffer) + return True + else: + return False + + def ipython_paste(self,e): + '''Paste windows clipboard. If enable_ipython_paste_list_of_lists is + True then try to convert tabseparated data to repr of list of lists or + repr of array. + If enable_ipython_paste_for_paths==True then change \\ to / and spaces to \space''' + if self.enable_win32_clipboard: + txt=clipboard.get_clipboard_text_and_convert( + self.enable_ipython_paste_list_of_lists) + if self.enable_ipython_paste_for_paths: + if len(txt)<300 and ("\t" not in txt) and ("\n" not in txt): + txt=txt.replace("\\","/").replace(" ",r"\ ") + self.insert_text(txt) + + + def copy_region_to_clipboard(self, e): # () + '''Copy the text in the region to the windows clipboard.''' + self.l_buffer.copy_region_to_clipboard() + + def copy_selection_to_clipboard(self, e): # () + '''Copy the text in the region to the windows clipboard.''' + self.l_buffer.copy_selection_to_clipboard() + + def cut_selection_to_clipboard(self, e): # () + '''Copy the text in the region to the windows clipboard.''' + self.l_buffer.cut_selection_to_clipboard() + + + def dump_functions(self, e): # () + '''Print all of the functions and their key bindings to the Readline + output stream. If a numeric argument is supplied, the output is + formatted in such a way that it can be made part of an inputrc + file. This command is unbound by default.''' + print + txt="\n".join(self.rl_settings_to_string()) + print txt + self._print_prompt() + + + + +def commonprefix(m): + "Given a list of pathnames, returns the longest common leading component" + if not m: return '' + prefix = m[0] + for item in m: + for i in range(len(prefix)): + if prefix[:i+1].lower() != item[:i+1].lower(): + prefix = prefix[:i] + if i == 0: return '' + break + return prefix diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/modes/emacs.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/modes/emacs.py new file mode 100644 index 0000000..2d6b7e1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/modes/emacs.py @@ -0,0 +1,628 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2003-2006 Gary Bishop. +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +import os,sys,time +import pyreadline.logger as logger +from pyreadline.logger import log,log_sock +from pyreadline.lineeditor.lineobj import Point +import pyreadline.lineeditor.lineobj as lineobj +import pyreadline.lineeditor.history as history +import basemode +import string +from pyreadline.unicode_helper import ensure_unicode + +def format(keyinfo): + if len(keyinfo[-1])!=1: + k=keyinfo+(-1,) + else: + k=keyinfo+(ord(keyinfo[-1]),) + + return "(%s,%s,%s,%s,%x)"%k +in_ironpython="IronPython" in sys.version + + +class EmacsMode(basemode.BaseMode): + mode="emacs" + def __init__(self,rlobj): + super(EmacsMode,self).__init__(rlobj) + self._keylog=(lambda x,y: None) + self.previous_func=None + self.prompt=">>>" + def __repr__(self): + return "" + + def add_key_logger(self,logfun): + """logfun should be function that takes disp_fun and line_buffer object """ + self._keylog=logfun + + def _readline_from_keyboard(self): + c=self.console + def nop(e): + pass + while 1: + self._update_line() + lbuf=self.l_buffer + log_sock("point:%d mark:%d selection_mark:%d"%(lbuf.point,lbuf.mark,lbuf.selection_mark)) + try: + event = c.getkeypress() + log_sock(u">>%s"%event) + except KeyboardInterrupt: + from pyreadline.keysyms.common import KeyPress + from pyreadline.console.event import Event + event=Event(0,0) + event.char="c" + event.keyinfo=KeyPress("c",shift=False,control=True,meta=False,keyname=None) + log_sock("KBDIRQ") + if self.allow_ctrl_c: + now=time.time() + if (now-self.ctrl_c_timeout)1: + default=nop + else: + default=self.self_insert + dispatch_func = self.key_dispatch.get(keyinfo,default) + + log("readline from keyboard:%s,%s"%(keyinfo,dispatch_func)) + log_sock((u"%s|%s"%(ensure_unicode(format(keyinfo)),dispatch_func.__name__)),"bound_function") + r = None + if dispatch_func: + r = dispatch_func(event) + self._keylog(dispatch_func,self.l_buffer) + self.l_buffer.push_undo() + + self.previous_func = dispatch_func + if r: + self._update_line() + break + + def readline(self, prompt=''): + '''Try to act like GNU readline.''' + # handle startup_hook + self.ctrl_c_timeout=time.time() + self.l_buffer.selection_mark=-1 + if self.first_prompt: + self.first_prompt = False + if self.startup_hook: + try: + self.startup_hook() + except: + print 'startup hook failed' + traceback.print_exc() + + c = self.console + self.l_buffer.reset_line() + self.prompt = prompt + self._print_prompt() + + if self.pre_input_hook: + try: + self.pre_input_hook() + except: + print 'pre_input_hook failed' + traceback.print_exc() + self.pre_input_hook = None + + log("in readline: %s"%self.paste_line_buffer) + if len(self.paste_line_buffer)>0: + self.l_buffer=lineobj.ReadLineTextBuffer(self.paste_line_buffer[0]) + self._update_line() + self.paste_line_buffer=self.paste_line_buffer[1:] + c.write('\r\n') + else: + self._readline_from_keyboard() + c.write('\r\n') + + self.add_history(self.l_buffer.copy()) + + log('returning(%s)' % self.l_buffer.get_line_text()) + return self.l_buffer.get_line_text() + '\n' + +######### History commands + def previous_history(self, e): # (C-p) + '''Move back through the history list, fetching the previous command. ''' + self._history.previous_history(self.l_buffer) + self.l_buffer.point=lineobj.EndOfLine + + def next_history(self, e): # (C-n) + '''Move forward through the history list, fetching the next command. ''' + self._history.next_history(self.l_buffer) + + def beginning_of_history(self, e): # (M-<) + '''Move to the first line in the history.''' + self._history.beginning_of_history() + + def end_of_history(self, e): # (M->) + '''Move to the end of the input history, i.e., the line currently + being entered.''' + self._history.end_of_history(self.l_buffer) + + def _i_search(self, searchfun, direction, init_event): + c = self.console + line = self.l_buffer.get_line_text() + query = '' + if (self.previous_func != self.history_search_forward and + self.previous_func != self.history_search_backward): + self.query = ''.join(self.l_buffer[0:Point].get_line_text()) + hc_start = self._history.history_cursor #+ direction + while 1: + x, y = self.prompt_end_pos + c.pos(0, y) + if direction < 0: + prompt = 'reverse-i-search' + else: + prompt = 'forward-i-search' + + scroll = c.write_scrolling("%s`%s': %s" % (prompt, query, line)) + self._update_prompt_pos(scroll) + self._clear_after() + + event = c.getkeypress() + if event.keyinfo.keyname == 'backspace': + query = query[:-1] + if len(query) > 0: + #self._history.history_cursor = hc_start #forces search to restart when search empty + line=searchfun(query) + else: + self._bell() + line="" #empty query means no search result + elif event.char in string.letters + string.digits + string.punctuation + ' ': + #self._history.history_cursor = hc_start + query += event.char + line=searchfun(query) + elif event.keyinfo == init_event.keyinfo: + self._history.history_cursor += direction + line=searchfun(query) + else: + if event.keyinfo.keyname != 'return': + self._bell() + break + + px, py = self.prompt_begin_pos + c.pos(0, py) + self.l_buffer.set_line(line) + self._print_prompt() + self._history.history_cursor=len(self._history.history) + + def reverse_search_history(self, e): # (C-r) + '''Search backward starting at the current line and moving up + through the history as necessary. This is an incremental search.''' + self._i_search(self._history.reverse_search_history, -1, e) + + def forward_search_history(self, e): # (C-s) + '''Search forward starting at the current line and moving down + through the the history as necessary. This is an incremental search.''' + self._i_search(self._history.forward_search_history, 1, e) + + + def non_incremental_reverse_search_history(self, e): # (M-p) + '''Search backward starting at the current line and moving up + through the history as necessary using a non-incremental search for + a string supplied by the user.''' + q=self._history.non_incremental_reverse_search_history(self.l_buffer) + self.l_buffer=q + + def non_incremental_forward_search_history(self, e): # (M-n) + '''Search forward starting at the current line and moving down + through the the history as necessary using a non-incremental search + for a string supplied by the user.''' + q=self._history.non_incremental_reverse_search_history(self.l_buffer) + self.l_buffer=q + + def history_search_forward(self, e): # () + '''Search forward through the history for the string of characters + between the start of the current line and the point. This is a + non-incremental search. By default, this command is unbound.''' + if self.previous_func and hasattr(self._history,self.previous_func.__name__): + self._history.lastcommand=getattr(self._history,self.previous_func.__name__) + else: + self._history.lastcommand=None + q=self._history.history_search_forward(self.l_buffer) + self.l_buffer=q + self.l_buffer.point=q.point + + def history_search_backward(self, e): # () + '''Search backward through the history for the string of characters + between the start of the current line and the point. This is a + non-incremental search. By default, this command is unbound.''' + if self.previous_func and hasattr(self._history,self.previous_func.__name__): + self._history.lastcommand=getattr(self._history,self.previous_func.__name__) + else: + self._history.lastcommand=None + q=self._history.history_search_backward(self.l_buffer) + self.l_buffer=q + self.l_buffer.point=q.point + + + def yank_nth_arg(self, e): # (M-C-y) + '''Insert the first argument to the previous command (usually the + second word on the previous line) at point. With an argument n, + insert the nth word from the previous command (the words in the + previous command begin with word 0). A negative argument inserts the + nth word from the end of the previous command.''' + pass + + def yank_last_arg(self, e): # (M-. or M-_) + '''Insert last argument to the previous command (the last word of + the previous history entry). With an argument, behave exactly like + yank-nth-arg. Successive calls to yank-last-arg move back through + the history list, inserting the last argument of each line in turn.''' + pass + + def forward_backward_delete_char(self, e): # () + '''Delete the character under the cursor, unless the cursor is at + the end of the line, in which case the character behind the cursor + is deleted. By default, this is not bound to a key.''' + pass + + def quoted_insert(self, e): # (C-q or C-v) + '''Add the next character typed to the line verbatim. This is how to + insert key sequences like C-q, for example.''' + e = self.console.getkeypress() + self.insert_text(e.char) + + def tab_insert(self, e): # (M-TAB) + '''Insert a tab character. ''' + ws = ' ' * (self.tabstop - (self.line_cursor%self.tabstop)) + self.insert_text(ws) + + def transpose_chars(self, e): # (C-t) + '''Drag the character before the cursor forward over the character + at the cursor, moving the cursor forward as well. If the insertion + point is at the end of the line, then this transposes the last two + characters of the line. Negative arguments have no effect.''' + self.l_buffer.transpose_chars() + + def transpose_words(self, e): # (M-t) + '''Drag the word before point past the word after point, moving + point past that word as well. If the insertion point is at the end + of the line, this transposes the last two words on the line.''' + self.l_buffer.transpose_words() + + def overwrite_mode(self, e): # () + '''Toggle overwrite mode. With an explicit positive numeric + argument, switches to overwrite mode. With an explicit non-positive + numeric argument, switches to insert mode. This command affects only + emacs mode; vi mode does overwrite differently. Each call to + readline() starts in insert mode. In overwrite mode, characters + bound to self-insert replace the text at point rather than pushing + the text to the right. Characters bound to backward-delete-char + replace the character before point with a space.''' + pass + + def kill_line(self, e): # (C-k) + '''Kill the text from point to the end of the line. ''' + self.l_buffer.kill_line() + + def backward_kill_line(self, e): # (C-x Rubout) + '''Kill backward to the beginning of the line. ''' + self.l_buffer.backward_kill_line() + + def unix_line_discard(self, e): # (C-u) + '''Kill backward from the cursor to the beginning of the current line. ''' + # how is this different from backward_kill_line? + self.l_buffer.unix_line_discard() + + def kill_whole_line(self, e): # () + '''Kill all characters on the current line, no matter where point + is. By default, this is unbound.''' + self.l_buffer.kill_whole_line() + + def kill_word(self, e): # (M-d) + '''Kill from point to the end of the current word, or if between + words, to the end of the next word. Word boundaries are the same as + forward-word.''' + self.l_buffer.kill_word() + forward_kill_word=kill_word + + def backward_kill_word(self, e): # (M-DEL) + '''Kill the word behind point. Word boundaries are the same as + backward-word. ''' + self.l_buffer.backward_kill_word() + + def unix_word_rubout(self, e): # (C-w) + '''Kill the word behind point, using white space as a word + boundary. The killed text is saved on the kill-ring.''' + self.l_buffer.unix_word_rubout() + + def kill_region(self, e): # () + '''Kill the text in the current region. By default, this command is unbound. ''' + pass + + def copy_region_as_kill(self, e): # () + '''Copy the text in the region to the kill buffer, so it can be + yanked right away. By default, this command is unbound.''' + pass + + def copy_backward_word(self, e): # () + '''Copy the word before point to the kill buffer. The word + boundaries are the same as backward-word. By default, this command + is unbound.''' + pass + + def copy_forward_word(self, e): # () + '''Copy the word following point to the kill buffer. The word + boundaries are the same as forward-word. By default, this command is + unbound.''' + pass + + + def yank(self, e): # (C-y) + '''Yank the top of the kill ring into the buffer at point. ''' + self.l_buffer.yank() + + def yank_pop(self, e): # (M-y) + '''Rotate the kill-ring, and yank the new top. You can only do this + if the prior command is yank or yank-pop.''' + self.l_buffer.yank_pop() + + + def digit_argument(self, e): # (M-0, M-1, ... M--) + '''Add this digit to the argument already accumulating, or start a + new argument. M-- starts a negative argument.''' + args=e.char + + c = self.console + line = self.l_buffer.get_line_text() + oldprompt=self.prompt + def nop(e): + pass + while 1: + x, y = self.prompt_end_pos + c.pos(0, y) + self.prompt="(arg: %s) "%args + self._print_prompt() + self._update_line() + + event = c.getkeypress() + if event.keyinfo.keyname == 'enter': + break + elif event.char in "0123456789": + args+=event.char + else: + self.argument=int(args) + keyinfo=event.keyinfo.tuple() + if len(keyinfo[-1])>1: + default=nop + else: + default=self.self_insert + dispatch_func = self.key_dispatch.get(keyinfo,default) + dispatch_func(event) + break + self.prompt=oldprompt + x, y = self.prompt_end_pos + c.pos(0, y) + self._print_prompt() + self._update_line() + + + + + def universal_argument(self, e): # () + '''This is another way to specify an argument. If this command is + followed by one or more digits, optionally with a leading minus + sign, those digits define the argument. If the command is followed + by digits, executing universal-argument again ends the numeric + argument, but is otherwise ignored. As a special case, if this + command is immediately followed by a character that is neither a + digit or minus sign, the argument count for the next command is + multiplied by four. The argument count is initially one, so + executing this function the first time makes the argument count + four, a second time makes the argument count sixteen, and so on. By + default, this is not bound to a key.''' + pass + + def delete_char_or_list(self, e): # () + '''Deletes the character under the cursor if not at the beginning or + end of the line (like delete-char). If at the end of the line, + behaves identically to possible-completions. This command is unbound + by default.''' + pass + + def start_kbd_macro(self, e): # (C-x () + '''Begin saving the characters typed into the current keyboard macro. ''' + pass + + def end_kbd_macro(self, e): # (C-x )) + '''Stop saving the characters typed into the current keyboard macro + and save the definition.''' + pass + + def call_last_kbd_macro(self, e): # (C-x e) + '''Re-execute the last keyboard macro defined, by making the + characters in the macro appear as if typed at the keyboard.''' + pass + + def re_read_init_file(self, e): # (C-x C-r) + '''Read in the contents of the inputrc file, and incorporate any + bindings or variable assignments found there.''' + pass + + def abort(self, e): # (C-g) + '''Abort the current editing command and ring the terminals bell + (subject to the setting of bell-style).''' + self._bell() + + def do_uppercase_version(self, e): # (M-a, M-b, M-x, ...) + '''If the metafied character x is lowercase, run the command that is + bound to the corresponding uppercase character.''' + pass + + def prefix_meta(self, e): # (ESC) + '''Metafy the next character typed. This is for keyboards without a + meta key. Typing ESC f is equivalent to typing M-f. ''' + self.next_meta = True + + def undo(self, e): # (C-_ or C-x C-u) + '''Incremental undo, separately remembered for each line.''' + self.l_buffer.pop_undo() + + def revert_line(self, e): # (M-r) + '''Undo all changes made to this line. This is like executing the + undo command enough times to get back to the beginning.''' + pass + + def tilde_expand(self, e): # (M-~) + '''Perform tilde expansion on the current word.''' + pass + + def set_mark(self, e): # (C-@) + '''Set the mark to the point. If a numeric argument is supplied, the + mark is set to that position.''' + self.l_buffer.set_mark() + + def exchange_point_and_mark(self, e): # (C-x C-x) + '''Swap the point with the mark. The current cursor position is set + to the saved position, and the old cursor position is saved as the + mark.''' + pass + + def character_search(self, e): # (C-]) + '''A character is read and point is moved to the next occurrence of + that character. A negative count searches for previous occurrences.''' + pass + + def character_search_backward(self, e): # (M-C-]) + '''A character is read and point is moved to the previous occurrence + of that character. A negative count searches for subsequent + occurrences.''' + pass + + def insert_comment(self, e): # (M-#) + '''Without a numeric argument, the value of the comment-begin + variable is inserted at the beginning of the current line. If a + numeric argument is supplied, this command acts as a toggle: if the + characters at the beginning of the line do not match the value of + comment-begin, the value is inserted, otherwise the characters in + comment-begin are deleted from the beginning of the line. In either + case, the line is accepted as if a newline had been typed.''' + pass + + def dump_variables(self, e): # () + '''Print all of the settable variables and their values to the + Readline output stream. If a numeric argument is supplied, the + output is formatted in such a way that it can be made part of an + inputrc file. This command is unbound by default.''' + pass + + def dump_macros(self, e): # () + '''Print all of the Readline key sequences bound to macros and the + strings they output. If a numeric argument is supplied, the output + is formatted in such a way that it can be made part of an inputrc + file. This command is unbound by default.''' + pass + + + #Create key bindings: + + def init_editing_mode(self, e): # (C-e) + '''When in vi command mode, this causes a switch to emacs editing + mode.''' + self._bind_exit_key('Control-d') + self._bind_exit_key('Control-z') + + # I often accidentally hold the shift or control while typing space + self._bind_key('space', self.self_insert) + self._bind_key('Shift-space', self.self_insert) + self._bind_key('Control-space', self.self_insert) + self._bind_key('Return', self.accept_line) + self._bind_key('Left', self.backward_char) + self._bind_key('Control-b', self.backward_char) + self._bind_key('Right', self.forward_char) + self._bind_key('Control-f', self.forward_char) + self._bind_key('BackSpace', self.backward_delete_char) + self._bind_key('Control-BackSpace', self.backward_delete_word) + + self._bind_key('Home', self.beginning_of_line) + self._bind_key('End', self.end_of_line) + self._bind_key('Delete', self.delete_char) + self._bind_key('Control-d', self.delete_char) + self._bind_key('Clear', self.clear_screen) + self._bind_key('Alt-f', self.forward_word) + self._bind_key('Alt-b', self.backward_word) + self._bind_key('Control-l', self.clear_screen) + self._bind_key('Control-p', self.previous_history) + self._bind_key('Up', self.history_search_backward) + self._bind_key('Control-n', self.next_history) + self._bind_key('Down', self.history_search_forward) + self._bind_key('Control-a', self.beginning_of_line) + self._bind_key('Control-e', self.end_of_line) + self._bind_key('Alt-<', self.beginning_of_history) + self._bind_key('Alt->', self.end_of_history) + self._bind_key('Control-r', self.reverse_search_history) + self._bind_key('Control-s', self.forward_search_history) + self._bind_key('Alt-p', self.non_incremental_reverse_search_history) + self._bind_key('Alt-n', self.non_incremental_forward_search_history) + self._bind_key('Control-z', self.undo) + self._bind_key('Control-_', self.undo) + self._bind_key('Escape', self.kill_whole_line) + self._bind_key('Meta-d', self.kill_word) + self._bind_key('Control-Delete', self.forward_delete_word) + self._bind_key('Control-w', self.unix_word_rubout) + #self._bind_key('Control-Shift-v', self.quoted_insert) + self._bind_key('Control-v', self.paste) + self._bind_key('Alt-v', self.ipython_paste) + self._bind_key('Control-y', self.yank) + self._bind_key('Control-k', self.kill_line) + self._bind_key('Control-m', self.set_mark) + self._bind_key('Control-q', self.copy_region_to_clipboard) +# self._bind_key('Control-shift-k', self.kill_whole_line) + self._bind_key('Control-Shift-v', self.paste_mulitline_code) + self._bind_key("Control-Right", self.forward_word_end) + self._bind_key("Control-Left", self.backward_word) + self._bind_key("Shift-Right", self.forward_char_extend_selection) + self._bind_key("Shift-Left", self.backward_char_extend_selection) + self._bind_key("Shift-Control-Right", self.forward_word_end_extend_selection) + self._bind_key("Shift-Control-Left", self.backward_word_extend_selection) + self._bind_key("Shift-Home", self.beginning_of_line_extend_selection) + self._bind_key("Shift-End", self.end_of_line_extend_selection) + self._bind_key("numpad0", self.self_insert) + self._bind_key("numpad1", self.self_insert) + self._bind_key("numpad2", self.self_insert) + self._bind_key("numpad3", self.self_insert) + self._bind_key("numpad4", self.self_insert) + self._bind_key("numpad5", self.self_insert) + self._bind_key("numpad6", self.self_insert) + self._bind_key("numpad7", self.self_insert) + self._bind_key("numpad8", self.self_insert) + self._bind_key("numpad9", self.self_insert) + self._bind_key("add", self.self_insert) + self._bind_key("subtract", self.self_insert) + self._bind_key("multiply", self.self_insert) + self._bind_key("divide", self.self_insert) + self._bind_key("vk_decimal", self.self_insert) + log("RUNNING INIT EMACS") + +# make it case insensitive +def commonprefix(m): + "Given a list of pathnames, returns the longest common leading component" + if not m: return '' + prefix = m[0] + for item in m: + for i in range(len(prefix)): + if prefix[:i+1].lower() != item[:i+1].lower(): + prefix = prefix[:i] + if i == 0: return '' + break + return prefix + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/modes/notemacs.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/modes/notemacs.py new file mode 100644 index 0000000..4043a5c --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/modes/notemacs.py @@ -0,0 +1,601 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2003-2006 Gary Bishop. +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +import os +import pyreadline.logger as logger +from pyreadline.logger import log +import pyreadline.lineeditor.lineobj as lineobj +import pyreadline.lineeditor.history as history +import basemode + +class NotEmacsMode(basemode.BaseMode): + mode="notemacs" + def __init__(self,rlobj): + super(NotEmacsMode,self).__init__(rlobj) + + def __repr__(self): + return "" + + def _readline_from_keyboard(self): + c=self.console + while 1: + self._update_line() + event = c.getkeypress() + if self.next_meta: + self.next_meta = False + control, meta, shift, code = event.keyinfo + event.keyinfo = (control, True, shift, code) + + #Process exit keys. Only exit on empty line + if event.keyinfo in self.exit_dispatch: + if lineobj.EndOfLine(self.l_buffer) == 0: + raise EOFError + + dispatch_func = self.key_dispatch.get(event.keyinfo,self.self_insert) + log("readline from keyboard:%s"%(event.keyinfo,)) + r = None + if dispatch_func: + r = dispatch_func(event) + self.l_buffer.push_undo() + + self.previous_func = dispatch_func + if r: + self._update_line() + break + + def readline(self, prompt=''): + '''Try to act like GNU readline.''' + # handle startup_hook + if self.first_prompt: + self.first_prompt = False + if self.startup_hook: + try: + self.startup_hook() + except: + print 'startup hook failed' + traceback.print_exc() + + c = self.console + self.l_buffer.reset_line() + self.prompt = prompt + self._print_prompt() + + if self.pre_input_hook: + try: + self.pre_input_hook() + except: + print 'pre_input_hook failed' + traceback.print_exc() + self.pre_input_hook = None + + log("in readline: %s"%self.paste_line_buffer) + if len(self.paste_line_buffer)>0: + self.l_buffer=lineobj.ReadlineTextBuffer(self.paste_line_buffer[0]) + self._update_line() + self.paste_line_buffer=self.paste_line_buffer[1:] + c.write('\r\n') + else: + self._readline_from_keyboard() + c.write('\r\n') + + self.add_history(self.l_buffer.copy()) + + log('returning(%s)' % self.l_buffer.get_line_text()) + return self.l_buffer.get_line_text() + '\n' + + ### Methods below here are bindable emacs functions + + def beginning_of_line(self, e): # (C-a) + '''Move to the start of the current line. ''' + self.l_buffer.beginning_of_line() + + def end_of_line(self, e): # (C-e) + '''Move to the end of the line. ''' + self.l_buffer.end_of_line() + + def forward_char(self, e): # (C-f) + '''Move forward a character. ''' + self.l_buffer.forward_char() + + def backward_char(self, e): # (C-b) + '''Move back a character. ''' + self.l_buffer.backward_char() + + def forward_word(self, e): # (M-f) + '''Move forward to the end of the next word. Words are composed of + letters and digits.''' + self.l_buffer.forward_word() + + def backward_word(self, e): # (M-b) + '''Move back to the start of the current or previous word. Words are + composed of letters and digits.''' + self.l_buffer.backward_word() + + def clear_screen(self, e): # (C-l) + '''Clear the screen and redraw the current line, leaving the current + line at the top of the screen.''' + self.console.page() + + def redraw_current_line(self, e): # () + '''Refresh the current line. By default, this is unbound.''' + pass + + def accept_line(self, e): # (Newline or Return) + '''Accept the line regardless of where the cursor is. If this line + is non-empty, it may be added to the history list for future recall + with add_history(). If this line is a modified history line, the + history line is restored to its original state.''' + return True + +######### History commands + def previous_history(self, e): # (C-p) + '''Move back through the history list, fetching the previous command. ''' + self._history.previous_history(self.l_buffer) + + def next_history(self, e): # (C-n) + '''Move forward through the history list, fetching the next command. ''' + self._history.next_history(self.l_buffer) + + def beginning_of_history(self, e): # (M-<) + '''Move to the first line in the history.''' + self._history.beginning_of_history() + + def end_of_history(self, e): # (M->) + '''Move to the end of the input history, i.e., the line currently + being entered.''' + self._history.end_of_history(self.l_buffer) + + def _i_search(self, searchfun, direction, init_event): + c = self.console + line = self.get_line_buffer() + query = '' + hc_start = self._history.history_cursor #+ direction + while 1: + x, y = self.prompt_end_pos + c.pos(0, y) + if direction < 0: + prompt = 'reverse-i-search' + else: + prompt = 'forward-i-search' + + scroll = c.write_scrolling("%s`%s': %s" % (prompt, query, line)) + self._update_prompt_pos(scroll) + self._clear_after() + + event = c.getkeypress() + if event.keysym == 'BackSpace': + if len(query) > 0: + query = query[:-1] + self._history.history_cursor = hc_start + else: + self._bell() + elif event.char in string.letters + string.digits + string.punctuation + ' ': + self._history.history_cursor = hc_start + query += event.char + elif event.keyinfo == init_event.keyinfo: + self._history.history_cursor += direction + line=searchfun(query) + pass + else: + if event.keysym != 'Return': + self._bell() + break + line=searchfun(query) + + px, py = self.prompt_begin_pos + c.pos(0, py) + self.l_buffer.set_line(line) + self._print_prompt() + self._history.history_cursor=len(self._history.history) + + def reverse_search_history(self, e): # (C-r) + '''Search backward starting at the current line and moving up + through the history as necessary. This is an incremental search.''' +# print "HEJ" +# self.console.bell() + self._i_search(self._history.reverse_search_history, -1, e) + + def forward_search_history(self, e): # (C-s) + '''Search forward starting at the current line and moving down + through the the history as necessary. This is an incremental search.''' +# print "HEJ" +# self.console.bell() + self._i_search(self._history.forward_search_history, 1, e) + + + def non_incremental_reverse_search_history(self, e): # (M-p) + '''Search backward starting at the current line and moving up + through the history as necessary using a non-incremental search for + a string supplied by the user.''' + self._history.non_incremental_reverse_search_history(self.l_buffer) + + def non_incremental_forward_search_history(self, e): # (M-n) + '''Search forward starting at the current line and moving down + through the the history as necessary using a non-incremental search + for a string supplied by the user.''' + self._history.non_incremental_reverse_search_history(self.l_buffer) + + def history_search_forward(self, e): # () + '''Search forward through the history for the string of characters + between the start of the current line and the point. This is a + non-incremental search. By default, this command is unbound.''' + self.l_buffer=self._history.history_search_forward(self.l_buffer) + + def history_search_backward(self, e): # () + '''Search backward through the history for the string of characters + between the start of the current line and the point. This is a + non-incremental search. By default, this command is unbound.''' + self.l_buffer=self._history.history_search_backward(self.l_buffer) + + def yank_nth_arg(self, e): # (M-C-y) + '''Insert the first argument to the previous command (usually the + second word on the previous line) at point. With an argument n, + insert the nth word from the previous command (the words in the + previous command begin with word 0). A negative argument inserts the + nth word from the end of the previous command.''' + pass + + def yank_last_arg(self, e): # (M-. or M-_) + '''Insert last argument to the previous command (the last word of + the previous history entry). With an argument, behave exactly like + yank-nth-arg. Successive calls to yank-last-arg move back through + the history list, inserting the last argument of each line in turn.''' + pass + + def delete_char(self, e): # (C-d) + '''Delete the character at point. If point is at the beginning of + the line, there are no characters in the line, and the last + character typed was not bound to delete-char, then return EOF.''' + self.l_buffer.delete_char() + + def backward_delete_char(self, e): # (Rubout) + '''Delete the character behind the cursor. A numeric argument means + to kill the characters instead of deleting them.''' + self.l_buffer.backward_delete_char() + + def forward_backward_delete_char(self, e): # () + '''Delete the character under the cursor, unless the cursor is at + the end of the line, in which case the character behind the cursor + is deleted. By default, this is not bound to a key.''' + pass + + def quoted_insert(self, e): # (C-q or C-v) + '''Add the next character typed to the line verbatim. This is how to + insert key sequences like C-q, for example.''' + e = self.console.getkeypress() + self.insert_text(e.char) + + def tab_insert(self, e): # (M-TAB) + '''Insert a tab character. ''' + ws = ' ' * (self.tabstop - (self.line_cursor%self.tabstop)) + self.insert_text(ws) + + def self_insert(self, e): # (a, b, A, 1, !, ...) + '''Insert yourself. ''' + if ord(e.char)!=0: #don't insert null character in buffer, can happen with dead keys. + self.insert_text(e.char) + + def transpose_chars(self, e): # (C-t) + '''Drag the character before the cursor forward over the character + at the cursor, moving the cursor forward as well. If the insertion + point is at the end of the line, then this transposes the last two + characters of the line. Negative arguments have no effect.''' + self.l_buffer.transpose_chars() + + def transpose_words(self, e): # (M-t) + '''Drag the word before point past the word after point, moving + point past that word as well. If the insertion point is at the end + of the line, this transposes the last two words on the line.''' + self.l_buffer.transpose_words() + + def upcase_word(self, e): # (M-u) + '''Uppercase the current (or following) word. With a negative + argument, uppercase the previous word, but do not move the cursor.''' + self.l_buffer.upcase_word() + + def downcase_word(self, e): # (M-l) + '''Lowercase the current (or following) word. With a negative + argument, lowercase the previous word, but do not move the cursor.''' + self.l_buffer.downcase_word() + + def capitalize_word(self, e): # (M-c) + '''Capitalize the current (or following) word. With a negative + argument, capitalize the previous word, but do not move the cursor.''' + self.l_buffer.capitalize_word() + + def overwrite_mode(self, e): # () + '''Toggle overwrite mode. With an explicit positive numeric + argument, switches to overwrite mode. With an explicit non-positive + numeric argument, switches to insert mode. This command affects only + emacs mode; vi mode does overwrite differently. Each call to + readline() starts in insert mode. In overwrite mode, characters + bound to self-insert replace the text at point rather than pushing + the text to the right. Characters bound to backward-delete-char + replace the character before point with a space.''' + pass + + def kill_line(self, e): # (C-k) + '''Kill the text from point to the end of the line. ''' + self.l_buffer.kill_line() + + def backward_kill_line(self, e): # (C-x Rubout) + '''Kill backward to the beginning of the line. ''' + self.l_buffer.backward_kill_line() + + def unix_line_discard(self, e): # (C-u) + '''Kill backward from the cursor to the beginning of the current line. ''' + # how is this different from backward_kill_line? + self.l_buffer.unix_line_discard() + + def kill_whole_line(self, e): # () + '''Kill all characters on the current line, no matter where point + is. By default, this is unbound.''' + self.l_buffer.kill_whole_line() + + def kill_word(self, e): # (M-d) + '''Kill from point to the end of the current word, or if between + words, to the end of the next word. Word boundaries are the same as + forward-word.''' + self.l_buffer.kill_word() + + def backward_kill_word(self, e): # (M-DEL) + '''Kill the word behind point. Word boundaries are the same as + backward-word. ''' + self.l_buffer.backward_kill_word() + + def unix_word_rubout(self, e): # (C-w) + '''Kill the word behind point, using white space as a word + boundary. The killed text is saved on the kill-ring.''' + self.l_buffer.unix_word_rubout() + + def delete_horizontal_space(self, e): # () + '''Delete all spaces and tabs around point. By default, this is unbound. ''' + pass + + def kill_region(self, e): # () + '''Kill the text in the current region. By default, this command is unbound. ''' + pass + + def copy_region_as_kill(self, e): # () + '''Copy the text in the region to the kill buffer, so it can be + yanked right away. By default, this command is unbound.''' + pass + + def copy_region_to_clipboard(self, e): # () + '''Copy the text in the region to the windows clipboard.''' + if self.enable_win32_clipboard: + mark=min(self.l_buffer.mark,len(self.l_buffer.line_buffer)) + cursor=min(self.l_buffer.point,len(self.l_buffer.line_buffer)) + if self.l_buffer.mark==-1: + return + begin=min(cursor,mark) + end=max(cursor,mark) + toclipboard="".join(self.l_buffer.line_buffer[begin:end]) + clipboard.SetClipboardText(str(toclipboard)) + + def copy_backward_word(self, e): # () + '''Copy the word before point to the kill buffer. The word + boundaries are the same as backward-word. By default, this command + is unbound.''' + pass + + def copy_forward_word(self, e): # () + '''Copy the word following point to the kill buffer. The word + boundaries are the same as forward-word. By default, this command is + unbound.''' + pass + + def paste(self,e): + '''Paste windows clipboard''' + if self.enable_win32_clipboard: + txt=clipboard.get_clipboard_text_and_convert(False) + self.insert_text(txt) + + def paste_mulitline_code(self,e): + '''Paste windows clipboard''' + reg=re.compile("\r?\n") + if self.enable_win32_clipboard: + txt=clipboard.get_clipboard_text_and_convert(False) + t=reg.split(txt) + t=[row for row in t if row.strip()!=""] #remove empty lines + if t!=[""]: + self.insert_text(t[0]) + self.add_history(self.l_buffer.copy()) + self.paste_line_buffer=t[1:] + log("multi: %s"%self.paste_line_buffer) + return True + else: + return False + + def ipython_paste(self,e): + '''Paste windows clipboard. If enable_ipython_paste_list_of_lists is + True then try to convert tabseparated data to repr of list of lists or + repr of array''' + if self.enable_win32_clipboard: + txt=clipboard.get_clipboard_text_and_convert( + self.enable_ipython_paste_list_of_lists) + if self.enable_ipython_paste_for_paths: + if len(txt)<300 and ("\t" not in txt) and ("\n" not in txt): + txt=txt.replace("\\","/").replace(" ",r"\ ") + self.insert_text(txt) + + def yank(self, e): # (C-y) + '''Yank the top of the kill ring into the buffer at point. ''' + pass + + def yank_pop(self, e): # (M-y) + '''Rotate the kill-ring, and yank the new top. You can only do this + if the prior command is yank or yank-pop.''' + pass + + + def digit_argument(self, e): # (M-0, M-1, ... M--) + '''Add this digit to the argument already accumulating, or start a + new argument. M-- starts a negative argument.''' + pass + + def universal_argument(self, e): # () + '''This is another way to specify an argument. If this command is + followed by one or more digits, optionally with a leading minus + sign, those digits define the argument. If the command is followed + by digits, executing universal-argument again ends the numeric + argument, but is otherwise ignored. As a special case, if this + command is immediately followed by a character that is neither a + digit or minus sign, the argument count for the next command is + multiplied by four. The argument count is initially one, so + executing this function the first time makes the argument count + four, a second time makes the argument count sixteen, and so on. By + default, this is not bound to a key.''' + pass + + def delete_char_or_list(self, e): # () + '''Deletes the character under the cursor if not at the beginning or + end of the line (like delete-char). If at the end of the line, + behaves identically to possible-completions. This command is unbound + by default.''' + pass + + def start_kbd_macro(self, e): # (C-x () + '''Begin saving the characters typed into the current keyboard macro. ''' + pass + + def end_kbd_macro(self, e): # (C-x )) + '''Stop saving the characters typed into the current keyboard macro + and save the definition.''' + pass + + def call_last_kbd_macro(self, e): # (C-x e) + '''Re-execute the last keyboard macro defined, by making the + characters in the macro appear as if typed at the keyboard.''' + pass + + def re_read_init_file(self, e): # (C-x C-r) + '''Read in the contents of the inputrc file, and incorporate any + bindings or variable assignments found there.''' + pass + + def abort(self, e): # (C-g) + '''Abort the current editing command and ring the terminals bell + (subject to the setting of bell-style).''' + self._bell() + + def do_uppercase_version(self, e): # (M-a, M-b, M-x, ...) + '''If the metafied character x is lowercase, run the command that is + bound to the corresponding uppercase character.''' + pass + + def prefix_meta(self, e): # (ESC) + '''Metafy the next character typed. This is for keyboards without a + meta key. Typing ESC f is equivalent to typing M-f. ''' + self.next_meta = True + + def undo(self, e): # (C-_ or C-x C-u) + '''Incremental undo, separately remembered for each line.''' + self.l_buffer.pop_undo() + + def revert_line(self, e): # (M-r) + '''Undo all changes made to this line. This is like executing the + undo command enough times to get back to the beginning.''' + pass + + def tilde_expand(self, e): # (M-~) + '''Perform tilde expansion on the current word.''' + pass + + def set_mark(self, e): # (C-@) + '''Set the mark to the point. If a numeric argument is supplied, the + mark is set to that position.''' + self.l_buffer.set_mark() + + def exchange_point_and_mark(self, e): # (C-x C-x) + '''Swap the point with the mark. The current cursor position is set + to the saved position, and the old cursor position is saved as the + mark.''' + pass + + def character_search(self, e): # (C-]) + '''A character is read and point is moved to the next occurrence of + that character. A negative count searches for previous occurrences.''' + pass + + def character_search_backward(self, e): # (M-C-]) + '''A character is read and point is moved to the previous occurrence + of that character. A negative count searches for subsequent + occurrences.''' + pass + + def insert_comment(self, e): # (M-#) + '''Without a numeric argument, the value of the comment-begin + variable is inserted at the beginning of the current line. If a + numeric argument is supplied, this command acts as a toggle: if the + characters at the beginning of the line do not match the value of + comment-begin, the value is inserted, otherwise the characters in + comment-begin are deleted from the beginning of the line. In either + case, the line is accepted as if a newline had been typed.''' + pass + + def dump_functions(self, e): # () + '''Print all of the functions and their key bindings to the Readline + output stream. If a numeric argument is supplied, the output is + formatted in such a way that it can be made part of an inputrc + file. This command is unbound by default.''' + pass + + def dump_variables(self, e): # () + '''Print all of the settable variables and their values to the + Readline output stream. If a numeric argument is supplied, the + output is formatted in such a way that it can be made part of an + inputrc file. This command is unbound by default.''' + pass + + def dump_macros(self, e): # () + '''Print all of the Readline key sequences bound to macros and the + strings they output. If a numeric argument is supplied, the output + is formatted in such a way that it can be made part of an inputrc + file. This command is unbound by default.''' + pass + + + #Create key bindings: + + def init_editing_mode(self, e): # (C-e) + '''When in vi command mode, this causes a switch to emacs editing + mode.''' + + self._bind_exit_key('Control-d') + self._bind_exit_key('Control-z') + + # I often accidentally hold the shift or control while typing space + self._bind_key('Shift-space', self.self_insert) + self._bind_key('Control-space', self.self_insert) + self._bind_key('Return', self.accept_line) + self._bind_key('Left', self.backward_char) + self._bind_key('Control-b', self.backward_char) + self._bind_key('Right', self.forward_char) + self._bind_key('Control-f', self.forward_char) + self._bind_key('BackSpace', self.backward_delete_char) + self._bind_key('Home', self.beginning_of_line) + self._bind_key('End', self.end_of_line) + self._bind_key('Delete', self.delete_char) + self._bind_key('Control-d', self.delete_char) + self._bind_key('Clear', self.clear_screen) + + +# make it case insensitive +def commonprefix(m): + "Given a list of pathnames, returns the longest common leading component" + if not m: return '' + prefix = m[0] + for item in m: + for i in range(len(prefix)): + if prefix[:i+1].lower() != item[:i+1].lower(): + prefix = prefix[:i] + if i == 0: return '' + break + return prefix + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/modes/vi.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/modes/vi.py new file mode 100644 index 0000000..5542fda --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/modes/vi.py @@ -0,0 +1,1219 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2003-2006 Gary Bishop. +# Copyright (C) 2006 Michael Graz. +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +import os +import pyreadline.logger as logger +from pyreadline.logger import log,log_sock +import pyreadline.lineeditor.lineobj as lineobj +import pyreadline.lineeditor.history as history +import basemode + +class ViMode(basemode.BaseMode): + mode="vi" + def __init__(self,rlobj): + super(ViMode,self).__init__(rlobj) + self.__vi_insert_mode = None + + def __repr__(self): + return "" + + def _readline_from_keyboard(self): + c=self.console + while 1: + self._update_line() + event = c.getkeypress() + if self.next_meta: + self.next_meta = False + control, meta, shift, code = event.keyinfo + event.keyinfo = (control, True, shift, code) + + #Process exit keys. Only exit on empty line + if event.keyinfo in self.exit_dispatch: + if lineobj.EndOfLine(self.l_buffer) == 0: + raise EOFError + + dispatch_func = self.key_dispatch.get(event.keyinfo.tuple(),self.vi_key) + log("readline from keyboard:%s->%s"%(event.keyinfo.tuple(),dispatch_func)) + r = None + if dispatch_func: + r = dispatch_func(event) + self.l_buffer.push_undo() + + self.previous_func = dispatch_func + if r: + self._update_line() + break + + def readline(self, prompt=''): + '''Try to act like GNU readline.''' + # handle startup_hook + if self.first_prompt: + self.first_prompt = False + if self.startup_hook: + try: + self.startup_hook() + except: + print 'startup hook failed' + traceback.print_exc() + + c = self.console + self.l_buffer.reset_line() + self.prompt = prompt + self._print_prompt() + + if self.pre_input_hook: + try: + self.pre_input_hook() + except: + print 'pre_input_hook failed' + traceback.print_exc() + self.pre_input_hook = None + + log("in readline: %s"%self.paste_line_buffer) + if len(self.paste_line_buffer)>0: + self.l_buffer=lineobj.ReadlineTextBuffer(self.paste_line_buffer[0]) + self._update_line() + self.paste_line_buffer=self.paste_line_buffer[1:] + c.write('\r\n') + else: + self._readline_from_keyboard() + c.write('\r\n') + + self.add_history(self.l_buffer.copy()) + + log('returning(%s)' % self.l_buffer.get_line_text()) + return self.l_buffer.get_line_text() + '\n' + + ### Methods below here are bindable emacs functions + + def init_editing_mode(self, e): # (M-C-j) + '''Initialize vi editingmode''' + self.show_all_if_ambiguous = 'on' + self.key_dispatch = {} + self.__vi_insert_mode = None + self._vi_command = None + self._vi_command_edit = None + self._vi_key_find_char = None + self._vi_key_find_direction = True + self._vi_yank_buffer = None + self._vi_multiplier1 = '' + self._vi_multiplier2 = '' + self._vi_undo_stack = [] + self._vi_undo_cursor = -1 + self._vi_current = None + self._vi_search_text = '' + self.vi_save_line () + self.vi_set_insert_mode (True) + # make ' ' to ~ self insert + for c in range(ord(' '), 127): + self._bind_key('%s' % chr(c), self.vi_key) + self._bind_key('BackSpace', self.vi_backspace) + self._bind_key('Escape', self.vi_escape) + self._bind_key('Return', self.vi_accept_line) + + self._bind_key('Left', self.backward_char) + self._bind_key('Right', self.forward_char) + self._bind_key('Home', self.beginning_of_line) + self._bind_key('End', self.end_of_line) + self._bind_key('Delete', self.delete_char) + + self._bind_key('Control-d', self.vi_eof) + self._bind_key('Control-z', self.vi_eof) + self._bind_key('Control-r', self.vi_redo) + self._bind_key('Up', self.vi_arrow_up) + self._bind_key('Control-p', self.vi_up) + self._bind_key('Down', self.vi_arrow_down) + self._bind_key('Control-n', self.vi_down) + self._bind_key('Tab', self.vi_complete) +# self._bind_key('Control-e', self.emacs) + + def vi_key (self, e): + if not self._vi_command: + self._vi_command = ViCommand (self) + elif self._vi_command.is_end: + if self._vi_command.is_edit: + self._vi_command_edit = self._vi_command + self._vi_command = ViCommand (self) + self._vi_command.add_char (e.char) + + def vi_error (self): + self._bell () + + def vi_get_is_insert_mode (self): + return self.__vi_insert_mode + vi_is_insert_mode = property (vi_get_is_insert_mode) + + def vi_escape (self, e): + if self.vi_is_insert_mode: + if self._vi_command: + self._vi_command.add_char (e.char) + else: + self._vi_command = ViCommand (self) + self.vi_set_insert_mode (False) +# if self.line_cursor > 0: +# self.line_cursor -= 1 + self.l_buffer.point=lineobj.PrevChar + elif self._vi_command and self._vi_command.is_replace_one: + self._vi_command.add_char (e.char) + else: + self.vi_error () + + def vi_backspace (self, e): + if self._vi_command: + self._vi_command.add_char (e.char) + else: + self._vi_do_backspace (self._vi_command) + + def _vi_do_backspace (self, vi_cmd): + if self.vi_is_insert_mode or (self._vi_command and self._vi_command.is_search): + if self.l_buffer.point > 0: + self.l_buffer.point -= 1 + if self.l_buffer.overwrite: + try: + prev = self._vi_undo_stack [self._vi_undo_cursor][1][self.l_buffer.point ] + self.l_buffer.line_buffer [self.l_buffer.point] = prev + except IndexError: + del self.l_buffer.line_buffer [self.l_buffer.point ] + else: + self.vi_save_line () + del self.l_buffer.line_buffer [self.l_buffer.point ] + + def vi_accept_line (self, e): + if self._vi_command and self._vi_command.is_search: + self._vi_command.do_search () + return False + self._vi_command = None + self.vi_set_insert_mode (True) + self._vi_undo_stack = [] + self._vi_undo_cursor = -1 + self._vi_current = None + return self.accept_line (e) + + def vi_eof (self, e): + raise EOFError + + def vi_set_insert_mode (self, value): + if self.__vi_insert_mode == value: + return + self.__vi_insert_mode = value + if value: + self.vi_save_line () + self.console.cursor (size=25) + else: + self.console.cursor (size=100) + + def vi_undo_restart (self): + tpl_undo = (self.l_buffer.point, self.l_buffer.line_buffer[:], ) + self._vi_undo_stack = [tpl_undo] + self._vi_undo_cursor = 0 + + def vi_save_line (self): + if self._vi_undo_stack and self._vi_undo_cursor >= 0: + del self._vi_undo_stack [self._vi_undo_cursor + 1 : ] + # tpl_undo = (self.l_buffer.point, self.l_buffer[:], ) + tpl_undo = (self.l_buffer.point, self.l_buffer.line_buffer[:], ) + if not self._vi_undo_stack or self._vi_undo_stack[self._vi_undo_cursor][1] != tpl_undo[1]: + self._vi_undo_stack.append (tpl_undo) + self._vi_undo_cursor += 1 + + def vi_undo_prepare (self): + if self._vi_undo_cursor == len(self._vi_undo_stack)-1: + self.vi_save_line () + + def vi_undo (self, do_pop=True): + self.vi_undo_prepare () + if not self._vi_undo_stack or self._vi_undo_cursor <= 0: + self.vi_error () + return + self._vi_undo_cursor -= 1 + self.vi_undo_assign () + + def vi_undo_all (self): + self.vi_undo_prepare () + if self._vi_undo_cursor > 0: + self._vi_undo_cursor = 0 + self.vi_undo_assign () + else: + self.vi_error () + + def vi_undo_assign (self): + tpl_undo = self._vi_undo_stack [self._vi_undo_cursor] + self.l_buffer.line_buffer = tpl_undo [1][:] + self.l_buffer.point = tpl_undo [0] + + def vi_redo (self, e): + if self._vi_undo_cursor >= len(self._vi_undo_stack)-1: + self.vi_error () + return + self._vi_undo_cursor += 1 + self.vi_undo_assign () + + def vi_search (self, rng): + for i in rng: + line_history = self._history.history [i] + pos = line_history.get_line_text().find (self._vi_search_text) + if pos >= 0: + self._history.history_cursor = i + self.l_buffer.line_buffer = list (line_history.line_buffer) + self.l_buffer.point = pos + self.vi_undo_restart () + return True + self._bell () + return False + + def vi_search_first (self): + text = ''.join (self.l_buffer.line_buffer [1:]) + if text: + self._vi_search_text = text + position = len (self._history.history) - 1 + elif self._vi_search_text: + position = self._history.history_cursor - 1 + else: + self.vi_error () + self.vi_undo () + return + if not self.vi_search (range (position, -1, -1)): + # Here: search text not found + self.vi_undo () + + def vi_search_again_backward (self): + self.vi_search (range (self._history.history_cursor-1, -1, -1)) + + def vi_search_again_forward (self): + self.vi_search (range (self._history.history_cursor+1, len(self._history.history))) + + def vi_up (self, e): + if self._history.history_cursor == len(self._history.history): + self._vi_current = self.l_buffer.line_buffer [:] + # self._history.previous_history (e) + self._history.previous_history (self.l_buffer) + if self.vi_is_insert_mode: + self.end_of_line (e) + else: + self.beginning_of_line (e) + self.vi_undo_restart () + + def vi_down (self, e): + if self._history.history_cursor >= len(self._history.history): + self.vi_error () + return + if self._history.history_cursor < len(self._history.history) - 1: + # self._history.next_history (e) + self._history.next_history (self.l_buffer) + if self.vi_is_insert_mode: + self.end_of_line (e) + else: + self.beginning_of_line (e) + self.vi_undo_restart () + elif self._vi_current is not None: + self._history.history_cursor = len(self._history.history) + self.l_buffer.line_buffer = self._vi_current + self.end_of_line (e) + if not self.vi_is_insert_mode and self.l_buffer.point > 0: + self.l_buffer.point -= 1 + self._vi_current = None + else: + self.vi_error () + return + + def vi_arrow_up (self, e): + self.vi_set_insert_mode (True) + self.vi_up (e) + self.vi_save_line () + + def vi_arrow_down (self, e): + self.vi_set_insert_mode (True) + self.vi_down (e) + self.vi_save_line () + + def vi_complete (self, e): + text = self.l_buffer.get_line_text () + if text and not text.isspace (): + return self.complete (e) + else: + return self.vi_key (e) + +# vi input states +# sequence of possible states are in the order below +_VI_BEGIN = 'vi_begin' +_VI_MULTI1 = 'vi_multi1' +_VI_ACTION = 'vi_action' +_VI_MULTI2 = 'vi_multi2' +_VI_MOTION = 'vi_motion' +_VI_MOTION_ARGUMENT = 'vi_motion_argument' +_VI_REPLACE_ONE = 'vi_replace_one' +_VI_TEXT = 'vi_text' +_VI_SEARCH = 'vi_search' +_VI_END = 'vi_end' + +# vi helper class +class ViCommand: + def __init__ (self, readline): + self.readline = readline + self.lst_char = [] + self.state = _VI_BEGIN + self.action = self.movement + self.motion = None + self.motion_argument = None + self.text = None + self.pos_motion = None + self.is_edit = False + self.is_overwrite = False + self.is_error = False + self.is_star = False + self.delete_left = 0 + self.delete_right = 0 + self.readline._vi_multiplier1 = '' + self.readline._vi_multiplier2 = '' + self.set_override_multiplier (0) + self.skip_multipler = False + self.dct_fcn = { + ord('$') : self.key_dollar, + ord('^') : self.key_hat, + ord(';') : self.key_semicolon, + ord(',') : self.key_comma, + ord('%') : self.key_percent, + ord('.') : self.key_dot, + ord('/') : self.key_slash, + ord('*') : self.key_star, + ord('|') : self.key_bar, + ord('~') : self.key_tilde, + 8 : self.key_backspace, + } + + def add_char (self, char): + self.lst_char.append (char) + if self.state == _VI_BEGIN and self.readline.vi_is_insert_mode: + self.readline.vi_save_line () + self.state = _VI_TEXT + if self.state == _VI_SEARCH: + if char == '\x08': # backspace + self.key_backspace (char) + else: + self.set_text (char) + return + if self.state == _VI_TEXT: + if char == '\x1b': # escape + self.escape (char) + elif char == '\x09': # tab + ts = self.readline.tabstop + ws = ' ' * (ts - (self.readline.l_buffer.point%ts)) + self.set_text (ws) + elif char == '\x08': # backspace + self.key_backspace (char) + else: + self.set_text (char) + return + if self.state == _VI_MOTION_ARGUMENT: + self.set_motion_argument (char) + return + if self.state == _VI_REPLACE_ONE: + self.replace_one (char) + return + try: + fcn_instance = self.dct_fcn [ord(char)] + except: + fcn_instance = getattr (self, 'key_%s' % char, None) + if fcn_instance: + fcn_instance (char) + return + if char.isdigit (): + self.key_digit (char) + return + # Here: could not process key + self.error () + + def set_text (self, text): + if self.text is None: + self.text = text + else: + self.text += text + self.set_buffer (text) + + def set_buffer (self, text): + for char in text: + if not self.char_isprint (char): + continue +# self.readline.l_buffer.insert_text(char) +# continue +# #overwrite in l_buffer obj + if self.is_overwrite: + if self.readline.l_buffer.point < len (self.readline.l_buffer.line_buffer): + # self.readline.l_buffer[self.l_buffer.point]=char + self.readline.l_buffer.line_buffer [self.readline.l_buffer.point] = char + else: + # self.readline.l_buffer.insert_text(char) + self.readline.l_buffer.line_buffer.append (char) + else: + # self.readline.l_buffer.insert_text(char) + self.readline.l_buffer.line_buffer.insert (self.readline.l_buffer.point, char) + self.readline.l_buffer.point += 1 + + def replace_one (self, char): + if char == '\x1b': # escape + self.end () + return + self.is_edit = True + self.readline.vi_save_line () + times = self.get_multiplier () + cursor = self.readline.l_buffer.point + self.readline.l_buffer.line_buffer [cursor : cursor + times] = char * times + if times > 1: + self.readline.l_buffer.point += (times - 1) + self.end () + + def char_isprint (self, char): + return ord(char) >= ord(' ') and ord(char) <= ord('~') + + def key_dollar (self, char): + self.motion = self.motion_end_in_line + self.delete_right = 1 + self.state = _VI_MOTION + self.apply () + + def key_hat (self, char): + self.motion = self.motion_beginning_of_line + self.state = _VI_MOTION + self.apply () + + def key_0 (self, char): + if self.state in [_VI_BEGIN, _VI_ACTION]: + self.key_hat (char) + else: + self.key_digit (char) + + def key_digit (self, char): + if self.state in [_VI_BEGIN, _VI_MULTI1]: + self.readline._vi_multiplier1 += char + self.readline._vi_multiplier2 = '' + self.state = _VI_MULTI1 + elif self.state in [_VI_ACTION, _VI_MULTI2]: + self.readline._vi_multiplier2 += char + self.state = _VI_MULTI2 + + def key_w (self, char): + if self.action == self.change: + self.key_e (char) + return + self.motion = self.motion_word_short + self.state = _VI_MOTION + self.apply () + + def key_W (self, char): + if self.action == self.change: + self.key_E (char) + return + self.motion = self.motion_word_long + self.state = _VI_MOTION + self.apply () + + def key_e (self, char): + self.motion = self.motion_end_short + self.state = _VI_MOTION + self.delete_right = 1 + self.apply () + + def key_E (self, char): + self.motion = self.motion_end_long + self.state = _VI_MOTION + self.delete_right = 1 + self.apply () + + def key_b (self, char): + self.motion = self.motion_back_short + self.state = _VI_MOTION + self.apply () + + def key_B (self, char): + self.motion = self.motion_back_long + self.state = _VI_MOTION + self.apply () + + def key_f (self, char): + self.readline._vi_key_find_direction = True + self.motion = self.motion_find_char_forward + self.delete_right = 1 + self.state = _VI_MOTION_ARGUMENT + + def key_F (self, char): + self.readline._vi_key_find_direction = False + self.motion = self.motion_find_char_backward + self.delete_left = 1 + self.state = _VI_MOTION_ARGUMENT + + def key_t (self, char): + self.motion = self.motion_to_char_forward + self.delete_right = 1 + self.state = _VI_MOTION_ARGUMENT + + def key_T (self, char): + self.motion = self.motion_to_char_backward + self.state = _VI_MOTION_ARGUMENT + + def key_j (self, char): + self.readline.vi_down (ViEvent (char)) + self.state = _VI_END + + def key_k (self, char): + self.readline.vi_up (ViEvent (char)) + self.state = _VI_END + + def key_semicolon (self, char): + if self.readline._vi_key_find_char is None: + self.error () + return + if self.readline._vi_key_find_direction: + self.motion = self.motion_find_char_forward + else: + self.motion = self.motion_find_char_backward + self.set_motion_argument (self.readline._vi_key_find_char) + + def key_comma (self, char): + if self.readline._vi_key_find_char is None: + self.error () + return + if self.readline._vi_key_find_direction: + self.motion = self.motion_find_char_backward + else: + self.motion = self.motion_find_char_forward + self.set_motion_argument (self.readline._vi_key_find_char) + + def key_percent (self, char): + '''find matching <([{}])>''' + self.motion = self.motion_matching + self.delete_right = 1 + self.state = _VI_MOTION + self.apply () + + def key_dot (self, char): + vi_cmd_edit = self.readline._vi_command_edit + if not vi_cmd_edit: + return + if vi_cmd_edit.is_star: + self.key_star (char) + return + if self.has_multiplier (): + count = self.get_multiplier () + else: + count = 0 + # Create the ViCommand object after getting multipler from self + # Side effect of the ViCommand creation is resetting of global multipliers + vi_cmd = ViCommand (self.readline) + if count >= 1: + vi_cmd.set_override_multiplier (count) + vi_cmd_edit.set_override_multiplier (count) + elif vi_cmd_edit.override_multiplier: + vi_cmd.set_override_multiplier (vi_cmd_edit.override_multiplier) + for char in vi_cmd_edit.lst_char: + vi_cmd.add_char (char) + if vi_cmd_edit.is_overwrite and self.readline.l_buffer.point > 0: + self.readline.l_buffer.point -= 1 + self.readline.vi_set_insert_mode (False) + self.end () + + def key_slash (self, char): + self.readline.vi_save_line () + self.readline.l_buffer.line_buffer=['/'] + self.readline.l_buffer.point= 1 + self.state = _VI_SEARCH + + def key_star (self, char): + self.is_star = True + self.is_edit = True + self.readline.vi_save_line () + completions = self.readline._get_completions() + if completions: + text = ' '.join (completions) + ' ' + self.readline.l_buffer.line_buffer [self.readline.begidx : self.readline.endidx + 1] = list (text) + prefix_len = self.readline.endidx - self.readline.begidx + self.readline.l_buffer.point += len(text) - prefix_len + self.readline.vi_set_insert_mode (True) + else: + self.error () + self.state = _VI_TEXT + + def key_bar (self, char): + self.motion = self.motion_column + self.state = _VI_MOTION + self.apply () + + def key_tilde (self, char): + self.is_edit = True + self.readline.vi_save_line () + for i in range (self.get_multiplier()): + try: + c = self.readline.l_buffer.line_buffer [self.readline.l_buffer.point] + if c.isupper (): + self.readline.l_buffer.line_buffer [self.readline.l_buffer.point] = c.lower() + elif c.islower (): + self.readline.l_buffer.line_buffer [self.readline.l_buffer.point] = c.upper() + self.readline.l_buffer.point += 1 + except IndexError: + break + self.end () + + def key_h (self, char): + self.motion = self.motion_left + self.state = _VI_MOTION + self.apply () + + def key_backspace (self, char): + if self.state in [_VI_TEXT, _VI_SEARCH]: + if self.text and len(self.text): + self.text = self.text [:-1] + try: + # Remove backspaces for potential dot command + self.lst_char.pop () + self.lst_char.pop () + except IndexError: + pass + else: + self.key_h (char) + self.readline._vi_do_backspace (self) + if self.state == _VI_SEARCH and not (self.readline.l_buffer.line_buffer): + self.state = _VI_BEGIN + + def key_l (self, char): + self.motion = self.motion_right + self.state = _VI_MOTION + self.apply () + + def key_i (self, char): + self.is_edit = True + self.state = _VI_TEXT + self.readline.vi_set_insert_mode (True) + + def key_I (self, char): + self.is_edit = True + self.state = _VI_TEXT + self.readline.vi_set_insert_mode (True) + self.readline.l_buffer.point = 0 + + def key_a (self, char): + self.is_edit = True + self.state = _VI_TEXT + self.readline.vi_set_insert_mode (True) + if len (self.readline.l_buffer.line_buffer): + self.readline.l_buffer.point += 1 + + def key_A (self, char): + self.is_edit = True + self.state = _VI_TEXT + self.readline.vi_set_insert_mode (True) + self.readline.l_buffer.point = len (self.readline.l_buffer.line_buffer) + + def key_d (self, char): + self.is_edit = True + self.state = _VI_ACTION + self.action = self.delete + + def key_D (self, char): + self.is_edit = True + self.state = _VI_ACTION + self.action = self.delete_end_of_line + self.apply () + + def key_x (self, char): + self.is_edit = True + self.state = _VI_ACTION + self.action = self.delete_char + self.apply () + + def key_X (self, char): + self.is_edit = True + self.state = _VI_ACTION + self.action = self.delete_prev_char + self.apply () + + def key_s (self, char): + self.is_edit = True + i1 = self.readline.l_buffer.point + i2 = self.readline.l_buffer.point + self.get_multiplier () + self.skip_multipler = True + self.readline.vi_set_insert_mode (True) + del self.readline.l_buffer.line_buffer [i1 : i2] + self.state = _VI_TEXT + + def key_S (self, char): + self.is_edit = True + self.readline.vi_set_insert_mode (True) + self.readline.l_buffer.line_buffer = [] + self.readline.l_buffer.point = 0 + self.state = _VI_TEXT + + def key_c (self, char): + self.is_edit = True + self.state = _VI_ACTION + self.action = self.change + + def key_C (self, char): + self.is_edit = True + self.readline.vi_set_insert_mode (True) + del self.readline.l_buffer.line_buffer [self.readline.l_buffer.point : ] + self.state = _VI_TEXT + + def key_r (self, char): + self.state = _VI_REPLACE_ONE + + def key_R (self, char): + self.is_edit = True + self.is_overwrite = True + self.readline.l_buffer.overwrite=True + self.readline.vi_set_insert_mode (True) + self.state = _VI_TEXT + + def key_y (self, char): + self._state = _VI_ACTION + self.action = self.yank + + def key_Y (self, char): + self.readline._vi_yank_buffer = self.readline.l_buffer.get_line_text() + self.end () + + def key_p (self, char): + if not self.readline._vi_yank_buffer: + return + self.is_edit = True + self.readline.vi_save_line () + self.readline.l_buffer.point += 1 + self.readline.l_buffer.insert_text (self.readline._vi_yank_buffer * self.get_multiplier ()) + self.readline.l_buffer.point -= 1 + self.state = _VI_END + + def key_P (self, char): + if not self.readline._vi_yank_buffer: + return + self.is_edit = True + self.readline.vi_save_line () + self.readline.l_buffer.insert_text (self.readline._vi_yank_buffer * self.get_multiplier ()) + self.readline.l_buffer.point -= 1 + self.state = _VI_END + + def key_u (self, char): + self.readline.vi_undo () + self.state = _VI_END + + def key_U (self, char): + self.readline.vi_undo_all () + self.state = _VI_END + + def key_v (self, char): + editor = ViExternalEditor (self.readline.l_buffer.line_buffer) + self.readline.l_buffer.line_buffer = list (editor.result) + self.readline.l_buffer.point = 0 + self.is_edit = True + self.state = _VI_END + + def error (self): + self.readline._bell () + self.is_error = True + + def state_is_end (self): + return self.state == _VI_END + is_end = property (state_is_end) + + def state_is_search (self): + return self.state == _VI_SEARCH + is_search = property (state_is_search) + + def state_is_replace_one (self): + return self.state == _VI_REPLACE_ONE + is_replace_one = property (state_is_replace_one) + + def do_search (self): + self.readline.vi_search_first () + self.state = _VI_END + + def key_n (self, char): + self.readline.vi_search_again_backward () + self.state = _VI_END + + def key_N (self, char): + self.readline.vi_search_again_forward () + self.state = _VI_END + + def motion_beginning_of_line (self, line, index=0, count=1, **kw): + return 0 + + def motion_end_in_line (self, line, index=0, count=1, **kw): + return max (0, len (self.readline.l_buffer.line_buffer)-1) + + def motion_word_short (self, line, index=0, count=1, **kw): + return vi_pos_word_short (line, index, count) + + def motion_word_long (self, line, index=0, count=1, **kw): + return vi_pos_word_long (line, index, count) + + def motion_end_short (self, line, index=0, count=1, **kw): + return vi_pos_end_short (line, index, count) + + def motion_end_long (self, line, index=0, count=1, **kw): + return vi_pos_end_long (line, index, count) + + def motion_back_short (self, line, index=0, count=1, **kw): + return vi_pos_back_short (line, index, count) + + def motion_back_long (self, line, index=0, count=1, **kw): + return vi_pos_back_long (line, index, count) + + def motion_find_char_forward (self, line, index=0, count=1, char=None): + self.readline._vi_key_find_char = char + return vi_pos_find_char_forward (line, char, index, count) + + def motion_find_char_backward (self, line, index=0, count=1, char=None): + self.readline._vi_key_find_char = char + return vi_pos_find_char_backward (line, char, index, count) + + def motion_to_char_forward (self, line, index=0, count=1, char=None): + return vi_pos_to_char_forward (line, char, index, count) + + def motion_to_char_backward (self, line, index=0, count=1, char=None): + return vi_pos_to_char_backward (line, char, index, count) + + def motion_left (self, line, index=0, count=1, char=None): + return max (0, index - count) + + def motion_right (self, line, index=0, count=1, char=None): + return min (len(line), index + count) + + def motion_matching (self, line, index=0, count=1, char=None): + return vi_pos_matching (line, index) + + def motion_column (self, line, index=0, count=1, char=None): + return max (0, count-1) + + def has_multiplier (self): + return self.override_multiplier or self.readline._vi_multiplier1 or self.readline._vi_multiplier2 + + def get_multiplier (self): + if self.override_multiplier: + return int (self.override_multiplier) + if self.readline._vi_multiplier1 == '': m1 = 1 + else: m1 = int(self.readline._vi_multiplier1) + if self.readline._vi_multiplier2 == '': m2 = 1 + else: m2 = int(self.readline._vi_multiplier2) + return m1 * m2 + + def set_override_multiplier (self, count): + self.override_multiplier = count + + def apply (self): + if self.motion: + self.pos_motion = self.motion (self.readline.l_buffer.line_buffer, self.readline.l_buffer.point, + self.get_multiplier(), char=self.motion_argument) + if self.pos_motion < 0: + self.error () + return + self.action () + if self.state != _VI_TEXT: + self.end () + + def movement (self): + if self.pos_motion <= len(self.readline.l_buffer.line_buffer): + self.readline.l_buffer.point = self.pos_motion + else: + self.readline.l_buffer.point = len(self.readline.l_buffer.line_buffer) - 1 + + def yank (self): + if self.pos_motion > self.readline.l_buffer.point: + s = self.readline.l_buffer.line_buffer [self.readline.l_buffer.point : self.pos_motion + self.delete_right] + else: + index = max (0, self.pos_motion - self.delete_left) + s = self.readline.l_buffer.line_buffer [index : self.readline.l_buffer.point + self.delete_right] + self.readline._vi_yank_buffer = s + + def delete (self): + self.readline.vi_save_line () + self.yank () +# point=lineobj.Point(self.readline.l_buffer) +# pm=self.pos_motion +# del self.readline.l_buffer[point:pm] +# return + if self.pos_motion > self.readline.l_buffer.point: + del self.readline.l_buffer.line_buffer [self.readline.l_buffer.point : self.pos_motion + self.delete_right] + if self.readline.l_buffer.point > len (self.readline.l_buffer.line_buffer): + self.readline.l_buffer.point = len (self.readline.l_buffer.line_buffer) + else: + index = max (0, self.pos_motion - self.delete_left) + del self.readline.l_buffer.line_buffer [index : self.readline.l_buffer.point + self.delete_right] + self.readline.l_buffer.point = index + + def delete_end_of_line (self): + self.readline.vi_save_line () + # del self.readline.l_buffer [self.readline.l_buffer.point : ] + line_text = self.readline.l_buffer.get_line_text () + line_text = line_text [ : self.readline.l_buffer.point] + self.readline.l_buffer.set_line (line_text) + if self.readline.l_buffer.point > 0: + self.readline.l_buffer.point -= 1 + + def delete_char (self): +# point=lineobj.Point(self.readline.l_buffer) +# del self.readline.l_buffer[point:point+self.get_multiplier ()] +# return + self.pos_motion = self.readline.l_buffer.point + self.get_multiplier () + self.delete () + end = max (0, len (self.readline.l_buffer) - 1) + if self.readline.l_buffer.point > end: + self.readline.l_buffer.point = end + + def delete_prev_char (self): + self.pos_motion = self.readline.l_buffer.point - self.get_multiplier () + self.delete () + + def change (self): + self.readline.vi_set_insert_mode (True) + self.delete () + self.skip_multipler = True + self.state = _VI_TEXT + + def escape (self, char): + if self.state == _VI_TEXT: + if not self.skip_multipler: + times = self.get_multiplier () + if times > 1 and self.text: + extra = self.text * (times - 1) + self.set_buffer (extra) + self.state = _VI_END + + def set_motion_argument (self, char): + self.motion_argument = char + self.apply () + + def end (self): + self.state = _VI_END + if self.readline.l_buffer.point >= len(self.readline.l_buffer.line_buffer): + self.readline.l_buffer.point = max (0, len(self.readline.l_buffer.line_buffer) - 1) + +class ViExternalEditor: + def __init__ (self, line): + if type(line) is type([]): + line = ''.join (line) + file_tmp = self.get_tempfile () + fp_tmp = self.file_open (file_tmp, 'w') + fp_tmp.write (line) + fp_tmp.close () + self.run_editor (file_tmp) + fp_tmp = self.file_open (file_tmp, 'r') + self.result = fp_tmp.read () + fp_tmp.close () + self.file_remove (file_tmp) + + def get_tempfile (self): + import tempfile + return tempfile.mktemp (prefix='readline-', suffix='.py') + + def file_open (self, filename, mode): + return file (filename, mode) + + def file_remove (self, filename): + os.remove (filename) + + def get_editor (self): + try: + return os.environ ['EDITOR'] + except KeyError: + return 'notepad' # ouch + + def run_editor (self, filename): + cmd = '%s %s' % (self.get_editor(), filename, ) + self.run_command (cmd) + + def run_command (self, command): + os.system (command) + +class ViEvent: + def __init__ (self, char): + self.char = char + +# vi standalone functions +def vi_is_word (char): + log ('xx vi_is_word: type(%s), %s' % (type(char), char, )) + return char.isalpha() or char.isdigit() or char == '_' + +def vi_is_space (char): + return char.isspace () + +def vi_is_word_or_space (char): + return vi_is_word (char) or vi_is_space (char) + +def vi_pos_word_short (line, index=0, count=1): + try: + for i in range(count): + in_word = vi_is_word (line[index]) + if not in_word: + while not vi_is_word (line[index]): + index += 1 + else: + while vi_is_word (line[index]): + index += 1 + while vi_is_space (line[index]): + index += 1 + return index + except IndexError: + return len(line) + +def vi_pos_word_long (line, index=0, count=1): + try: + for i in range(count): + in_space = vi_is_space (line[index]) + if not in_space: + while not vi_is_space (line[index]): + index += 1 + while vi_is_space (line[index]): + index += 1 + return index + except IndexError: + return len(line) + +def vi_pos_end_short (line, index=0, count=1): + try: + for i in range(count): + index += 1 + while vi_is_space (line[index]): + index += 1 + in_word = vi_is_word (line[index]) + if not in_word: + while not vi_is_word_or_space (line[index]): + index += 1 + else: + while vi_is_word (line[index]): + index += 1 + return index - 1 + except IndexError: + return max (0, len(line)-1) + +def vi_pos_end_long (line, index=0, count=1): + try: + for i in range(count): + index += 1 + while vi_is_space (line[index]): + index += 1 + while not vi_is_space (line[index]): + index += 1 + return index - 1 + except IndexError: + return max (0, len(line)-1) + +class vi_list (list): + '''This is a list that cannot have a negative index''' + def __getitem__ (self, key): + try: + if int(key) < 0: + raise IndexError + except ValueError: + pass + return list.__getitem__ (self, key) + +def vi_pos_back_short (line, index=0, count=1): + line = vi_list (line) + try: + for i in range(count): + index -= 1 + while vi_is_space (line[index]): + index -= 1 + in_word = vi_is_word (line[index]) + if in_word: + while vi_is_word (line[index]): + index -= 1 + else: + while not vi_is_word_or_space (line[index]): + index -= 1 + return index + 1 + except IndexError: + return 0 + +def vi_pos_back_long (line, index=0, count=1): + line = vi_list (line) + try: + for i in range(count): + index -= 1 + while vi_is_space (line[index]): + index -= 1 + while not vi_is_space (line[index]): + index -= 1 + return index + 1 + except IndexError: + return 0 + +def vi_pos_find_char_forward (line, char, index=0, count=1): + try: + for i in range(count): + index += 1 + while line [index] != char: + index += 1 + return index + except IndexError: + return -1 + +def vi_pos_find_char_backward (line, char, index=0, count=1): + try: + for i in range(count): + index -= 1 + while 1: + if index < 0: + return -1 + if line[index] == char: + break + index -= 1 + return index + except IndexError: + return -1 + +def vi_pos_to_char_forward (line, char, index=0, count=1): + index = vi_pos_find_char_forward (line, char, index, count) + if index > 0: + return index - 1 + return index + +def vi_pos_to_char_backward (line, char, index=0, count=1): + index = vi_pos_find_char_backward (line, char, index, count) + if index >= 0: + return index + 1 + return index + +_vi_dct_matching = { + '<': ('>', +1), '>': ('<', -1), + '(': (')', +1), ')': ('(', -1), + '[': (']', +1), ']': ('[', -1), + '{': ('}', +1), '}': ('{', -1), +} + +def vi_pos_matching (line, index=0): + '''find matching <([{}])>''' + anchor = None + target = None + delta = 1 + count = 0 + try: + while 1: + if anchor is None: + # first find anchor + try: + target, delta = _vi_dct_matching [line [index]] + anchor = line [index] + count = 1 + except KeyError: + index += 1 + continue + else: + # Here the anchor has been found + # Need to get corresponding target + if index < 0: + return -1 + if line [index] == anchor: + count += 1 + elif line [index] == target: + count -= 1 + if count == 0: + return index + index += delta + except IndexError: + return -1 + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/release.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/release.py new file mode 100644 index 0000000..d913381 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/release.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- +"""Release data for the pyreadline project. + +$Id: release.py 2514 2007-07-19 17:01:31Z jstenar $""" + +#***************************************************************************** +# Copyright (C) 2006 Jorgen Stenarson. +# +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +# Name of the package for release purposes. This is the name which labels +# the tarballs and RPMs made by distutils, so it's best to lowercase it. +name = 'pyreadline' + +# For versions with substrings (like 0.6.16.svn), use an extra . to separate +# the new substring. We have to avoid using either dashes or underscores, +# because bdist_rpm does not accept dashes (an RPM) convention, and +# bdist_deb does not accept underscores (a Debian convention). + +branch = '' + +#version = '1.5.svn' +version = '1.5' + +revision = '$Revision: 2514 $' + +description = "A python implmementation of GNU readline." + +long_description = \ +""" +The pyreadline package is a python implementation of GNU readline functionality +it is based on the ctypes based UNC readline package by Gary Bishop. +It is not complete. It has been tested for use with windows 2000 and windows xp. + +Features: + * NEW: keyboard text selection and copy/paste + * Shift-arrowkeys for text selection + * Control-c can be used for copy activate with allow_ctrl_c(True) is config file + * Double tapping ctrl-c will raise a KeyboardInterrupt, use ctrl_c_tap_time_interval(x) + where x is your preferred tap time window, default 0.3 s. + * paste pastes first line of content on clipboard. + * ipython_paste, pastes tab-separated data as list of lists or numpy array if all data is numeric + * paste_mulitline_code pastes multi line code, removing any empty lines. + * Experimental support for ironpython. At this time Ironpython has to be patched for it to work. + + + The latest development version is always available at the IPython subversion + repository_. + +.. _repository: http://ipython.scipy.org/svn/ipython/pyreadline/trunk#egg=pyreadline-dev + """ + +license = 'BSD' + +authors = {'Jorgen' : ('Jorgen Stenarson','jorgen.stenarson@bostream.nu'), + 'Gary': ('Gary Bishop', ''), + 'Jack': ('Jack Trainor', ''), + } + +url = 'http://ipython.scipy.org/moin/PyReadline/Intro' + +download_url = '' + +platforms = ['Windows XP/2000/NT','Windows 95/98/ME'] + +keywords = ['readline','pyreadline'] + +classifiers = ['Development Status :: 4 - Beta', + 'Environment :: Console', + 'Operating System :: Microsoft :: Windows',] + + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/rlmain.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/rlmain.py new file mode 100644 index 0000000..7ca5705 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/rlmain.py @@ -0,0 +1,479 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2003-2006 Gary Bishop. +# Copyright (C) 2006 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +''' an attempt to implement readline for Python in Python using ctypes''' +import sys,os,re +from glob import glob + +import clipboard,logger,console +from logger import log,log_sock +from error import ReadlineError,GetSetError +from pyreadline.keysyms.common import make_KeyPress_from_keydescr + +import pyreadline.lineeditor.lineobj as lineobj +import pyreadline.lineeditor.history as history +import release + +from modes import editingmodes + +in_ironpython="IronPython" in sys.version +if in_ironpython:#ironpython does not provide a prompt string to readline + import System + default_prompt=">>> " +else: + default_prompt="" + import pdb + + +def quote_char(c): + if ord(c)>0: + return c + +def inword(buffer,point): + return buffer[point:point+1] in [A-Za-z0-9] + + +class Readline(object): + def __init__(self): + self.startup_hook = None + self.pre_input_hook = None + self.completer = None + self.completer_delims = " \t\n\"\\'`@$><=;|&{(" + self.console = console.Console() + self.size = self.console.size() + self.prompt_color = None + self.command_color = None + self.selection_color = self.console.saveattr<<4 + self.key_dispatch = {} + self.previous_func = None + self.first_prompt = True + self.next_meta = False # True to force meta on next character + self.tabstop = 4 + self.allow_ctrl_c=False + self.ctrl_c_tap_time_interval=0.3 + self.debug=False + + self.begidx = 0 + self.endidx = 0 + + # variables you can control with parse_and_bind + self.show_all_if_ambiguous = 'off' + self.mark_directories = 'on' + self.bell_style = 'none' + self.mark=-1 + self.l_buffer=lineobj.ReadLineTextBuffer("") + self._history=history.LineHistory() + + # this code needs to follow l_buffer and history creation + self.editingmodes=[mode(self) for mode in editingmodes] + for mode in self.editingmodes: + mode.init_editing_mode(None) + self.mode=self.editingmodes[0] + + self.read_inputrc() + log("\n".join(self.rl_settings_to_string())) + + #Paste settings + #assumes data on clipboard is path if shorter than 300 characters and doesn't contain \t or \n + #and replace \ with / for easier use in ipython + self.enable_ipython_paste_for_paths=True + + #automatically convert tabseparated data to list of lists or array constructors + self.enable_ipython_paste_list_of_lists=True + self.enable_win32_clipboard=True + + self.paste_line_buffer=[] + + #Below is for refactoring, raise errors when using old style attributes + #that should be refactored out + def _g(x): + def g(self): + raise GetSetError("GET %s"%x) + def s(self,q): + raise GetSetError("SET %s"%x) + return g,s + line_buffer=property(*_g("line_buffer")) + line_cursor=property(*_g("line_buffer")) + undo_stack =property(*_g("undo_stack")) # each entry is a tuple with cursor_position and line_text + history_length =property(*_g("history_length")) # each entry is a tuple with cursor_position and line_text + history =property(*_g("history")) # each entry is a tuple with cursor_position and line_text + history_cursor =property(*_g("history_cursor")) # each entry is a tuple with cursor_position and line_text + + +# To export as readline interface + + def parse_and_bind(self, string): + '''Parse and execute single line of a readline init file.''' + try: + log('parse_and_bind("%s")' % string) + if string.startswith('#'): + return + if string.startswith('set'): + m = re.compile(r'set\s+([-a-zA-Z0-9]+)\s+(.+)\s*$').match(string) + if m: + var_name = m.group(1) + val = m.group(2) + try: + setattr(self, var_name.replace('-','_'), val) + except AttributeError: + log('unknown var="%s" val="%s"' % (var_name, val)) + else: + log('bad set "%s"' % string) + return + m = re.compile(r'\s*(.+)\s*:\s*([-a-zA-Z]+)\s*$').match(string) + if m: + key = m.group(1) + func_name = m.group(2) + py_name = func_name.replace('-', '_') + try: + func = getattr(self.mode, py_name) + except AttributeError: + log('unknown func key="%s" func="%s"' % (key, func_name)) + if self.debug: + print 'pyreadline parse_and_bind error, unknown function to bind: "%s"' % func_name + return + self.mode._bind_key(key, func) + except: + log('error') + raise + + def get_line_buffer(self): + '''Return the current contents of the line buffer.''' + return self.l_buffer.get_line_text() + + def insert_text(self, string): + '''Insert text into the command line.''' + self.l_buffer.insert_text(string) + + def read_init_file(self, filename=None): + '''Parse a readline initialization file. The default filename is the last filename used.''' + log('read_init_file("%s")' % filename) + + #History file book keeping methods (non-bindable) + + def add_history(self, line): + '''Append a line to the history buffer, as if it was the last line typed.''' + self._history.add_history(line) + + def get_history_length(self ): + '''Return the desired length of the history file. + + Negative values imply unlimited history file size.''' + return self._history.get_history_length() + + def set_history_length(self, length): + '''Set the number of lines to save in the history file. + + write_history_file() uses this value to truncate the history file + when saving. Negative values imply unlimited history file size. + ''' + self._history.set_history_length(length) + + def clear_history(self): + '''Clear readline history''' + self._history.clear_history() + + def read_history_file(self, filename=None): + '''Load a readline history file. The default filename is ~/.history.''' + self._history.read_history_file(filename) + + def write_history_file(self, filename=None): + '''Save a readline history file. The default filename is ~/.history.''' + self._history.write_history_file(filename) + + #Completer functions + + def set_completer(self, function=None): + '''Set or remove the completer function. + + If function is specified, it will be used as the new completer + function; if omitted or None, any completer function already + installed is removed. The completer function is called as + function(text, state), for state in 0, 1, 2, ..., until it returns a + non-string value. It should return the next possible completion + starting with text. + ''' + log('set_completer') + self.completer = function + + def get_completer(self): + '''Get the completer function. + ''' + + log('get_completer') + return self.completer + + def get_begidx(self): + '''Get the beginning index of the readline tab-completion scope.''' + return self.begidx + + def get_endidx(self): + '''Get the ending index of the readline tab-completion scope.''' + return self.endidx + + def set_completer_delims(self, string): + '''Set the readline word delimiters for tab-completion.''' + self.completer_delims = string + + def get_completer_delims(self): + '''Get the readline word delimiters for tab-completion.''' + return self.completer_delims + + def set_startup_hook(self, function=None): + '''Set or remove the startup_hook function. + + If function is specified, it will be used as the new startup_hook + function; if omitted or None, any hook function already installed is + removed. The startup_hook function is called with no arguments just + before readline prints the first prompt. + + ''' + self.startup_hook = function + + def set_pre_input_hook(self, function=None): + '''Set or remove the pre_input_hook function. + + If function is specified, it will be used as the new pre_input_hook + function; if omitted or None, any hook function already installed is + removed. The pre_input_hook function is called with no arguments + after the first prompt has been printed and just before readline + starts reading input characters. + + ''' + self.pre_input_hook = function + +## Internal functions + + def rl_settings_to_string(self): + out=["%-20s: %s"%("show all if ambigous",self.show_all_if_ambiguous)] + out.append("%-20s: %s"%("mark_directories",self.mark_directories)) + out.append("%-20s: %s"%("bell_style",self.bell_style)) + out.append("%-20s: %s"%("mark_directories",self.mark_directories)) + out.append("------------- key bindings ------------") + tablepat="%-7s %-7s %-7s %-15s %-15s " + out.append(tablepat%("Control","Meta","Shift","Keycode/char","Function")) + bindings=[(k[0],k[1],k[2],k[3],v.__name__) for k,v in self.mode.key_dispatch.iteritems()] + bindings.sort() + for key in bindings: + out.append(tablepat%(key)) + return out + + def _bell(self): + '''ring the bell if requested.''' + if self.bell_style == 'none': + pass + elif self.bell_style == 'visible': + raise NotImplementedError("Bellstyle visible is not implemented yet.") + elif self.bell_style == 'audible': + self.console.bell() + else: + raise ReadlineError("Bellstyle %s unknown."%self.bell_style) + + def _clear_after(self): + c = self.console + x, y = c.pos() + w, h = c.size() + c.rectangle((x, y, w+1, y+1)) + c.rectangle((0, y+1, w, min(y+3,h))) + + def _set_cursor(self): + c = self.console + xc, yc = self.prompt_end_pos + w, h = c.size() + xc += self.l_buffer.visible_line_width() + while(xc >= w): + xc -= w + yc += 1 + c.pos(xc, yc) + + def _print_prompt(self): + c = self.console + x, y = c.pos() + + n = c.write_scrolling(self.prompt, self.prompt_color) + self.prompt_begin_pos = (x, y - n) + self.prompt_end_pos = c.pos() + self.size = c.size() + + def _update_prompt_pos(self, n): + if n != 0: + bx, by = self.prompt_begin_pos + ex, ey = self.prompt_end_pos + self.prompt_begin_pos = (bx, by - n) + self.prompt_end_pos = (ex, ey - n) + + def _update_line(self): + c=self.console + c.cursor(0) #Hide cursor avoiding flicking + c.pos(*self.prompt_end_pos) + ltext = self.l_buffer.quoted_text() + if self.l_buffer.enable_selection and self.l_buffer.selection_mark>=0: + start=len(self.l_buffer[:self.l_buffer.selection_mark].quoted_text()) + stop=len(self.l_buffer[:self.l_buffer.point].quoted_text()) + if start>stop: + stop,start=start,stop + n = c.write_scrolling(ltext[:start], self.command_color) + n = c.write_scrolling(ltext[start:stop], self.selection_color) + n = c.write_scrolling(ltext[stop:], self.command_color) + else: + n = c.write_scrolling(ltext, self.command_color) + + x,y = c.pos() #Preserve one line for Asian IME(Input Method Editor) statusbar + w,h = c.size() + if y >= h - 1 or n > 0: + c.scroll_window(-1) + c.scroll((0,0,w,h),0,-1) + n += 1 + + self._update_prompt_pos(n) + if hasattr(c,"clear_to_end_of_window"): #Work around function for ironpython due + c.clear_to_end_of_window() #to System.Console's lack of FillFunction + else: + self._clear_after() + c.cursor(1) #Show cursor + self._set_cursor() + + def readline(self, prompt=''): + return self.mode.readline(prompt) + + def read_inputrc(self,inputrcpath=os.path.expanduser("~/pyreadlineconfig.ini")): + modes=dict([(x.mode,x) for x in self.editingmodes]) + mode=self.editingmodes[0].mode + def setmode(name): + self.mode=modes[name] + def bind_key(key,name): + log("bind %s %s"%(key,name)) + if hasattr(modes[mode],name): + modes[mode]._bind_key(key,getattr(modes[mode],name)) + else: + print "Trying to bind unknown command '%s' to key '%s'"%(name,key) + def un_bind_key(key): + keyinfo = make_KeyPress_from_keydescr(key).tuple() + if keyinfo in modes[mode].key_dispatch: + del modes[mode].key_dispatch[keyinfo] + + def bind_exit_key(key): + modes[mode]._bind_exit_key(key) + def un_bind_exit_key(key): + keyinfo = make_KeyPress_from_keydescr(key).tuple() + if keyinfo in modes[mode].exit_dispatch: + del modes[mode].exit_dispatch[keyinfo] + + def setkill_ring_to_clipboard(killring): + import pyreadline.lineeditor.lineobj + pyreadline.lineeditor.lineobj.kill_ring_to_clipboard=killring + def sethistoryfilename(filename): + self._history.history_filename=os.path.expanduser(filename) + def setbellstyle(mode): + self.bell_style=mode + def sethistorylength(length): + self._history.history_length=int(length) + def allow_ctrl_c(mode): + log_sock("allow_ctrl_c:%s:%s"%(self.allow_ctrl_c,mode)) + self.allow_ctrl_c=mode + def setbellstyle(mode): + self.bell_style=mode + def show_all_if_ambiguous(mode): + self.show_all_if_ambiguous=mode + def ctrl_c_tap_time_interval(mode): + self.ctrl_c_tap_time_interval=mode + def mark_directories(mode): + self.mark_directories=mode + def completer_delims(mode): + self.completer_delims=mode + def debug_output(on,filename="pyreadline_debug_log.txt"): #Not implemented yet + if on in ["on","on_nologfile"]: + self.debug=True + logger.start_log(on,filename) + logger.log("STARTING LOG") +# print release.branch + def set_prompt_color(color): + trtable={"black":0,"darkred":4,"darkgreen":2,"darkyellow":6,"darkblue":1,"darkmagenta":5,"darkcyan":3,"gray":7, + "red":4+8,"green":2+8,"yellow":6+8,"blue":1+8,"magenta":5+8,"cyan":3+8,"white":7+8} + self.prompt_color=trtable.get(color.lower(),7) + + def set_input_color(color): + trtable={"black":0,"darkred":4,"darkgreen":2,"darkyellow":6,"darkblue":1,"darkmagenta":5,"darkcyan":3,"gray":7, + "red":4+8,"green":2+8,"yellow":6+8,"blue":1+8,"magenta":5+8,"cyan":3+8,"white":7+8} + self.command_color=trtable.get(color.lower(),7) + loc={"branch":release.branch, + "version":release.version, + "mode":mode, + "modes":modes, + "set_mode":setmode, + "bind_key":bind_key, + "bind_exit_key":bind_exit_key, + "un_bind_key":un_bind_key, + "un_bind_exit_key":un_bind_exit_key, + "bell_style":setbellstyle, + "mark_directories":mark_directories, + "show_all_if_ambiguous":show_all_if_ambiguous, + "completer_delims":completer_delims, + "debug_output":debug_output, + "history_filename":sethistoryfilename, + "history_length":sethistorylength, + "set_prompt_color":set_prompt_color, + "set_input_color":set_input_color, + "allow_ctrl_c":allow_ctrl_c, + "ctrl_c_tap_time_interval":ctrl_c_tap_time_interval, + "kill_ring_to_clipboard":setkill_ring_to_clipboard, + } + if os.path.isfile(inputrcpath): + try: + execfile(inputrcpath,loc,loc) + except Exception,x: + raise + import traceback + print >>sys.stderr, "Error reading .pyinputrc" + filepath,lineno=traceback.extract_tb(sys.exc_traceback)[1][:2] + print >>sys.stderr, "Line: %s in file %s"%(lineno,filepath) + print >>sys.stderr, x + raise ReadlineError("Error reading .pyinputrc") + + + + +def CTRL(c): + '''make a control character''' + assert '@' <= c <= '_' + return chr(ord(c) - ord('@')) + +# create a Readline object to contain the state +rl = Readline() + + +def GetOutputFile(): + '''Return the console object used by readline so that it can be used for printing in color.''' + return rl.console + +# make these available so this looks like the python readline module +parse_and_bind = rl.parse_and_bind +get_line_buffer = rl.get_line_buffer +insert_text = rl.insert_text +read_init_file = rl.read_init_file +add_history = rl.add_history +get_history_length = rl.get_history_length +set_history_length = rl.set_history_length +clear_history = rl.clear_history +read_history_file = rl.read_history_file +write_history_file = rl.write_history_file +set_completer = rl.set_completer +get_completer = rl.get_completer +get_begidx = rl.get_begidx +get_endidx = rl.get_endidx +set_completer_delims = rl.set_completer_delims +get_completer_delims = rl.get_completer_delims +set_startup_hook = rl.set_startup_hook +set_pre_input_hook = rl.set_pre_input_hook + +if __name__ == '__main__': + res = [ rl.readline('In[%d] ' % i) for i in range(3) ] + print res +else: + console.install_readline(rl.readline) + pass diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/unicode_helper.py b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/unicode_helper.py new file mode 100644 index 0000000..bfd5afc --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/pyreadline/unicode_helper.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2007 Jorgen Stenarson. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +import sys + +try: + pyreadline_codepage=sys.stdout.encoding +except AttributeError: #This error occurs when pdb imports readline and doctest has replaced + #stdout with stdout collector + pyreadline_codepage="ascii" #assume ascii codepage + + +def ensure_unicode(text): + """helper to ensure that text passed to WriteConsoleW is unicode""" + if isinstance(text, str): + return text.decode(pyreadline_codepage, "replace") + return text + +def ensure_str(text): + """Convert unicode to str using pyreadline_codepage""" + if isinstance(text, unicode): + return text.encode(pyreadline_codepage, "replace") + return text diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/readme.txt b/interactive-mining-3rdparty-madis/madis/src/lib/readme.txt new file mode 100644 index 0000000..51c56b2 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/readme.txt @@ -0,0 +1 @@ +This directory contains "library" functions which are used from more than one places. \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/reimport.py b/interactive-mining-3rdparty-madis/madis/src/lib/reimport.py new file mode 100644 index 0000000..ad2bba3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/reimport.py @@ -0,0 +1,737 @@ +# MIT Licensed +# Copyright (c) 2009-2010 Peter Shinners +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. + +""" +This module intends to be a full featured replacement for Python's reload +function. It is targeted towards making a reload that works for Python +plugins and extensions used by longer running applications. + +Reimport currently supports Python 2.4 through 2.6. + +By its very nature, this is not a completely solvable problem. The goal of +this module is to make the most common sorts of updates work well. It also +allows individual modules and package to assist in the process. A more +detailed description of what happens is at +http://code.google.com/p/reimport . +""" + + +__all__ = ["reimport", "modified"] + + +import sys +import os +import gc +import imp +import inspect +import weakref +import traceback +import time + + + +__version__ = "1.3" +__author__ = "Peter Shinners " +__license__ = "MIT" +__url__ = "http://code.google.com/p/reimport" + + + +_previous_scan_time = time.time() - 1.0 +_module_timestamps = {} + + +# find the 'instance' old style type +class _OldClass: pass +_InstanceType = type(_OldClass()) +del _OldClass + + + +def reimport(*modules): + """Reimport python modules. Multiple modules can be passed either by + name or by reference. Only pure python modules can be reimported. + + For advanced control, global variables can be placed in modules + that allows finer control of the reimport process. + + If a package module has a true value for "__package_reimport__" + then that entire package will be reimported when any of its children + packages or modules are reimported. + + If a package module defines __reimported__ it must be a callable + function that accepts one argument and returns a bool. The argument + is the reference to the old version of that module before any + cleanup has happened. The function should normally return True to + allow the standard reimport cleanup. If the function returns false + then cleanup will be disabled for only that module. Any exceptions + raised during the callback will be handled by traceback.print_exc, + similar to what happens with tracebacks in the __del__ method. + """ + __internal_swaprefs_ignore__ = "reimport" + reloadSet = set() + + if not modules: + return + + # Get names of all modules being reloaded + for module in modules: + name, target = _find_exact_target(module) + if not target: + raise ValueError("Module %r not found" % module) + if not _is_code_module(target): + raise ValueError("Cannot reimport extension, %r" % name) + + reloadSet.update(_find_reloading_modules(name)) + + # Sort module names + reloadNames = _package_depth_sort(reloadSet, False) + + # Check for SyntaxErrors ahead of time. This won't catch all + # possible SyntaxErrors or any other ImportErrors. But these + # should be the most common problems, and now is the cleanest + # time to abort. + # I know this gets compiled again anyways. It could be + # avoided with py_compile, but I will not be the creator + # of messy .pyc files! + for name in reloadNames: + filename = getattr(sys.modules[name], "__file__", None) + if not filename: + continue + pyname = os.path.splitext(filename)[0] + ".py" + try: + data = open(pyname, "rU").read() + "\n" + except (IOError, OSError): + continue + + compile(data, pyname, "exec", 0, False) # Let this raise exceptions + + # Begin changing things. We "grab the GIL", so other threads + # don't get a chance to see our half-baked universe + imp.acquire_lock() + prevInterval = sys.getcheckinterval() + sys.setcheckinterval(min(sys.maxint, 0x7fffffff)) + try: + + # Python will munge the parent package on import. Remember original value + parentValues = [] + parentPackageDeleted = lambda: None + for name in reloadNames: + parentPackageName = name.rsplit(".", 1) + if len(parentPackageName) == 2: + parentPackage = sys.modules.get(parentPackageName[0], None) + parentValue = getattr(parentPackage, parentPackageName[1], parentPackageDeleted) + if parentValue != sys.modules[name]: + parentValues.append((parentPackage, parentPackageName[1], parentValue)) + parentPackage = parentValue = None + + # Move modules out of sys + oldModules = {} + for name in reloadNames: + oldModules[name] = sys.modules.pop(name) + ignores = (id(oldModules),) + prevNames = set(sys.modules) + + # Reimport modules, trying to rollback on exceptions + try: + try: + for name in reloadNames: + if name not in sys.modules: + __import__(name) + + except StandardError: + # Try to dissolve any newly import modules and revive the old ones + newNames = set(sys.modules) - prevNames + newNames = _package_depth_sort(newNames, True) + for name in newNames: + backoutModule = sys.modules.pop(name, None) + if backoutModule is not None: + _unimport(backoutModule, ignores) + del backoutModule + + sys.modules.update(oldModules) + raise + + finally: + # Fix Python automatically shoving of children into parent packages + for parentPackage, name, value in parentValues: + if value == parentPackageDeleted: + try: + delattr(parentPackage, name) + except AttributeError: + pass + else: + setattr(parentPackage, name, value) + parentValues = parentPackage = parentPackageDeleted = value = None + + newNames = set(sys.modules) - prevNames + newNames = _package_depth_sort(newNames, True) + + # Update timestamps for loaded time + now = time.time() - 1.0 + for name in newNames: + _module_timestamps[name] = (now, True) + + # Push exported namespaces into parent packages + pushSymbols = {} + for name in newNames: + oldModule = oldModules.get(name) + if not oldModule: + continue + parents = _find_parent_importers(name, oldModule, newNames) + pushSymbols[name] = parents + for name, parents in pushSymbols.iteritems(): + for parent in parents: + oldModule = oldModules[name] + newModule = sys.modules[name] + _push_imported_symbols(newModule, oldModule, parent) + + # Rejigger the universe + for name in newNames: + old = oldModules.get(name) + if not old: + continue + new = sys.modules[name] + rejigger = True + reimported = getattr(new, "__reimported__", None) + if reimported: + try: + rejigger = reimported(old) + except StandardError: + # What else can we do? the callbacks must go on + # Note, this is same as __del__ behaviour. /shrug + traceback.print_exc() + + if rejigger: + _rejigger_module(old, new, ignores) + else: + _unimport_module(new, ignores) + + finally: + # Restore the GIL + imp.release_lock() + sys.setcheckinterval(prevInterval) + time.sleep(0) + + + +def modified(path=None): + """Find loaded modules that have changed on disk under the given path. + If no path is given then all modules are searched. + """ + global _previous_scan_time + modules = [] + + if path: + path = os.path.normpath(path) + os.sep + + defaultTime = (_previous_scan_time, False) + pycExt = __debug__ and ".pyc" or ".pyo" + + for name, module in sys.modules.items(): + filename = _is_code_module(module) + if not filename: + continue + + filename = os.path.normpath(filename) + prevTime, prevScan = _module_timestamps.setdefault(name, defaultTime) + if path and not filename.startswith(path): + continue + + # Get timestamp of .pyc if this is first time checking this module + if not prevScan: + pycName = os.path.splitext(filename)[0] + pycExt + if pycName != filename: + try: + prevTime = os.path.getmtime(pycName) + except OSError: + pass + _module_timestamps[name] = (prevTime, True) + + # Get timestamp of source file + try: + diskTime = os.path.getmtime(filename) + except OSError: + diskTime = None + + if diskTime is not None and prevTime < diskTime: + modules.append(name) + + _previous_scan_time = time.time() + return modules + + +def _safevars(obj): + try: + return vars(obj) + except TypeError: + return {} + + +def _is_code_module(module): + """Determine if a module comes from python code""" + # getsourcefile will not return "bare" pyc modules. we can reload those? + try: + return inspect.getsourcefile(module) or "" + except TypeError: + return "" + + + +def _find_exact_target(module): + """Given a module name or object, find the + base module where reimport will happen.""" + # Given a name or a module, find both the name and the module + actualModule = sys.modules.get(module) + if actualModule is not None: + name = module + else: + for name, mod in sys.modules.iteritems(): + if mod is module: + actualModule = module + break + else: + return "", None + + # Find highest level parent package that has package_reimport magic + parentName = name + while True: + splitName = parentName.rsplit(".", 1) + if len(splitName) <= 1: + return name, actualModule + parentName = splitName[0] + + parentModule = sys.modules.get(parentName) + if getattr(parentModule, "__package_reimport__", None): + name = parentName + actualModule = parentModule + + + +def _find_reloading_modules(name): + """Find all modules that will be reloaded from given name""" + modules = [name] + childNames = name + "." + for name in sys.modules.keys(): + if name.startswith(childNames) and _is_code_module(sys.modules[name]): + modules.append(name) + return modules + + + +def _package_depth_sort(names, reverse): + """Sort a list of module names by their package depth""" + def packageDepth(name): + return name.count(".") + return sorted(names, key=packageDepth, reverse=reverse) + + + +def _find_module_exports(module): + allNames = getattr(module, "__all__", ()) + if not allNames: + allNames = [n for n in dir(module) if n[0] != "_"] + return set(allNames) + + + +def _find_parent_importers(name, oldModule, newNames): + """Find parents of reimported module that have all exported symbols""" + parents = [] + + # Get exported symbols + exports = _find_module_exports(oldModule) + if not exports: + return parents + + # Find non-reimported parents that have all old symbols + parent = name + while True: + names = parent.rsplit(".", 1) + if len(names) <= 1: + break + parent = names[0] + if parent in newNames: + continue + parentModule = sys.modules[parent] + if not exports - set(dir(parentModule)): + parents.append(parentModule) + + return parents + + + +def _push_imported_symbols(newModule, oldModule, parent): + """Transfer changes symbols from a child module to a parent package""" + # This assumes everything in oldModule is already found in parent + oldExports = _find_module_exports(oldModule) + newExports = _find_module_exports(newModule) + + # Delete missing symbols + for name in oldExports - newExports: + delattr(parent, name) + + # Find symbols in new module, use placeholder if missing + symbols = {} + for name in newExports: + try: + symbols[name] = getattr(newModule, name) + except AttributeError: + holder = type(name, (_MissingAllReference,), + {"__module__":newModule.__name__}) + symbols[name] = holder() + + + # Add new symbols + for name in newExports - oldExports: + setattr(parent, name, symbols[name]) + + # Update existing symbols + for name in newExports & oldExports: + oldValue = getattr(oldModule, name) + if getattr(parent, name) is oldValue: + setattr(parent, name, symbols[name]) + + + +# To rejigger is to copy internal values from new to old +# and then to swap external references from old to new + + +def _rejigger_module(old, new, ignores): + """Mighty morphin power modules""" + __internal_swaprefs_ignore__ = "rejigger_module" + oldVars = _safevars(old) + newVars = _safevars(new) + ignores += (id(oldVars),) + old.__doc__ = new.__doc__ + + # Get filename used by python code + filename = new.__file__ + + for name, value in newVars.iteritems(): + if name in oldVars: + oldValue = oldVars[name] + if oldValue is value: + continue + + if _from_file(filename, value): + if inspect.isclass(value): + if inspect.isclass(oldValue): + _rejigger_class(oldValue, value, ignores) + + elif inspect.isfunction(value): + if inspect.isfunction(oldValue): + _rejigger_func(oldValue, value, ignores) + + setattr(old, name, value) + + for name, value in oldVars.items(): + if name not in newVars: + delattr(old, name) + if _from_file(filename, value): + if inspect.isclass(value) or inspect.isfunction(value): + _remove_refs(value, ignores) + + _swap_refs(old, new, ignores) + + + +def _from_file(filename, value): + """Test if object came from a filename, works for pyc/py confusion""" + try: + objfile = inspect.getsourcefile(value) + except TypeError: + return False + return bool(objfile) and objfile.startswith(filename) + + + +def _rejigger_class(old, new, ignores): + """Mighty morphin power classes""" + __internal_swaprefs_ignore__ = "rejigger_class" + oldVars = _safevars(old) + newVars = _safevars(new) + ignores += (id(oldVars),) + + slotted = hasattr(old, "__slots__") and isinstance(old.__slots__, tuple) + ignoreAttrs = ["__dict__", "__doc__", "__weakref__"] + if slotted: + ignoreAttrs.extend(old.__slots__) + ignoreAttrs.append("__slots__") + ignoreAttrs = tuple(ignoreAttrs) + + for name, value in newVars.iteritems(): + if name in ignoreAttrs: + continue + + if name in oldVars: + oldValue = oldVars[name] + if oldValue is value: + continue + + if inspect.isclass(value) and value.__module__ == new.__module__: + _rejigger_class(oldValue, value, ignores) + + elif inspect.isfunction(value): + _rejigger_func(oldValue, value, ignores) + + setattr(old, name, value) + + for name, value in oldVars.items(): + if name not in newVars: + delattr(old, name) + _remove_refs(value, ignores) + + _swap_refs(old, new, ignores) + + + +def _rejigger_func(old, new, ignores): + """Mighty morphin power functions""" + __internal_swaprefs_ignore__ = "rejigger_func" + old.func_code = new.func_code + old.func_doc = new.func_doc + old.func_defaults = new.func_defaults + old.func_dict = new.func_dict + _swap_refs(old, new, ignores) + + + +def _unimport(old, ignores): + """Unimport something, mainly used to rollback a reimport""" + if isinstance(old, type(sys)): + _unimport_module(old, ignores) + elif inspect.isclass(old): + _unimport_class(old, ignores) + else: + _remove_refs(old, ignores) + + + +def _unimport_module(old, ignores): + """Remove traces of a module""" + __internal_swaprefs_ignore__ = "unimport_module" + oldValues = _safevars(old).values() + ignores += (id(oldValues),) + + # Get filename used by python code + filename = old.__file__ + fileext = os.path.splitext(filename) + if fileext in (".pyo", ".pyc", ".pyw"): + filename = filename[:-1] + + for value in oldValues: + try: objfile = inspect.getsourcefile(value) + except TypeError: objfile = "" + + if objfile == filename: + if inspect.isclass(value): + _unimport_class(value, ignores) + + elif inspect.isfunction(value): + _remove_refs(value, ignores) + + _remove_refs(old, ignores) + + + +def _unimport_class(old, ignores): + """Remove traces of a class""" + __internal_swaprefs_ignore__ = "unimport_class" + oldItems = _safevars(old).items() + ignores += (id(oldItems),) + + for name, value in oldItems: + if name in ("__dict__", "__doc__", "__weakref__"): + continue + + if inspect.isclass(value) and value.__module__ == old.__module__: + _unimport_class(value, ignores) + + elif inspect.isfunction(value): + _remove_refs(value, ignores) + + _remove_refs(old, ignores) + + + + +class _MissingAllReference(object): + """This is a stub placeholder for objects added to __all__ but + are not actually found. + """ + def __str__(self, *args): + raise AttributeError("%r missing from module %r" % + (type(self).__name__, type(self).__module__)) + __nonzero__ = __hash__ = __id__ = __cmp__ = __len__ = __iter__ = __str__ + __repr__ = __int__ = __getattr__ = __setattr__ = __delattr__ = __str__ + + + +_recursive_tuple_swap = set() + + +def _bonus_containers(): + """Find additional container types, if they are loaded. Returns + (deque, defaultdict). + Any of these will be None if not loaded. + """ + deque = defaultdict = None + collections = sys.modules.get("collections", None) + if collections: + deque = getattr(collections, "collections", None) + defaultdict = getattr(collections, "defaultdict", None) + return deque, defaultdict + + + +def _find_sequence_indices(container, value): + """Find indices of value in container. The indices will + be in reverse order, to allow safe editing. + """ + indices = [] + for i in range(len(container)-1, -1, -1): + if container[i] is value: + indices.append(i) + return indices + + +def _swap_refs(old, new, ignores): + """Swap references from one object to another""" + __internal_swaprefs_ignore__ = "swap_refs" + # Swap weak references + refs = weakref.getweakrefs(old) + if refs: + try: + newRef = weakref.ref(new) + except ValueError: + pass + else: + for oldRef in refs: + _swap_refs(oldRef, newRef, ignores + (id(refs),)) + del refs + + deque, defaultdict = _bonus_containers() + + # Swap through garbage collector + referrers = gc.get_referrers(old) + for container in referrers: + if id(container) in ignores: + continue + containerType = type(container) + + if containerType is list or containerType is deque: + for index in _find_sequence_indices(container, old): + container[index] = new + + elif containerType is tuple: + # protect from recursive tuples + orig = container + if id(orig) in _recursive_tuple_swap: + continue + _recursive_tuple_swap.add(id(orig)) + try: + container = list(container) + for index in _find_sequence_indices(container, old): + container[index] = new + container = tuple(container) + _swap_refs(orig, container, ignores + (id(referrers),)) + finally: + _recursive_tuple_swap.remove(id(orig)) + + elif containerType is dict or containerType is defaultdict: + if "__internal_swaprefs_ignore__" not in container: + try: + if old in container: + container[new] = container.pop(old) + except TypeError: # Unhashable old value + pass + for k,v in container.iteritems(): + if v is old: + container[k] = new + + elif containerType is set: + container.remove(old) + container.add(new) + + elif containerType is type: + if old in container.__bases__: + bases = list(container.__bases__) + bases[bases.index(old)] = new + container.__bases__ = tuple(bases) + + elif type(container) is old: + try: + container.__class__ = new + except TypeError: + # Type error happens on slotted classes + pass + + elif containerType is _InstanceType: + if container.__class__ is old: + container.__class__ = new + + + +def _remove_refs(old, ignores): + """Remove references to a discontinued object""" + __internal_swaprefs_ignore__ = "remove_refs" + + # Ignore builtin immutables that keep no other references + if old is None or isinstance(old, (int, basestring, float, complex)): + return + + deque, defaultdict = _bonus_containers() + + # Remove through garbage collector + for container in gc.get_referrers(old): + if id(container) in ignores: + continue + containerType = type(container) + + if containerType is list or containerType is deque: + for index in _find_sequence_indices(container, old): + del container[index] + + elif containerType is tuple: + orig = container + container = list(container) + for index in _find_sequence_indices(container, old): + del container[index] + container = tuple(container) + _swap_refs(orig, container, ignores) + + elif containerType is dict or containerType is defaultdict: + if "__internal_swaprefs_ignore__" not in container: + try: + container.pop(old, None) + except TypeError: # Unhashable old value + pass + for k,v in container.items(): + if v is old: + del container[k] + + elif containerType is set: + container.remove(old) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/schemaUtils.py b/interactive-mining-3rdparty-madis/madis/src/lib/schemaUtils.py new file mode 100644 index 0000000..eb279f7 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/schemaUtils.py @@ -0,0 +1,56 @@ +import re + +reduce_spaces=re.compile(ur'\s+', re.UNICODE) + +def CreateStatement(description,tablename): + names=[] + types=[] + for tp in description: + names+=[tp[0]] + if len(tp)==1: + types+=['None'] + else: + if tp[1]!=None: + types+=[tp[1]] + else: + types+=['None'] + return schemastr(tablename,names,types) + +def unify(slist): + if len(set(slist))==len(slist): + return slist + eldict={} + for s in slist: + if s in eldict: + eldict[s]+=1 + else: + eldict[s]=1 + for val,fr in eldict.items(): + if fr==1: + del eldict[val] + for val in eldict: + eldict[val]=1 + uniquelist=[] + for s in slist: + if s in eldict: + uniquelist+=[s+str(eldict[s])] + eldict[s]+=1 + else: + uniquelist+=[s] + + return uniquelist + +onlyalphnum=re.compile('[a-zA-Z]\w*$') + +def schemastr(tablename,colnames,typenames=None): + stripedcolnames=['"'+el+'"' if onlyalphnum.match(el) + else '"'+reduce_spaces.sub(' ', el.replace('\n','').replace('\t','')).strip().replace('"','""')+'"' + for el in unify(colnames)] + if not typenames: + return "create table %s(%s)" %(tablename,','.join([c for c in stripedcolnames])) + else: + stripedtypenames=['' if el.lower()=="none" or el=='' + else el if onlyalphnum.match(el) + else '"'+el.replace('"','""')+'"' + for el in typenames] + return "create table %s(%s)" %(tablename,','.join([c+' '+str(t) for c,t in zip(stripedcolnames,stripedtypenames)])) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/setpath.py b/interactive-mining-3rdparty-madis/madis/src/lib/setpath.py new file mode 100644 index 0000000..f05bb6a --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/setpath.py @@ -0,0 +1,2 @@ +import sys, os +sys.path.append((os.path.join(sys.path[0],'..'))) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/simpleutils.py b/interactive-mining-3rdparty-madis/madis/src/lib/simpleutils.py new file mode 100644 index 0000000..deafb5e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/simpleutils.py @@ -0,0 +1,10 @@ +def latinnum(x): + x=int(x) + if x<=0: + raise ValueError("Value must be greater than zero to produce an equivalent latin string") + lx="" + while x>25: + lx+=chr(ord('A')+int(x/25)) + x%=25 + lx+=chr(ord('A')+x) + return lx \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/sqlitetypes.py b/interactive-mining-3rdparty-madis/madis/src/lib/sqlitetypes.py new file mode 100644 index 0000000..3b95259 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/sqlitetypes.py @@ -0,0 +1,23 @@ +def getElementSqliteType(element): + elemtype = type(element) + if elemtype is int or elemtype is long: + return "integer" + if elemtype is float: + return "real" + if elemtype is buffer: + return "blob" + return "text" + +def typestoSqliteTypes(type): + type = str(type).upper() + if type=="TEXT" or type=="INTEGER" or type=="REAL" or type=="NONE" or type=="NUMERIC": + return type + if "INT" in type: + return "INTEGER" + if "CHAR" in type or "CLOB" in type or "TEXT" in type: + return "TEXT" + if "BLOB" in type or type=="": + return "NONE" + if "REAL" in type or "FLOA" in type or "DOUB" in type: + return "REAL" + return "NUMERIC" \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/__init__.py new file mode 100644 index 0000000..2e9493f --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/__init__.py @@ -0,0 +1,55 @@ +# Copyright (C) 2008 Andi Albrecht, albrecht.andi@gmail.com +# +# This module is part of python-sqlparse and is released under +# the BSD License: http://www.opensource.org/licenses/bsd-license.php. + +"""Parse SQL statements.""" + + +__version__ = '0.1.1' + + +class SQLParseError(Exception): + """Base class for exceptions in this module.""" + + +# Setup namespace +from sqlparse import engine +from sqlparse import filters +from sqlparse import formatter + + +def parse(sql): + """Parse sql and return a list of statements. + + *sql* is a single string containting one or more SQL statements. + + Returns a tuple of :class:`~sqlparse.sql.Statement` instances. + """ + stack = engine.FilterStack() + stack.full_analyze() + return tuple(stack.run(sql)) + + +def format(sql, **options): + """Format *sql* according to *options*. + + Available options are documented in :ref:`formatting`. + + Returns the formatted SQL statement as string. + """ + stack = engine.FilterStack() + options = formatter.validate_options(options) + stack = formatter.build_filter_stack(stack, options) + stack.postprocess.append(filters.SerializerUnicode()) + return ''.join(stack.run(sql)) + + +def split(sql): + """Split *sql* into single statements. + + Returns a list of strings. + """ + stack = engine.FilterStack() + stack.split_statements = True + return [unicode(stmt) for stmt in stack.run(sql)] diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/engine/__init__.py b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/engine/__init__.py new file mode 100644 index 0000000..02f84c6 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/engine/__init__.py @@ -0,0 +1,78 @@ +# Copyright (C) 2008 Andi Albrecht, albrecht.andi@gmail.com +# +# This module is part of python-sqlparse and is released under +# the BSD License: http://www.opensource.org/licenses/bsd-license.php. + +"""filter""" + +from sqlparse import lexer +from sqlparse.engine import grouping +from sqlparse.engine.filter import StatementFilter + +# XXX remove this when cleanup is complete +Filter = object + + +class FilterStack(object): + + def __init__(self): + self.preprocess = [] + self.stmtprocess = [] + self.postprocess = [] + self.split_statements = False + self._grouping = False + + def _flatten(self, stream): + for token in stream: + if token.is_group(): + for t in self._flatten(token.tokens): + yield t + else: + yield token + + def enable_grouping(self): + self._grouping = True + + def full_analyze(self): + self.enable_grouping() + + def run(self, sql): + stream = lexer.tokenize(sql) + # Process token stream + if self.preprocess: + for filter_ in self.preprocess: + stream = filter_.process(self, stream) + + if (self.stmtprocess or self.postprocess or self.split_statements + or self._grouping): + splitter = StatementFilter() + stream = splitter.process(self, stream) + + if self._grouping: + def _group(stream): + for stmt in stream: + grouping.group(stmt) + yield stmt + stream = _group(stream) + + if self.stmtprocess: + def _run1(stream): + ret = [] + for stmt in stream: + for filter_ in self.stmtprocess: + filter_.process(self, stmt) + ret.append(stmt) + return ret + stream = _run1(stream) + + if self.postprocess: + def _run2(stream): + for stmt in stream: + stmt.tokens = list(self._flatten(stmt.tokens)) + for filter_ in self.postprocess: + stmt = filter_.process(self, stmt) + yield stmt + stream = _run2(stream) + + return stream + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/engine/filter.py b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/engine/filter.py new file mode 100644 index 0000000..08ff21d --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/engine/filter.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- + +from sqlparse import tokens as T +from sqlparse.engine.grouping import Statement, Token + + +class TokenFilter(object): + + def __init__(self, **options): + self.options = options + + def process(self, stack, stream): + """Process token stream.""" + raise NotImplementedError + + +class StatementFilter(TokenFilter): + + def __init__(self): + TokenFilter.__init__(self) + self._in_declare = False + self._in_dbldollar = False + self._is_create = False + + def _reset(self): + self._in_declare = False + self._in_dbldollar = False + self._is_create = False + + def _change_splitlevel(self, ttype, value): + # PostgreSQL + if (ttype == T.Name.Builtin + and value.startswith('$') and value.endswith('$')): + if self._in_dbldollar: + self._in_dbldollar = False + return -1 + else: + self._in_dbldollar = True + return 1 + elif self._in_dbldollar: + return 0 + + # ANSI + if ttype is not T.Keyword: + return 0 + + unified = value.upper() + + if unified == 'DECLARE': + self._in_declare = True + return 1 + + if unified == 'BEGIN': + if self._in_declare: + return 0 + return 0 + + if unified == 'END': + # Should this respect a preceeding BEGIN? + # In CASE ... WHEN ... END this results in a split level -1. + return -1 + + if ttype is T.Keyword.DDL and unified.startswith('CREATE'): + self._is_create = True + + if unified in ('IF', 'FOR') and self._is_create: + return 1 + + # Default + return 0 + + def process(self, stack, stream): + splitlevel = 0 + stmt = None + consume_ws = False + stmt_tokens = [] + for ttype, value in stream: + # Before appending the token + if (consume_ws and ttype is not T.Whitespace + and ttype is not T.Comment.Single): + consume_ws = False + stmt.tokens = stmt_tokens + yield stmt + self._reset() + stmt = None + splitlevel = 0 + if stmt is None: + stmt = Statement() + stmt_tokens = [] + splitlevel += self._change_splitlevel(ttype, value) + # Append the token + stmt_tokens.append(Token(ttype, value)) + # After appending the token + if (splitlevel <= 0 and ttype is T.Punctuation + and value == ';'): + consume_ws = True + if stmt is not None: + stmt.tokens = stmt_tokens + yield stmt diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/engine/grouping.py b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/engine/grouping.py new file mode 100644 index 0000000..a03c0b4 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/engine/grouping.py @@ -0,0 +1,292 @@ +# -*- coding: utf-8 -*- + +import itertools + +from sqlparse import tokens as T +from sqlparse.sql import * + + +def _group_left_right(tlist, ttype, value, cls, + check_right=lambda t: True, + check_left = lambda t: True, + include_semicolon=False): + [_group_left_right(sgroup, ttype, value, cls, check_right, + include_semicolon) for sgroup in tlist.get_sublists() + if not isinstance(sgroup, cls)] + idx = 0 + token = tlist.token_next_match(idx, ttype, value) + while token: + right = tlist.token_next(tlist.token_index(token)) + left = tlist.token_prev(tlist.token_index(token)) + if right is None or not check_right(right): + token = tlist.token_next_match(tlist.token_index(token)+1, + ttype, value) + elif left is None or not check_right(left): + token = tlist.token_next_match(tlist.token_index(token)+1, + ttype, value) + else: + if include_semicolon: + sright = tlist.token_next_match(tlist.token_index(right), + T.Punctuation, ';') + if sright is not None: + # only overwrite "right" if a semicolon is actually + # present. + right = sright + tokens = tlist.tokens_between(left, right)[1:] + if not isinstance(left, cls): + new = cls([left]) + new_idx = tlist.token_index(left) + tlist.tokens.remove(left) + tlist.tokens.insert(new_idx, new) + left = new + left.tokens.extend(tokens) + for t in tokens: + tlist.tokens.remove(t) + token = tlist.token_next_match(tlist.token_index(left)+1, + ttype, value) + +def _group_matching(tlist, start_ttype, start_value, end_ttype, end_value, + cls, include_semicolon=False, recurse=False): + def _find_matching(i, tl, stt, sva, ett, eva): + depth = 1 + for t in tl.tokens[i:]: + if t.match(stt, sva): + depth += 1 + elif t.match(ett, eva): + depth -= 1 + if depth == 1: + return t + return None + [_group_matching(sgroup, start_ttype, start_value, end_ttype, end_value, + cls, include_semicolon) for sgroup in tlist.get_sublists() + if recurse] + if isinstance(tlist, cls): + idx = 1 + else: + idx = 0 + token = tlist.token_next_match(idx, start_ttype, start_value) + while token: + tidx = tlist.token_index(token) + end = _find_matching(tidx, tlist, start_ttype, start_value, + end_ttype, end_value) + if end is None: + idx = tidx+1 + else: + if include_semicolon: + next_ = tlist.token_next(tlist.token_index(end)) + if next_ and next_.match(T.Punctuation, ';'): + end = next_ + group = tlist.group_tokens(cls, tlist.tokens_between(token, end)) + _group_matching(group, start_ttype, start_value, + end_ttype, end_value, cls, include_semicolon) + idx = tlist.token_index(group)+1 + token = tlist.token_next_match(idx, start_ttype, start_value) + +def group_if(tlist): + _group_matching(tlist, T.Keyword, 'IF', T.Keyword, 'END IF', If, True) + +def group_for(tlist): + _group_matching(tlist, T.Keyword, 'FOR', T.Keyword, 'END LOOP', For, True) + +def group_as(tlist): + def _right_valid(token): + # Currently limited to DML/DDL. Maybe additional more non SQL reserved + # keywords should appear here (see issue8). + return not token.ttype in (T.DML, T.DDL) + _group_left_right(tlist, T.Keyword, 'AS', Identifier, + check_right=_right_valid) + +def group_assignment(tlist): + _group_left_right(tlist, T.Assignment, ':=', Assignment, + include_semicolon=True) + +def group_comparsion(tlist): + def _parts_valid(token): + return (token.ttype in (T.String.Symbol, T.Name, T.Number, + T.Number.Integer, T.Literal) + or isinstance(token, (Identifier,))) + _group_left_right(tlist, T.Operator.Comparsion, None, Comparsion, + check_left=_parts_valid, check_right=_parts_valid) + + +def group_case(tlist): + _group_matching(tlist, T.Keyword, 'CASE', T.Keyword, 'END', Case, + include_semicolon=True, recurse=True) + + +def group_identifier(tlist): + def _consume_cycle(tl, i): + x = itertools.cycle(( + lambda y: (y.match(T.Punctuation, '.') + or y.ttype is T.Operator), + lambda y: (y.ttype in (T.String.Symbol, + T.Name, + T.Wildcard)) + )) + for t in tl.tokens[i:]: + if x.next()(t): + yield t + else: + raise StopIteration + + # bottom up approach: group subgroups first + [group_identifier(sgroup) for sgroup in tlist.get_sublists() + if not isinstance(sgroup, Identifier)] + + # real processing + idx = 0 + token = tlist.token_next_by_instance(idx, Function) + if token is None: + token = tlist.token_next_by_type(idx, (T.String.Symbol, T.Name)) + while token: + identifier_tokens = [token]+list( + _consume_cycle(tlist, + tlist.token_index(token)+1)) + if not (len(identifier_tokens) == 1 + and isinstance(identifier_tokens[0], Function)): + group = tlist.group_tokens(Identifier, identifier_tokens) + idx = tlist.token_index(group)+1 + else: + idx += 1 + token = tlist.token_next_by_instance(idx, Function) + if token is None: + token = tlist.token_next_by_type(idx, (T.String.Symbol, T.Name)) + + +def group_identifier_list(tlist): + [group_identifier_list(sgroup) for sgroup in tlist.get_sublists() + if not isinstance(sgroup, (Identifier, IdentifierList))] + idx = 0 + # Allowed list items + fend1_funcs = [lambda t: isinstance(t, Identifier), + lambda t: t.is_whitespace(), + lambda t: t.ttype == T.Wildcard, + lambda t: t.match(T.Keyword, 'null'), + lambda t: t.ttype == T.Number.Integer, + lambda t: t.ttype == T.String.Single, + lambda t: isinstance(t, Comparsion), + ] + tcomma = tlist.token_next_match(idx, T.Punctuation, ',') + start = None + while tcomma is not None: + before = tlist.token_prev(tcomma) + after = tlist.token_next(tcomma) + # Check if the tokens around tcomma belong to a list + bpassed = apassed = False + for func in fend1_funcs: + if before is not None and func(before): + bpassed = True + if after is not None and func(after): + apassed = True + if not bpassed or not apassed: + # Something's wrong here, skip ahead to next "," + start = None + tcomma = tlist.token_next_match(tlist.token_index(tcomma)+1, + T.Punctuation, ',') + else: + if start is None: + start = before + next_ = tlist.token_next(after) + if next_ is None or not next_.match(T.Punctuation, ','): + # Reached the end of the list + tokens = tlist.tokens_between(start, after) + group = tlist.group_tokens(IdentifierList, tokens) + start = None + tcomma = tlist.token_next_match(tlist.token_index(group)+1, + T.Punctuation, ',') + else: + tcomma = next_ + + +def group_parenthesis(tlist): + _group_matching(tlist, T.Punctuation, '(', T.Punctuation, ')', Parenthesis) + +def group_comments(tlist): + [group_comments(sgroup) for sgroup in tlist.get_sublists() + if not isinstance(sgroup, Comment)] + idx = 0 + token = tlist.token_next_by_type(idx, T.Comment) + while token: + tidx = tlist.token_index(token) + end = tlist.token_not_matching(tidx+1, + [lambda t: t.ttype in T.Comment, + lambda t: t.is_whitespace()]) + if end is None: + idx = tidx + 1 + else: + eidx = tlist.token_index(end) + grp_tokens = tlist.tokens_between(token, + tlist.token_prev(eidx, False)) + group = tlist.group_tokens(Comment, grp_tokens) + idx = tlist.token_index(group) + token = tlist.token_next_by_type(idx, T.Comment) + +def group_where(tlist): + [group_where(sgroup) for sgroup in tlist.get_sublists() + if not isinstance(sgroup, Where)] + idx = 0 + token = tlist.token_next_match(idx, T.Keyword, 'WHERE') + stopwords = ('ORDER', 'GROUP', 'LIMIT', 'UNION') + while token: + tidx = tlist.token_index(token) + end = tlist.token_next_match(tidx+1, T.Keyword, stopwords) + if end is None: + end = tlist._groupable_tokens[-1] + else: + end = tlist.tokens[tlist.token_index(end)-1] + group = tlist.group_tokens(Where, tlist.tokens_between(token, end)) + idx = tlist.token_index(group) + token = tlist.token_next_match(idx, T.Keyword, 'WHERE') + +def group_aliased(tlist): + [group_aliased(sgroup) for sgroup in tlist.get_sublists() + if not isinstance(sgroup, Identifier)] + idx = 0 + token = tlist.token_next_by_instance(idx, Identifier) + while token: + next_ = tlist.token_next(tlist.token_index(token)) + if next_ is not None and isinstance(next_, Identifier): + grp = tlist.tokens_between(token, next_)[1:] + token.tokens.extend(grp) + for t in grp: + tlist.tokens.remove(t) + idx = tlist.token_index(token)+1 + token = tlist.token_next_by_instance(idx, Identifier) + + +def group_typecasts(tlist): + _group_left_right(tlist, T.Punctuation, '::', Identifier) + + +def group_functions(tlist): + [group_functions(sgroup) for sgroup in tlist.get_sublists() + if not isinstance(sgroup, Function)] + idx = 0 + token = tlist.token_next_by_type(idx, T.Name) + while token: + next_ = tlist.token_next(token) + if not isinstance(next_, Parenthesis): + idx = tlist.token_index(token)+1 + else: + func = tlist.group_tokens(Function, + tlist.tokens_between(token, next_)) + idx = tlist.token_index(func)+1 + token = tlist.token_next_by_type(idx, T.Name) + + +def group(tlist): + for func in [group_parenthesis, + group_functions, + group_comments, + group_where, + group_case, + group_identifier, + group_typecasts, + group_as, + group_aliased, + group_assignment, + group_comparsion, + group_identifier_list, + group_if, + group_for,]: + func(tlist) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/filters.py b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/filters.py new file mode 100644 index 0000000..d2bfebc --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/filters.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- + +import re + +from sqlparse.engine import grouping +from sqlparse import tokens as T +from sqlparse import sql + + +class Filter(object): + + def process(self, *args): + raise NotImplementedError + + +class TokenFilter(Filter): + + def process(self, stack, stream): + raise NotImplementedError + + +# -------------------------- +# token process + +class _CaseFilter(TokenFilter): + + ttype = None + + def __init__(self, case=None): + if case is None: + case = 'upper' + assert case in ['lower', 'upper', 'capitalize'] + self.convert = getattr(unicode, case) + + def process(self, stack, stream): + for ttype, value in stream: + if ttype in self.ttype: + value = self.convert(value) + yield ttype, value + + +class KeywordCaseFilter(_CaseFilter): + ttype = T.Keyword + + +class IdentifierCaseFilter(_CaseFilter): + ttype = (T.Name, T.String.Symbol) + + +# ---------------------- +# statement process + +class StripCommentsFilter(Filter): + + def _process(self, tlist): + idx = 0 + clss = set([x.__class__ for x in tlist.tokens]) + while grouping.Comment in clss: + token = tlist.token_next_by_instance(0, grouping.Comment) + tidx = tlist.token_index(token) + prev = tlist.token_prev(tidx, False) + next_ = tlist.token_next(tidx, False) + # Replace by whitespace if prev and next exist and if they're not + # whitespaces. This doesn't apply if prev or next is a paranthesis. + if (prev is not None and next_ is not None + and not prev.is_whitespace() and not next_.is_whitespace() + and not (prev.match(T.Punctuation, '(') + or next_.match(T.Punctuation, ')'))): + tlist.tokens[tidx] = grouping.Token(T.Whitespace, ' ') + else: + tlist.tokens.pop(tidx) + clss = set([x.__class__ for x in tlist.tokens]) + + def process(self, stack, stmt): + [self.process(stack, sgroup) for sgroup in stmt.get_sublists()] + self._process(stmt) + + +class StripWhitespaceFilter(Filter): + + def _stripws(self, tlist): + func_name = '_stripws_%s' % tlist.__class__.__name__.lower() + func = getattr(self, func_name, self._stripws_default) + func(tlist) + + def _stripws_default(self, tlist): + last_was_ws = False + for token in tlist.tokens: + if token.is_whitespace(): + if last_was_ws: + token.value = '' + else: + token.value = ' ' + last_was_ws = token.is_whitespace() + + def _stripws_parenthesis(self, tlist): + if tlist.tokens[1].is_whitespace(): + tlist.tokens.pop(1) + if tlist.tokens[-2].is_whitespace(): + tlist.tokens.pop(-2) + self._stripws_default(tlist) + + def process(self, stack, stmt): + [self.process(stack, sgroup) for sgroup in stmt.get_sublists()] + self._stripws(stmt) + if stmt.tokens[-1].is_whitespace(): + stmt.tokens.pop(-1) + + +class ReindentFilter(Filter): + + def __init__(self, width=2, char=' ', line_width=None): + self.width = width + self.char = char + self.indent = 0 + self.offset = 0 + self.line_width = line_width + self._curr_stmt = None + self._last_stmt = None + + def _get_offset(self, token): + all_ = list(self._curr_stmt.flatten()) + idx = all_.index(token) + raw = ''.join(unicode(x) for x in all_[:idx+1]) + line = raw.splitlines()[-1] + # Now take current offset into account and return relative offset. + full_offset = len(line)-(len(self.char*(self.width*self.indent))) + return full_offset - self.offset + + def nl(self): + # TODO: newline character should be configurable + ws = '\n'+(self.char*((self.indent*self.width)+self.offset)) + return grouping.Token(T.Whitespace, ws) + + def _split_kwds(self, tlist): + split_words = ('FROM', 'JOIN$', 'AND', 'OR', + 'GROUP', 'ORDER', 'UNION', 'VALUES', + 'SET') + idx = 0 + token = tlist.token_next_match(idx, T.Keyword, split_words, + regex=True) + while token: + prev = tlist.token_prev(tlist.token_index(token), False) + offset = 1 + if prev and prev.is_whitespace(): + tlist.tokens.pop(tlist.token_index(prev)) + offset += 1 + if (prev + and isinstance(prev, sql.Comment) + and (str(prev).endswith('\n') + or str(prev).endswith('\r'))): + nl = tlist.token_next(token) + else: + nl = self.nl() + tlist.insert_before(token, nl) + token = tlist.token_next_match(tlist.token_index(nl)+offset, + T.Keyword, split_words, regex=True) + + def _split_statements(self, tlist): + idx = 0 + token = tlist.token_next_by_type(idx, (T.Keyword.DDL, T.Keyword.DML)) + while token: + prev = tlist.token_prev(tlist.token_index(token), False) + if prev and prev.is_whitespace(): + tlist.tokens.pop(tlist.token_index(prev)) + # only break if it's not the first token + if prev: + nl = self.nl() + tlist.insert_before(token, nl) + token = tlist.token_next_by_type(tlist.token_index(token)+1, + (T.Keyword.DDL, T.Keyword.DML)) + + def _process(self, tlist): + func_name = '_process_%s' % tlist.__class__.__name__.lower() + func = getattr(self, func_name, self._process_default) + func(tlist) + + def _process_where(self, tlist): + token = tlist.token_next_match(0, T.Keyword, 'WHERE') + tlist.insert_before(token, self.nl()) + self.indent += 1 + self._process_default(tlist) + self.indent -= 1 + + def _process_parenthesis(self, tlist): + first = tlist.token_next(0) + indented = False + if first and first.ttype in (T.Keyword.DML, T.Keyword.DDL): + self.indent += 1 + tlist.tokens.insert(0, self.nl()) + indented = True + num_offset = self._get_offset(tlist.token_next_match(0, + T.Punctuation, '(')) + self.offset += num_offset + self._process_default(tlist, stmts=not indented) + if indented: + self.indent -= 1 + self.offset -= num_offset + + def _process_identifierlist(self, tlist): + identifiers = tlist.get_identifiers() + if len(identifiers) > 1 and not tlist.within(sql.Function): + first = list(identifiers[0].flatten())[0] + num_offset = self._get_offset(first)-len(first.value) + self.offset += num_offset + for token in identifiers[1:]: + tlist.insert_before(token, self.nl()) + self.offset -= num_offset + self._process_default(tlist) + + def _process_case(self, tlist): + cases = tlist.get_cases() + is_first = True + num_offset = None + case = tlist.tokens[0] + outer_offset = self._get_offset(case)-len(case.value) + self.offset += outer_offset + for cond, value in tlist.get_cases(): + if is_first: + is_first = False + num_offset = self._get_offset(cond[0])-len(cond[0].value) + self.offset += num_offset + continue + if cond is None: + token = value[0] + else: + token = cond[0] + tlist.insert_before(token, self.nl()) + # Line breaks on group level are done. Now let's add an offset of + # 5 (=length of "when", "then", "else") and process subgroups. + self.offset += 5 + self._process_default(tlist) + self.offset -= 5 + if num_offset is not None: + self.offset -= num_offset + end = tlist.token_next_match(0, T.Keyword, 'END') + tlist.insert_before(end, self.nl()) + self.offset -= outer_offset + + def _process_default(self, tlist, stmts=True, kwds=True): + if stmts: + self._split_statements(tlist) + if kwds: + self._split_kwds(tlist) + [self._process(sgroup) for sgroup in tlist.get_sublists()] + + def process(self, stack, stmt): + if isinstance(stmt, grouping.Statement): + self._curr_stmt = stmt + self._process(stmt) + if isinstance(stmt, grouping.Statement): + if self._last_stmt is not None: + if self._last_stmt.to_unicode().endswith('\n'): + nl = '\n' + else: + nl = '\n\n' + stmt.tokens.insert(0, + grouping.Token(T.Whitespace, nl)) + if self._last_stmt != stmt: + self._last_stmt = stmt + + +# FIXME: Doesn't work ;) +class RightMarginFilter(Filter): + + keep_together = ( +# grouping.TypeCast, grouping.Identifier, grouping.Alias, + ) + + def __init__(self, width=79): + self.width = width + self.line = '' + + def _process(self, stack, group, stream): + for token in stream: + if token.is_whitespace() and '\n' in token.value: + if token.value.endswith('\n'): + self.line = '' + else: + self.line = token.value.splitlines()[-1] + elif (token.is_group() + and not token.__class__ in self.keep_together): + token.tokens = self._process(stack, token, token.tokens) + else: + val = token.to_unicode() + if len(self.line) + len(val) > self.width: + match = re.search('^ +', self.line) + if match is not None: + indent = match.group() + else: + indent = '' + yield grouping.Token(T.Whitespace, '\n%s' % indent) + self.line = indent + self.line += val + yield token + + def process(self, stack, group): + return + group.tokens = self._process(stack, group, group.tokens) + + +# --------------------------- +# postprocess + +class SerializerUnicode(Filter): + + def process(self, stack, stmt): + raw = stmt.to_unicode() + add_nl = raw.endswith('\n') + res = '\n'.join(line.rstrip() for line in raw.splitlines()) + if add_nl: + res += '\n' + return res + + +class OutputPythonFilter(Filter): + + def __init__(self, varname='sql'): + self.varname = varname + self.cnt = 0 + + def _process(self, stream, varname, count, has_nl): + if count > 1: + yield grouping.Token(T.Whitespace, '\n') + yield grouping.Token(T.Name, varname) + yield grouping.Token(T.Whitespace, ' ') + yield grouping.Token(T.Operator, '=') + yield grouping.Token(T.Whitespace, ' ') + if has_nl: + yield grouping.Token(T.Operator, '(') + yield grouping.Token(T.Text, "'") + cnt = 0 + for token in stream: + cnt += 1 + if token.is_whitespace() and '\n' in token.value: + if cnt == 1: + continue + after_lb = token.value.split('\n', 1)[1] + yield grouping.Token(T.Text, " '") + yield grouping.Token(T.Whitespace, '\n') + for i in range(len(varname)+4): + yield grouping.Token(T.Whitespace, ' ') + yield grouping.Token(T.Text, "'") + if after_lb: # it's the indendation + yield grouping.Token(T.Whitespace, after_lb) + continue + elif token.value and "'" in token.value: + token.value = token.value.replace("'", "\\'") + yield grouping.Token(T.Text, token.value or '') + yield grouping.Token(T.Text, "'") + if has_nl: + yield grouping.Token(T.Operator, ')') + + def process(self, stack, stmt): + self.cnt += 1 + if self.cnt > 1: + varname = '%s%d' % (self.varname, self.cnt) + else: + varname = self.varname + has_nl = len(stmt.to_unicode().strip().splitlines()) > 1 + stmt.tokens = self._process(stmt.tokens, varname, self.cnt, has_nl) + return stmt + + +class OutputPHPFilter(Filter): + + def __init__(self, varname='sql'): + self.varname = '$%s' % varname + self.count = 0 + + def _process(self, stream, varname): + if self.count > 1: + yield grouping.Token(T.Whitespace, '\n') + yield grouping.Token(T.Name, varname) + yield grouping.Token(T.Whitespace, ' ') + yield grouping.Token(T.Operator, '=') + yield grouping.Token(T.Whitespace, ' ') + yield grouping.Token(T.Text, '"') + cnt = 0 + for token in stream: + if token.is_whitespace() and '\n' in token.value: +# cnt += 1 +# if cnt == 1: +# continue + after_lb = token.value.split('\n', 1)[1] + yield grouping.Token(T.Text, ' "') + yield grouping.Token(T.Operator, ';') + yield grouping.Token(T.Whitespace, '\n') + yield grouping.Token(T.Name, varname) + yield grouping.Token(T.Whitespace, ' ') + yield grouping.Token(T.Punctuation, '.') + yield grouping.Token(T.Operator, '=') + yield grouping.Token(T.Whitespace, ' ') + yield grouping.Token(T.Text, '"') + if after_lb: + yield grouping.Token(T.Text, after_lb) + continue + elif '"' in token.value: + token.value = token.value.replace('"', '\\"') + yield grouping.Token(T.Text, token.value) + yield grouping.Token(T.Text, '"') + yield grouping.Token(T.Punctuation, ';') + + def process(self, stack, stmt): + self.count += 1 + if self.count > 1: + varname = '%s%d' % (self.varname, self.count) + else: + varname = self.varname + stmt.tokens = tuple(self._process(stmt.tokens, varname)) + return stmt diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/formatter.py b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/formatter.py new file mode 100644 index 0000000..1955b5d --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/formatter.py @@ -0,0 +1,121 @@ +# Copyright (C) 2008 Andi Albrecht, albrecht.andi@gmail.com +# +# This module is part of python-sqlparse and is released under +# the BSD License: http://www.opensource.org/licenses/bsd-license.php. + +"""SQL formatter""" + +from sqlparse import SQLParseError +from sqlparse import filters + + +def validate_options(options): + """Validates options.""" + kwcase = options.get('keyword_case', None) + if kwcase not in [None, 'upper', 'lower', 'capitalize']: + raise SQLParseError('Invalid value for keyword_case: %r' % kwcase) + + idcase = options.get('identifier_case', None) + if idcase not in [None, 'upper', 'lower', 'capitalize']: + raise SQLParseError('Invalid value for identifier_case: %r' % idcase) + + ofrmt = options.get('output_format', None) + if ofrmt not in [None, 'sql', 'python', 'php']: + raise SQLParseError('Unknown output format: %r' % ofrmt) + + strip_comments = options.get('strip_comments', False) + if strip_comments not in [True, False]: + raise SQLParseError('Invalid value for strip_comments: %r' + % strip_comments) + + strip_ws = options.get('strip_whitespace', False) + if strip_ws not in [True, False]: + raise SQLParseError('Invalid value for strip_whitespace: %r' + % strip_ws) + + reindent = options.get('reindent', False) + if reindent not in [True, False]: + raise SQLParseError('Invalid value for reindent: %r' + % reindent) + elif reindent: + options['strip_whitespace'] = True + indent_tabs = options.get('indent_tabs', False) + if indent_tabs not in [True, False]: + raise SQLParseError('Invalid value for indent_tabs: %r' % indent_tabs) + elif indent_tabs: + options['indent_char'] = '\t' + else: + options['indent_char'] = ' ' + indent_width = options.get('indent_width', 2) + try: + indent_width = int(indent_width) + except (TypeError, ValueError): + raise SQLParseError('indent_width requires an integer') + if indent_width < 1: + raise SQLParseError('indent_width requires an positive integer') + options['indent_width'] = indent_width + + right_margin = options.get('right_margin', None) + if right_margin is not None: + try: + right_margin = int(right_margin) + except (TypeError, ValueError): + raise SQLParseError('right_margin requires an integer') + if right_margin < 10: + raise SQLParseError('right_margin requires an integer > 10') + options['right_margin'] = right_margin + + return options + + +def build_filter_stack(stack, options): + """Setup and return a filter stack. + + Args: + stack: :class:`~sqlparse.filters.FilterStack` instance + options: Dictionary with options validated by validate_options. + """ + # Token filter + if 'keyword_case' in options: + stack.preprocess.append( + filters.KeywordCaseFilter(options['keyword_case'])) + + if 'identifier_case' in options: + stack.preprocess.append( + filters.IdentifierCaseFilter(options['identifier_case'])) + + # After grouping + if options.get('strip_comments', False): + stack.enable_grouping() + stack.stmtprocess.append(filters.StripCommentsFilter()) + + if (options.get('strip_whitespace', False) + or options.get('reindent', False)): + stack.enable_grouping() + stack.stmtprocess.append(filters.StripWhitespaceFilter()) + + if options.get('reindent', False): + stack.enable_grouping() + stack.stmtprocess.append( + filters.ReindentFilter(char=options['indent_char'], + width=options['indent_width'])) + + if options.get('right_margin', False): + stack.enable_grouping() + stack.stmtprocess.append( + filters.RightMarginFilter(width=options['right_margin'])) + + # Serializer + if options.get('output_format'): + frmt = options['output_format'] + if frmt.lower() == 'php': + fltr = filters.OutputPHPFilter() + elif frmt.lower() == 'python': + fltr = filters.OutputPythonFilter() + else: + fltr = None + if fltr is not None: + stack.postprocess.append(fltr) + + return stack + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/keywords.py b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/keywords.py new file mode 100644 index 0000000..4a0bd1c --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/keywords.py @@ -0,0 +1,563 @@ +from sqlparse.tokens import * + +KEYWORDS = { + 'ABORT': Keyword, + 'ABS': Keyword, + 'ABSOLUTE': Keyword, + 'ACCESS': Keyword, + 'ADA': Keyword, + 'ADD': Keyword, + 'ADMIN': Keyword, + 'AFTER': Keyword, + 'AGGREGATE': Keyword, + 'ALIAS': Keyword, + 'ALL': Keyword, + 'ALLOCATE': Keyword, + 'ANALYSE': Keyword, + 'ANALYZE': Keyword, + 'ANY': Keyword, + 'ARE': Keyword, + 'ASC': Keyword, + 'ASENSITIVE': Keyword, + 'ASSERTION': Keyword, + 'ASSIGNMENT': Keyword, + 'ASYMMETRIC': Keyword, + 'AT': Keyword, + 'ATOMIC': Keyword, + 'AUTHORIZATION': Keyword, + 'AVG': Keyword, + + 'BACKWARD': Keyword, + 'BEFORE': Keyword, + 'BEGIN': Keyword, + 'BETWEEN': Keyword, + 'BITVAR': Keyword, + 'BIT_LENGTH': Keyword, + 'BOTH': Keyword, + 'BREADTH': Keyword, + +# 'C': Keyword, # most likely this is an alias + 'CACHE': Keyword, + 'CALL': Keyword, + 'CALLED': Keyword, + 'CARDINALITY': Keyword, + 'CASCADE': Keyword, + 'CASCADED': Keyword, + 'CAST': Keyword, + 'CATALOG': Keyword, + 'CATALOG_NAME': Keyword, + 'CHAIN': Keyword, + 'CHARACTERISTICS': Keyword, + 'CHARACTER_LENGTH': Keyword, + 'CHARACTER_SET_CATALOG': Keyword, + 'CHARACTER_SET_NAME': Keyword, + 'CHARACTER_SET_SCHEMA': Keyword, + 'CHAR_LENGTH': Keyword, + 'CHECK': Keyword, + 'CHECKED': Keyword, + 'CHECKPOINT': Keyword, + 'CLASS': Keyword, + 'CLASS_ORIGIN': Keyword, + 'CLOB': Keyword, + 'CLOSE': Keyword, + 'CLUSTER': Keyword, + 'COALSECE': Keyword, + 'COBOL': Keyword, + 'COLLATE': Keyword, + 'COLLATION': Keyword, + 'COLLATION_CATALOG': Keyword, + 'COLLATION_NAME': Keyword, + 'COLLATION_SCHEMA': Keyword, + 'COLUMN': Keyword, + 'COLUMN_NAME': Keyword, + 'COMMAND_FUNCTION': Keyword, + 'COMMAND_FUNCTION_CODE': Keyword, + 'COMMENT': Keyword, + 'COMMIT': Keyword, + 'COMMITTED': Keyword, + 'COMPLETION': Keyword, + 'CONDITION_NUMBER': Keyword, + 'CONNECT': Keyword, + 'CONNECTION': Keyword, + 'CONNECTION_NAME': Keyword, + 'CONSTRAINT': Keyword, + 'CONSTRAINTS': Keyword, + 'CONSTRAINT_CATALOG': Keyword, + 'CONSTRAINT_NAME': Keyword, + 'CONSTRAINT_SCHEMA': Keyword, + 'CONSTRUCTOR': Keyword, + 'CONTINUE': Keyword, + 'CONVERSION': Keyword, + 'CONVERT': Keyword, + 'COPY': Keyword, + 'CORRESPONTING': Keyword, + 'COUNT': Keyword, + 'CREATEDB': Keyword, + 'CREATEUSER': Keyword, + 'CROSS': Keyword, + 'CUBE': Keyword, + 'CURRENT': Keyword, + 'CURRENT_DATE': Keyword, + 'CURRENT_PATH': Keyword, + 'CURRENT_ROLE': Keyword, + 'CURRENT_TIME': Keyword, + 'CURRENT_TIMESTAMP': Keyword, + 'CURRENT_USER': Keyword, + 'CURSOR': Keyword, + 'CURSOR_NAME': Keyword, + 'CYCLE': Keyword, + + 'DATA': Keyword, + 'DATABASE': Keyword, + 'DATETIME_INTERVAL_CODE': Keyword, + 'DATETIME_INTERVAL_PRECISION': Keyword, + 'DAY': Keyword, + 'DEALLOCATE': Keyword, + 'DECLARE': Keyword, + 'DEFAULT': Keyword, + 'DEFAULTS': Keyword, + 'DEFERRABLE': Keyword, + 'DEFERRED': Keyword, + 'DEFINED': Keyword, + 'DEFINER': Keyword, + 'DELIMITER': Keyword, + 'DELIMITERS': Keyword, + 'DEREF': Keyword, + 'DESC': Keyword, + 'DESCRIBE': Keyword, + 'DESCRIPTOR': Keyword, + 'DESTROY': Keyword, + 'DESTRUCTOR': Keyword, + 'DETERMINISTIC': Keyword, + 'DIAGNOSTICS': Keyword, + 'DICTIONARY': Keyword, + 'DISCONNECT': Keyword, + 'DISPATCH': Keyword, + 'DO': Keyword, + 'DOMAIN': Keyword, + 'DYNAMIC': Keyword, + 'DYNAMIC_FUNCTION': Keyword, + 'DYNAMIC_FUNCTION_CODE': Keyword, + + 'EACH': Keyword, + 'ENCODING': Keyword, + 'ENCRYPTED': Keyword, + 'END-EXEC': Keyword, + 'EQUALS': Keyword, + 'ESCAPE': Keyword, + 'EVERY': Keyword, + 'EXCEPT': Keyword, + 'ESCEPTION': Keyword, + 'EXCLUDING': Keyword, + 'EXCLUSIVE': Keyword, + 'EXEC': Keyword, + 'EXECUTE': Keyword, + 'EXISTING': Keyword, + 'EXISTS': Keyword, + 'EXTERNAL': Keyword, + 'EXTRACT': Keyword, + + 'FALSE': Keyword, + 'FETCH': Keyword, + 'FINAL': Keyword, + 'FIRST': Keyword, + 'FORCE': Keyword, + 'FOREIGN': Keyword, + 'FORTRAN': Keyword, + 'FORWARD': Keyword, + 'FOUND': Keyword, + 'FREE': Keyword, + 'FREEZE': Keyword, + 'FULL': Keyword, + 'FUNCTION': Keyword, + + 'G': Keyword, + 'GENERAL': Keyword, + 'GENERATED': Keyword, + 'GET': Keyword, + 'GLOBAL': Keyword, + 'GO': Keyword, + 'GOTO': Keyword, + 'GRANT': Keyword, + 'GRANTED': Keyword, + 'GROUPING': Keyword, + + 'HANDLER': Keyword, + 'HAVING': Keyword, + 'HIERARCHY': Keyword, + 'HOLD': Keyword, + 'HOST': Keyword, + + 'IDENTITY': Keyword, + 'IGNORE': Keyword, + 'ILIKE': Keyword, + 'IMMEDIATE': Keyword, + 'IMMUTABLE': Keyword, + + 'IMPLEMENTATION': Keyword, + 'IMPLICIT': Keyword, + 'INCLUDING': Keyword, + 'INCREMENT': Keyword, + 'INDEX': Keyword, + + 'INDITCATOR': Keyword, + 'INFIX': Keyword, + 'INHERITS': Keyword, + 'INITIALIZE': Keyword, + 'INITIALLY': Keyword, + 'INOUT': Keyword, + 'INPUT': Keyword, + 'INSENSITIVE': Keyword, + 'INSTANTIABLE': Keyword, + 'INSTEAD': Keyword, + 'INTERSECT': Keyword, + 'INTO': Keyword, + 'INVOKER': Keyword, + 'IS': Keyword, + 'ISNULL': Keyword, + 'ISOLATION': Keyword, + 'ITERATE': Keyword, + + 'K': Keyword, + 'KEY': Keyword, + 'KEY_MEMBER': Keyword, + 'KEY_TYPE': Keyword, + + 'LANCOMPILER': Keyword, + 'LANGUAGE': Keyword, + 'LARGE': Keyword, + 'LAST': Keyword, + 'LATERAL': Keyword, + 'LEADING': Keyword, + 'LENGTH': Keyword, + 'LESS': Keyword, + 'LEVEL': Keyword, + 'LIMIT': Keyword, + 'LISTEN': Keyword, + 'LOAD': Keyword, + 'LOCAL': Keyword, + 'LOCALTIME': Keyword, + 'LOCALTIMESTAMP': Keyword, + 'LOCATION': Keyword, + 'LOCATOR': Keyword, + 'LOCK': Keyword, + 'LOWER': Keyword, + + 'M': Keyword, + 'MAP': Keyword, + 'MATCH': Keyword, + 'MAXVALUE': Keyword, + 'MESSAGE_LENGTH': Keyword, + 'MESSAGE_OCTET_LENGTH': Keyword, + 'MESSAGE_TEXT': Keyword, + 'METHOD': Keyword, + 'MINUTE': Keyword, + 'MINVALUE': Keyword, + 'MOD': Keyword, + 'MODE': Keyword, + 'MODIFIES': Keyword, + 'MODIFY': Keyword, + 'MONTH': Keyword, + 'MORE': Keyword, + 'MOVE': Keyword, + 'MUMPS': Keyword, + + 'NAMES': Keyword, + 'NATIONAL': Keyword, + 'NATURAL': Keyword, + 'NCHAR': Keyword, + 'NCLOB': Keyword, + 'NEW': Keyword, + 'NEXT': Keyword, + 'NO': Keyword, + 'NOCREATEDB': Keyword, + 'NOCREATEUSER': Keyword, + 'NONE': Keyword, + 'NOT': Keyword, + 'NOTHING': Keyword, + 'NOTIFY': Keyword, + 'NOTNULL': Keyword, + 'NULL': Keyword, + 'NULLABLE': Keyword, + 'NULLIF': Keyword, + + 'OBJECT': Keyword, + 'OCTET_LENGTH': Keyword, + 'OF': Keyword, + 'OFF': Keyword, + 'OFFSET': Keyword, + 'OIDS': Keyword, + 'OLD': Keyword, + 'ONLY': Keyword, + 'OPEN': Keyword, + 'OPERATION': Keyword, + 'OPERATOR': Keyword, + 'OPTION': Keyword, + 'OPTIONS': Keyword, + 'ORDINALITY': Keyword, + 'OUT': Keyword, + 'OUTPUT': Keyword, + 'OVERLAPS': Keyword, + 'OVERLAY': Keyword, + 'OVERRIDING': Keyword, + 'OWNER': Keyword, + + 'PAD': Keyword, + 'PARAMETER': Keyword, + 'PARAMETERS': Keyword, + 'PARAMETER_MODE': Keyword, + 'PARAMATER_NAME': Keyword, + 'PARAMATER_ORDINAL_POSITION': Keyword, + 'PARAMETER_SPECIFIC_CATALOG': Keyword, + 'PARAMETER_SPECIFIC_NAME': Keyword, + 'PARAMATER_SPECIFIC_SCHEMA': Keyword, + 'PARTIAL': Keyword, + 'PASCAL': Keyword, + 'PENDANT': Keyword, + 'PLACING': Keyword, + 'PLI': Keyword, + 'POSITION': Keyword, + 'POSTFIX': Keyword, + 'PRECISION': Keyword, + 'PREFIX': Keyword, + 'PREORDER': Keyword, + 'PREPARE': Keyword, + 'PRESERVE': Keyword, + 'PRIMARY': Keyword, + 'PRIOR': Keyword, + 'PRIVILEGES': Keyword, + 'PROCEDURAL': Keyword, + 'PROCEDURE': Keyword, + 'PUBLIC': Keyword, + + 'RAISE': Keyword, + 'READ': Keyword, + 'READS': Keyword, + 'RECHECK': Keyword, + 'RECURSIVE': Keyword, + 'REF': Keyword, + 'REFERENCES': Keyword, + 'REFERENCING': Keyword, + 'REINDEX': Keyword, + 'RELATIVE': Keyword, + 'RENAME': Keyword, + 'REPEATABLE': Keyword, + 'REPLACE': Keyword, + 'RESET': Keyword, + 'RESTART': Keyword, + 'RESTRICT': Keyword, + 'RESULT': Keyword, + 'RETURN': Keyword, + 'RETURNED_LENGTH': Keyword, + 'RETURNED_OCTET_LENGTH': Keyword, + 'RETURNED_SQLSTATE': Keyword, + 'RETURNS': Keyword, + 'REVOKE': Keyword, + 'RIGHT': Keyword, + 'ROLE': Keyword, + 'ROLLBACK': Keyword, + 'ROLLUP': Keyword, + 'ROUTINE': Keyword, + 'ROUTINE_CATALOG': Keyword, + 'ROUTINE_NAME': Keyword, + 'ROUTINE_SCHEMA': Keyword, + 'ROW': Keyword, + 'ROWS': Keyword, + 'ROW_COUNT': Keyword, + 'RULE': Keyword, + + 'SAVE_POINT': Keyword, + 'SCALE': Keyword, + 'SCHEMA': Keyword, + 'SCHEMA_NAME': Keyword, + 'SCOPE': Keyword, + 'SCROLL': Keyword, + 'SEARCH': Keyword, + 'SECOND': Keyword, + 'SECURITY': Keyword, + 'SELF': Keyword, + 'SENSITIVE': Keyword, + 'SERIALIZABLE': Keyword, + 'SERVER_NAME': Keyword, + 'SESSION': Keyword, + 'SESSION_USER': Keyword, + 'SETOF': Keyword, + 'SETS': Keyword, + 'SHARE': Keyword, + 'SHOW': Keyword, + 'SIMILAR': Keyword, + 'SIMPLE': Keyword, + 'SIZE': Keyword, + 'SOME': Keyword, + 'SOURCE': Keyword, + 'SPACE': Keyword, + 'SPECIFIC': Keyword, + 'SPECIFICTYPE': Keyword, + 'SPECIFIC_NAME': Keyword, + 'SQL': Keyword, + 'SQLCODE': Keyword, + 'SQLERROR': Keyword, + 'SQLEXCEPTION': Keyword, + 'SQLSTATE': Keyword, + 'SQLWARNINIG': Keyword, + 'STABLE': Keyword, + 'START': Keyword, + 'STATE': Keyword, + 'STATEMENT': Keyword, + 'STATIC': Keyword, + 'STATISTICS': Keyword, + 'STDIN': Keyword, + 'STDOUT': Keyword, + 'STORAGE': Keyword, + 'STRICT': Keyword, + 'STRUCTURE': Keyword, + 'STYPE': Keyword, + 'SUBCLASS_ORIGIN': Keyword, + 'SUBLIST': Keyword, + 'SUBSTRING': Keyword, + 'SUM': Keyword, + 'SYMMETRIC': Keyword, + 'SYSID': Keyword, + 'SYSTEM': Keyword, + 'SYSTEM_USER': Keyword, + + 'TABLE': Keyword, + 'TABLE_NAME': Keyword, + ' TEMP': Keyword, + 'TEMPLATE': Keyword, + 'TEMPORARY': Keyword, + 'TERMINATE': Keyword, + 'THAN': Keyword, + 'TIMESTAMP': Keyword, + 'TIMEZONE_HOUR': Keyword, + 'TIMEZONE_MINUTE': Keyword, + 'TO': Keyword, + 'TOAST': Keyword, + 'TRAILING': Keyword, + 'TRANSATION': Keyword, + 'TRANSACTIONS_COMMITTED': Keyword, + 'TRANSACTIONS_ROLLED_BACK': Keyword, + 'TRANSATION_ACTIVE': Keyword, + 'TRANSFORM': Keyword, + 'TRANSFORMS': Keyword, + 'TRANSLATE': Keyword, + 'TRANSLATION': Keyword, + 'TREAT': Keyword, + 'TRIGGER': Keyword, + 'TRIGGER_CATALOG': Keyword, + 'TRIGGER_NAME': Keyword, + 'TRIGGER_SCHEMA': Keyword, + 'TRIM': Keyword, + 'TRUE': Keyword, + 'TRUNCATE': Keyword, + 'TRUSTED': Keyword, + 'TYPE': Keyword, + + 'UNCOMMITTED': Keyword, + 'UNDER': Keyword, + 'UNENCRYPTED': Keyword, + 'UNION': Keyword, + 'UNIQUE': Keyword, + 'UNKNOWN': Keyword, + 'UNLISTEN': Keyword, + 'UNNAMED': Keyword, + 'UNNEST': Keyword, + 'UNTIL': Keyword, + 'UPPER': Keyword, + 'USAGE': Keyword, + 'USER': Keyword, + 'USER_DEFINED_TYPE_CATALOG': Keyword, + 'USER_DEFINED_TYPE_NAME': Keyword, + 'USER_DEFINED_TYPE_SCHEMA': Keyword, + 'USING': Keyword, + + 'VACUUM': Keyword, + 'VALID': Keyword, + 'VALIDATOR': Keyword, + 'VALUES': Keyword, + 'VARIABLE': Keyword, + 'VERBOSE': Keyword, + 'VERSION': Keyword, + 'VIEW': Keyword, + 'VOLATILE': Keyword, + + 'WHENEVER': Keyword, + 'WITH': Keyword, + 'WITHOUT': Keyword, + 'WORK': Keyword, + 'WRITE': Keyword, + + 'YEAR': Keyword, + + 'ZONE': Keyword, + + + 'ARRAY': Name.Builtin, + 'BIGINT': Name.Builtin, + 'BINARY': Name.Builtin, + 'BIT': Name.Builtin, + 'BLOB': Name.Builtin, + 'BOOLEAN': Name.Builtin, + 'CHAR': Name.Builtin, + 'CHARACTER': Name.Builtin, + 'DATE': Name.Builtin, + 'DEC': Name.Builtin, + 'DECIMAL': Name.Builtin, + 'FLOAT': Name.Builtin, + 'INT': Name.Builtin, + 'INTEGER': Name.Builtin, + 'INTERVAL': Name.Builtin, + 'NUMBER': Name.Builtin, + 'NUMERIC': Name.Builtin, + 'REAL': Name.Builtin, + 'SERIAL': Name.Builtin, + 'SMALLINT': Name.Builtin, + 'VARCHAR': Name.Builtin, + 'VARYING': Name.Builtin, + 'INT8': Name.Builtin, + 'SERIAL8': Name.Builtin, + 'TEXT': Name.Builtin, + } + + +KEYWORDS_COMMON = { + 'SELECT': Keyword.DML, + 'INSERT': Keyword.DML, + 'DELETE': Keyword.DML, + 'UPDATE': Keyword.DML, + 'DROP': Keyword.DDL, + 'CREATE': Keyword.DDL, + 'ALTER': Keyword.DDL, + + 'WHERE': Keyword, + 'FROM': Keyword, + 'INNER': Keyword, + 'JOIN': Keyword, + 'AND': Keyword, + 'OR': Keyword, + 'LIKE': Keyword, + 'ON': Keyword, + 'IN': Keyword, + 'SET': Keyword, + + 'BY': Keyword, + 'GROUP': Keyword, + 'ORDER': Keyword, + 'LEFT': Keyword, + 'OUTER': Keyword, + + 'IF': Keyword, + 'END': Keyword, + 'THEN': Keyword, + 'LOOP': Keyword, + 'AS': Keyword, + 'ELSE': Keyword, + 'FOR': Keyword, + + 'CASE': Keyword, + 'WHEN': Keyword, + 'MIN': Keyword, + 'MAX': Keyword, + 'DISTINCT': Keyword, + + } diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/lexer.py b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/lexer.py new file mode 100644 index 0000000..a416c16 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/lexer.py @@ -0,0 +1,320 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2008 Andi Albrecht, albrecht.andi@gmail.com +# +# This module is part of python-sqlparse and is released under +# the BSD License: http://www.opensource.org/licenses/bsd-license.php. + +"""SQL Lexer""" + +# This code is based on the SqlLexer in pygments. +# http://pygments.org/ +# It's separated from the rest of pygments to increase performance +# and to allow some customizations. + +import re + +from sqlparse.keywords import KEYWORDS, KEYWORDS_COMMON +from sqlparse.tokens import * +from sqlparse.tokens import _TokenType + + +class include(str): + pass + +class combined(tuple): + """Indicates a state combined from multiple states.""" + + def __new__(cls, *args): + return tuple.__new__(cls, args) + + def __init__(self, *args): + # tuple.__init__ doesn't do anything + pass + +def is_keyword(value): + test = value.upper() + return KEYWORDS_COMMON.get(test, KEYWORDS.get(test, Name)), value + + +def apply_filters(stream, filters, lexer=None): + """ + Use this method to apply an iterable of filters to + a stream. If lexer is given it's forwarded to the + filter, otherwise the filter receives `None`. + """ + + def _apply(filter_, stream): + for token in filter_.filter(lexer, stream): + yield token + + for filter_ in filters: + stream = _apply(filter_, stream) + return stream + + +class LexerMeta(type): + """ + Metaclass for Lexer, creates the self._tokens attribute from + self.tokens on the first instantiation. + """ + + def _process_state(cls, unprocessed, processed, state): + assert type(state) is str, "wrong state name %r" % state + assert state[0] != '#', "invalid state name %r" % state + if state in processed: + return processed[state] + tokens = processed[state] = [] + rflags = cls.flags + for tdef in unprocessed[state]: + if isinstance(tdef, include): + # it's a state reference + assert tdef != state, "circular state reference %r" % state + tokens.extend(cls._process_state( + unprocessed, processed, str(tdef))) + continue + + assert type(tdef) is tuple, "wrong rule def %r" % tdef + + try: + rex = re.compile(tdef[0], rflags).match + except Exception, err: + raise ValueError(("uncompilable regex %r in state" + " %r of %r: %s" + % (tdef[0], state, cls, err))) + + assert type(tdef[1]) is _TokenType or callable(tdef[1]), \ + 'token type must be simple type or callable, not %r' % (tdef[1],) + + if len(tdef) == 2: + new_state = None + else: + tdef2 = tdef[2] + if isinstance(tdef2, str): + # an existing state + if tdef2 == '#pop': + new_state = -1 + elif tdef2 in unprocessed: + new_state = (tdef2,) + elif tdef2 == '#push': + new_state = tdef2 + elif tdef2[:5] == '#pop:': + new_state = -int(tdef2[5:]) + else: + assert False, 'unknown new state %r' % tdef2 + elif isinstance(tdef2, combined): + # combine a new state from existing ones + new_state = '_tmp_%d' % cls._tmpname + cls._tmpname += 1 + itokens = [] + for istate in tdef2: + assert istate != state, 'circular state ref %r' % istate + itokens.extend(cls._process_state(unprocessed, + processed, istate)) + processed[new_state] = itokens + new_state = (new_state,) + elif isinstance(tdef2, tuple): + # push more than one state + for state in tdef2: + assert (state in unprocessed or + state in ('#pop', '#push')), \ + 'unknown new state ' + state + new_state = tdef2 + else: + assert False, 'unknown new state def %r' % tdef2 + tokens.append((rex, tdef[1], new_state)) + return tokens + + def process_tokendef(cls): + cls._all_tokens = {} + cls._tmpname = 0 + processed = cls._all_tokens[cls.__name__] = {} + #tokendefs = tokendefs or cls.tokens[name] + for state in cls.tokens.keys(): + cls._process_state(cls.tokens, processed, state) + return processed + + def __call__(cls, *args, **kwds): + if not hasattr(cls, '_tokens'): + cls._all_tokens = {} + cls._tmpname = 0 + if hasattr(cls, 'token_variants') and cls.token_variants: + # don't process yet + pass + else: + cls._tokens = cls.process_tokendef() + + return type.__call__(cls, *args, **kwds) + + + + +class Lexer: + + __metaclass__ = LexerMeta + + encoding = 'utf-8' + stripall = False + stripnl = False + tabsize = 0 + flags = re.IGNORECASE + + tokens = { + 'root': [ + (r'--.*?(\r|\n|\r\n)', Comment.Single), + (r'(\r|\n|\r\n)', Newline), + (r'\s+', Whitespace), + (r'/\*', Comment.Multiline, 'multiline-comments'), + (r':=', Assignment), + (r'::', Punctuation), + (r'[*]', Wildcard), + (r"`(``|[^`])*`", Name), + (r"´(´´|[^´])*´", Name), + (r'@[a-zA-Z_][a-zA-Z0-9_]+', Name), + (r'[<>=~!]+', Operator.Comparsion), + (r'[+/@#%^&|`?^-]+', Operator), + (r'[0-9]+', Number.Integer), + # TODO: Backslash escapes? + (r"'(''|[^'])*'", String.Single), + (r'"(""|[^"])*"', String.Symbol), # not a real string literal in ANSI SQL + (r'(LEFT |RIGHT )?(INNER |OUTER )?JOIN\b', Keyword), + (r'END( IF| LOOP)?\b', Keyword), + (r'CREATE( OR REPLACE)?\b', Keyword.DDL), + (r'[a-zA-Z_][a-zA-Z0-9_]*', is_keyword), + (r'\$([a-zA-Z_][a-zA-Z0-9_]*)?\$', Name.Builtin), + (r'[;:()\[\],\.]', Punctuation), + ], + 'multiline-comments': [ + (r'/\*', Comment.Multiline, 'multiline-comments'), + (r'\*/', Comment.Multiline, '#pop'), + (r'[^/\*]+', Comment.Multiline), + (r'[/*]', Comment.Multiline) + ] + } + + def __init__(self): + self.filters = [] + + def add_filter(self, filter_, **options): + from sqlparse.filters import Filter + if not isinstance(filter_, Filter): + filter_ = filter_(**options) + self.filters.append(filter_) + + def get_tokens(self, text, unfiltered=False): + """ + Return an iterable of (tokentype, value) pairs generated from + `text`. If `unfiltered` is set to `True`, the filtering mechanism + is bypassed even if filters are defined. + + Also preprocess the text, i.e. expand tabs and strip it if + wanted and applies registered filters. + """ + if not isinstance(text, unicode): + if self.encoding == 'guess': + try: + text = text.decode('utf-8') + if text.startswith(u'\ufeff'): + text = text[len(u'\ufeff'):] + except UnicodeDecodeError: + text = text.decode('latin1') + elif self.encoding == 'chardet': + try: + import chardet + except ImportError: + raise ImportError('To enable chardet encoding guessing, ' + 'please install the chardet library ' + 'from http://chardet.feedparser.org/') + enc = chardet.detect(text) + text = text.decode(enc['encoding']) + else: + text = text.decode(self.encoding) + if self.stripall: + text = text.strip() + elif self.stripnl: + text = text.strip('\n') + if self.tabsize > 0: + text = text.expandtabs(self.tabsize) +# if not text.endswith('\n'): +# text += '\n' + + def streamer(): + for i, t, v in self.get_tokens_unprocessed(text): + yield t, v + stream = streamer() + if not unfiltered: + stream = apply_filters(stream, self.filters, self) + return stream + + + def get_tokens_unprocessed(self, text, stack=('root',)): + """ + Split ``text`` into (tokentype, text) pairs. + + ``stack`` is the inital stack (default: ``['root']``) + """ + pos = 0 + tokendefs = self._tokens + statestack = list(stack) + statetokens = tokendefs[statestack[-1]] + known_names = {} + while 1: + for rexmatch, action, new_state in statetokens: + m = rexmatch(text, pos) + if m: + # print rex.pattern + value = m.group() + if value in known_names: + yield pos, known_names[value], value + elif type(action) is _TokenType: + yield pos, action, value + elif hasattr(action, '__call__'): + ttype, value = action(value) + known_names[value] = ttype + yield pos, ttype, value + else: + for item in action(self, m): + yield item + pos = m.end() + if new_state is not None: + # state transition + if isinstance(new_state, tuple): + for state in new_state: + if state == '#pop': + statestack.pop() + elif state == '#push': + statestack.append(statestack[-1]) + else: + statestack.append(state) + elif isinstance(new_state, int): + # pop + del statestack[new_state:] + elif new_state == '#push': + statestack.append(statestack[-1]) + else: + assert False, "wrong state def: %r" % new_state + statetokens = tokendefs[statestack[-1]] + break + else: + try: + if text[pos] == '\n': + # at EOL, reset state to "root" + pos += 1 + statestack = ['root'] + statetokens = tokendefs['root'] + yield pos, Text, u'\n' + continue + yield pos, Error, text[pos] + pos += 1 + except IndexError: + break + + +def tokenize(sql): + """Tokenize sql. + + Tokenize *sql* using the :class:`Lexer` and return a 2-tuple stream + of ``(token type, value)`` items. + """ + lexer = Lexer() + return lexer.get_tokens(sql) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/sql.py b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/sql.py new file mode 100644 index 0000000..195696e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/sql.py @@ -0,0 +1,508 @@ +# -*- coding: utf-8 -*- + +"""This module contains classes representing syntactical elements of SQL.""" + +import re + +from sqlparse import tokens as T + + +class Token(object): + """Base class for all other classes in this module. + + It represents a single token and has two instance attributes: + ``value`` is the unchange value of the token and ``ttype`` is + the type of the token. + """ + + __slots__ = ('value', 'ttype', 'parent') + + def __init__(self, ttype, value): + self.value = value + self.ttype = ttype + self.parent = None + + def __str__(self): + return unicode(self).encode('utf-8') + + def __repr__(self): + short = self._get_repr_value() + return '<%s \'%s\' at 0x%07x>' % (self._get_repr_name(), + short, id(self)) + + def __unicode__(self): + return self.value or '' + + def to_unicode(self): + """Returns a unicode representation of this object.""" + return unicode(self) + + def _get_repr_name(self): + return str(self.ttype).split('.')[-1] + + def _get_repr_value(self): + raw = unicode(self) + if len(raw) > 7: + short = raw[:6]+u'...' + else: + short = raw + return re.sub('\s+', ' ', short) + + def flatten(self): + """Resolve subgroups.""" + yield self + + def match(self, ttype, values, regex=False): + """Checks whether the token matches the given arguments. + + *ttype* is a token type. If this token doesn't match the given token + type. + *values* is a list of possible values for this token. The values + are OR'ed together so if only one of the values matches ``True`` + is returned. Except for keyword tokens the comparsion is + case-sensitive. For convenience it's ok to pass in a single string. + If *regex* is ``True`` (default is ``False``) the given values are + treated as regular expressions. + """ + type_matched = self.ttype is ttype + if not type_matched or values is None: + return type_matched + if isinstance(values, basestring): + values = set([values]) + if regex: + if self.ttype is T.Keyword: + values = set([re.compile(v, re.IGNORECASE) for v in values]) + else: + values = set([re.compile(v) for v in values]) + for pattern in values: + if pattern.search(self.value): + return True + return False + else: + if self.ttype is T.Keyword: + values = set([v.upper() for v in values]) + return self.value.upper() in values + else: + return self.value in values + + def is_group(self): + """Returns ``True`` if this object has children.""" + return False + + def is_whitespace(self): + """Return ``True`` if this token is a whitespace token.""" + return self.ttype and self.ttype in T.Whitespace + + def within(self, group_cls): + """Returns ``True`` if this token is within *group_cls*. + + Use this method for example to check if an identifier is within + a function: ``t.within(sql.Function)``. + """ + parent = self.parent + while parent: + if isinstance(parent, group_cls): + return True + parent = parent.parent + return False + + def is_child_of(self, other): + """Returns ``True`` if this token is a direct child of *other*.""" + return self.parent == other + + def has_ancestor(self, other): + """Returns ``True`` if *other* is in this tokens ancestry.""" + parent = self.parent + while parent: + if parent == other: + return True + parent = parent.parent + return False + + +class TokenList(Token): + """A group of tokens. + + It has an additional instance attribute ``tokens`` which holds a + list of child-tokens. + """ + + __slots__ = ('value', 'ttype', 'tokens') + + def __init__(self, tokens=None): + if tokens is None: + tokens = [] + self.tokens = tokens + Token.__init__(self, None, None) + + def __unicode__(self): + return ''.join(unicode(x) for x in self.flatten()) + + def __str__(self): + return unicode(self).encode('utf-8') + + def _get_repr_name(self): + return self.__class__.__name__ + + ## def _pprint_tree(self, max_depth=None, depth=0): + ## """Pretty-print the object tree.""" + ## indent = ' '*(depth*2) + ## for token in self.tokens: + ## if token.is_group(): + ## pre = ' | ' + ## else: + ## pre = ' | ' + ## print '%s%s%s \'%s\'' % (indent, pre, token._get_repr_name(), + ## token._get_repr_value()) + ## if (token.is_group() and max_depth is not None + ## and depth < max_depth): + ## token._pprint_tree(max_depth, depth+1) + + def flatten(self): + """Generator yielding ungrouped tokens. + + This method is recursively called for all child tokens. + """ + for token in self.tokens: + if isinstance(token, TokenList): + for item in token.flatten(): + yield item + else: + yield token + + def is_group(self): + return True + + def get_sublists(self): + return [x for x in self.tokens if isinstance(x, TokenList)] + + @property + def _groupable_tokens(self): + return self.tokens + + def token_first(self, ignore_whitespace=True): + """Returns the first child token. + + If *ignore_whitespace* is ``True`` (the default), whitespace + tokens are ignored. + """ + for token in self.tokens: + if ignore_whitespace and token.is_whitespace(): + continue + return token + return None + + def token_next_by_instance(self, idx, clss): + """Returns the next token matching a class. + + *idx* is where to start searching in the list of child tokens. + *clss* is a list of classes the token should be an instance of. + + If no matching token can be found ``None`` is returned. + """ + if isinstance(clss, (list, tuple)): + clss = (clss,) + if isinstance(clss, tuple): + clss = tuple(clss) + for token in self.tokens[idx:]: + if isinstance(token, clss): + return token + return None + + def token_next_by_type(self, idx, ttypes): + """Returns next matching token by it's token type.""" + if not isinstance(ttypes, (list, tuple)): + ttypes = [ttypes] + for token in self.tokens[idx:]: + if token.ttype in ttypes: + return token + return None + + def token_next_match(self, idx, ttype, value, regex=False): + """Returns next token where it's ``match`` method returns ``True``.""" + if not isinstance(idx, int): + idx = self.token_index(idx) + for token in self.tokens[idx:]: + if token.match(ttype, value, regex): + return token + return None + + def token_not_matching(self, idx, funcs): + for token in self.tokens[idx:]: + passed = False + for func in funcs: + if func(token): + passed = True + break + if not passed: + return token + return None + + def token_matching(self, idx, funcs): + for token in self.tokens[idx:]: + for i, func in enumerate(funcs): + if func(token): + return token + return None + + def token_prev(self, idx, skip_ws=True): + """Returns the previous token relative to *idx*. + + If *skip_ws* is ``True`` (the default) whitespace tokens are ignored. + ``None`` is returned if there's no previous token. + """ + if idx is None: + return None + if not isinstance(idx, int): + idx = self.token_index(idx) + while idx != 0: + idx -= 1 + if self.tokens[idx].is_whitespace() and skip_ws: + continue + return self.tokens[idx] + + def token_next(self, idx, skip_ws=True): + """Returns the next token relative to *idx*. + + If *skip_ws* is ``True`` (the default) whitespace tokens are ignored. + ``None`` is returned if there's no next token. + """ + if idx is None: + return None + if not isinstance(idx, int): + idx = self.token_index(idx) + while idx < len(self.tokens)-1: + idx += 1 + if self.tokens[idx].is_whitespace() and skip_ws: + continue + return self.tokens[idx] + + def token_index(self, token): + """Return list index of token.""" + return self.tokens.index(token) + + def tokens_between(self, start, end, exclude_end=False): + """Return all tokens between (and including) start and end. + + If *exclude_end* is ``True`` (default is ``False``) the end token + is included too. + """ + if exclude_end: + offset = 0 + else: + offset = 1 + return self.tokens[self.token_index(start):self.token_index(end)+offset] + + def group_tokens(self, grp_cls, tokens): + """Replace tokens by an instance of *grp_cls*.""" + idx = self.token_index(tokens[0]) + for t in tokens: + self.tokens.remove(t) + grp = grp_cls(tokens) + for token in tokens: + token.parent = grp + grp.parent = self + self.tokens.insert(idx, grp) + return grp + + def insert_before(self, where, token): + """Inserts *token* before *where*.""" + self.tokens.insert(self.token_index(where), token) + + +class Statement(TokenList): + """Represents a SQL statement.""" + + __slots__ = ('value', 'ttype', 'tokens') + + def get_type(self): + """Returns the type of a statement. + + The returned value is a string holding an upper-cased reprint of + the first DML or DDL keyword. If the first token in this group + isn't a DML or DDL keyword "UNKNOWN" is returned. + """ + first_token = self.token_first() + if first_token.ttype in (T.Keyword.DML, T.Keyword.DDL): + return first_token.value.upper() + else: + return 'UNKNOWN' + + +class Identifier(TokenList): + """Represents an identifier. + + Identifiers may have aliases or typecasts. + """ + + __slots__ = ('value', 'ttype', 'tokens') + + def has_alias(self): + """Returns ``True`` if an alias is present.""" + return self.get_alias() is not None + + def get_alias(self): + """Returns the alias for this identifier or ``None``.""" + kw = self.token_next_match(0, T.Keyword, 'AS') + if kw is not None: + alias = self.token_next(self.token_index(kw)) + if alias is None: + return None + else: + next_ = self.token_next(0) + if next_ is None or not isinstance(next_, Identifier): + return None + alias = next_ + if isinstance(alias, Identifier): + return alias.get_name() + else: + return alias.to_unicode() + + def get_name(self): + """Returns the name of this identifier. + + This is either it's alias or it's real name. The returned valued can + be considered as the name under which the object corresponding to + this identifier is known within the current statement. + """ + alias = self.get_alias() + if alias is not None: + return alias + return self.get_real_name() + + def get_real_name(self): + """Returns the real name (object name) of this identifier.""" + # a.b + dot = self.token_next_match(0, T.Punctuation, '.') + if dot is None: + return self.token_next_by_type(0, T.Name).value + else: + next_ = self.token_next_by_type(self.token_index(dot), + (T.Name, T.Wildcard)) + if next_ is None: # invalid identifier, e.g. "a." + return None + return next_.value + + def get_parent_name(self): + """Return name of the parent object if any. + + A parent object is identified by the first occuring dot. + """ + dot = self.token_next_match(0, T.Punctuation, '.') + if dot is None: + return None + prev_ = self.token_prev(self.token_index(dot)) + if prev_ is None: # something must be verry wrong here.. + return None + return prev_.value + + def is_wildcard(self): + """Return ``True`` if this identifier contains a wildcard.""" + token = self.token_next_by_type(0, T.Wildcard) + return token is not None + + def get_typecast(self): + """Returns the typecast or ``None`` of this object as a string.""" + marker = self.token_next_match(0, T.Punctuation, '::') + if marker is None: + return None + next_ = self.token_next(self.token_index(marker), False) + if next_ is None: + return None + return next_.to_unicode() + + +class IdentifierList(TokenList): + """A list of :class:`~sqlparse.sql.Identifier`\'s.""" + + __slots__ = ('value', 'ttype', 'tokens') + + def get_identifiers(self): + """Returns the identifiers. + + Whitespaces and punctuations are not included in this list. + """ + return [x for x in self.tokens + if not x.is_whitespace() and not x.match(T.Punctuation, ',')] + + +class Parenthesis(TokenList): + """Tokens between parenthesis.""" + __slots__ = ('value', 'ttype', 'tokens') + + @property + def _groupable_tokens(self): + return self.tokens[1:-1] + + +class Assignment(TokenList): + """An assignment like 'var := val;'""" + __slots__ = ('value', 'ttype', 'tokens') + +class If(TokenList): + """An 'if' clause with possible 'else if' or 'else' parts.""" + __slots__ = ('value', 'ttype', 'tokens') + +class For(TokenList): + """A 'FOR' loop.""" + __slots__ = ('value', 'ttype', 'tokens') + +class Comparsion(TokenList): + """A comparsion used for example in WHERE clauses.""" + __slots__ = ('value', 'ttype', 'tokens') + +class Comment(TokenList): + """A comment.""" + __slots__ = ('value', 'ttype', 'tokens') + +class Where(TokenList): + """A WHERE clause.""" + __slots__ = ('value', 'ttype', 'tokens') + + +class Case(TokenList): + """A CASE statement with one or more WHEN and possibly an ELSE part.""" + + __slots__ = ('value', 'ttype', 'tokens') + + def get_cases(self): + """Returns a list of 2-tuples (condition, value). + + If an ELSE exists condition is None. + """ + ret = [] + in_condition = in_value = False + for token in self.tokens: + if token.match(T.Keyword, 'WHEN'): + ret.append(([], [])) + in_condition = True + in_value = False + elif token.match(T.Keyword, 'ELSE'): + ret.append((None, [])) + in_condition = False + in_value = True + elif token.match(T.Keyword, 'THEN'): + in_condition = False + in_value = True + elif token.match(T.Keyword, 'END'): + in_condition = False + in_value = False + if in_condition: + ret[-1][0].append(token) + elif in_value: + ret[-1][1].append(token) + return ret + + +class Function(TokenList): + """A function or procedure call.""" + + __slots__ = ('value', 'ttype', 'tokens') + + def get_parameters(self): + """Return a list of parameters.""" + parenthesis = self.tokens[-1] + for t in parenthesis.tokens: + if isinstance(t, IdentifierList): + return t.get_identifiers() + return [] diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/tokens.py b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/tokens.py new file mode 100644 index 0000000..5d1458a --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/sqlparse/tokens.py @@ -0,0 +1,84 @@ +# Copyright (C) 2008 Andi Albrecht, albrecht.andi@gmail.com +# +# This module is part of python-sqlparse and is released under +# the BSD License: http://www.opensource.org/licenses/bsd-license.php. + +# The Token implementation is based on pygment's token system written +# by Georg Brandl. +# http://pygments.org/ + +"""Tokens""" + + +class _TokenType(tuple): + parent = None + + def split(self): + buf = [] + node = self + while node is not None: + buf.append(node) + node = node.parent + buf.reverse() + return buf + + def __contains__(self, val): + return val is not None and (self is val or val[:len(self)] == self) + + def __getattr__(self, val): + if not val or not val[0].isupper(): + return tuple.__getattribute__(self, val) + new = _TokenType(self + (val,)) + setattr(self, val, new) + new.parent = self + return new + + def __hash__(self): + return hash(tuple(self)) + + def __repr__(self): + return 'Token' + (self and '.' or '') + '.'.join(self) + + +Token = _TokenType() + +# Special token types +Text = Token.Text +Whitespace = Text.Whitespace +Newline = Whitespace.Newline +Error = Token.Error +# Text that doesn't belong to this lexer (e.g. HTML in PHP) +Other = Token.Other + +# Common token types for source code +Keyword = Token.Keyword +Name = Token.Name +Literal = Token.Literal +String = Literal.String +Number = Literal.Number +Punctuation = Token.Punctuation +Operator = Token.Operator +Comparsion = Operator.Comparsion +Wildcard = Token.Wildcard +Comment = Token.Comment +Assignment = Token.Assignement + +# Generic types for non-source code +Generic = Token.Generic + +# String and some others are not direct childs of Token. +# alias them: +Token.Token = Token +Token.String = String +Token.Number = Number + +# SQL specific tokens +DML = Keyword.DML +DDL = Keyword.DDL +Command = Keyword.Command + +Group = Token.Group +Group.Parenthesis = Token.Group.Parenthesis +Group.Comment = Token.Group.Comment +Group.Where = Token.Group.Where + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/stopwordlist.py b/interactive-mining-3rdparty-madis/madis/src/lib/stopwordlist.py new file mode 100644 index 0000000..d919296 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/stopwordlist.py @@ -0,0 +1,283 @@ +# coding: utf-8 + + +stopwords=set([ur".", ur"_", ur"stessi", ur"można", ur"einseitiger", ur"wären", ur"fÛr", ur"olette", ur"würde", ur"andre", ur"για", ur"ebben", ur"negl", ur"steigen", ur"einseitigen", +ur"dere", ur"niissä", ur"ergänzen", ur"otro", ur"noista", ur"dazu", ur"πεÏί", ur"tobie", ur"erst", ur"mußt", ur"szinte", ur"otra", ur"drauf", ur"gänzlich", ur"aus", +ur"under", ur"aux", ur"gesehen", ur"shouldn't", ur"dela", ur"neun", ur"dele", ur"berichteten", ur"neue", ur"voie", ur"ayantes", ur"letztes", ur"vase", ur"staremo", +ur"algunos", ur"letzten", ur"tandis", ur"tinham", ur"senin", ur"olisimme", ur"we'll", ur"ÔÃÇÃ", ur"mog±", ur"haben", ur"zde", ur"geworden", ur"zda", ur"upp", +ur"teníais", ur"fuera", ur"esos", ur"zuletzt", ur"abbiate", ur"zonder", ur"hors", ur"fece", ur"angefangen", ur"varit", ur"ezt", ur"verrate", ur"n", +ur"ellas", ur"alt", ur"avrebbero", ur"nel", ur"nem", ur"ÃÃÖÎÃ", ur"tipo", ur"nei", ur"emilyen", ur"ned", ur"klaren", ur"while", ur"ebbe", ur"tipy", ur"kun", +ur"estuvo", ur"nez", ur"sobre", ur"farebbero", ur"estuve", ur"ekkor", ur"fall", ur"neu", ur"nes", ur"dahi", ur"med", ur"meg", ur"powinni", ur"powinno", ur"daha", +ur"derjenige", ur"wezen", ur"men", ur"flere", ur"here", ur"meu", ur"met", ur"nicht", ur"avere", ur"mes", ur"mer", ur"hers", ur"ungefähr", ur"amolyan", ur"schätzt", +ur"sidan", ur"même", ur"gli", ur"auf", ur"ÓÅÊÞÃÓ", ur"anstatt", ur"näiksi", ur"aki", ur"i'd", ur"ueber", ur"där", ur"i'm", ur"aurai", ur"kýrk", ur"müssten", ur"esteve", +ur"arról", ur"desselben", ur"także", ur"magst", ur"कोई", ur"outro", ur"जो", ur"bra", ur"sarai", ur"tels", ur"estive", ur"would", ur"heille", ur"einiger", +ur"einiges", ur"fussions", ur"loro", ur"seraient", ur"vermögen", ur"cali", ur"niiden", ur"einigem", ur"ellos", ur"उसके", ur"sembra", ur"wÅ‚aÅ›nie", ur"által", ur"willst", +ur"Ã", ur"sabeu", ur"musi", ur"wenig", ur"saber", ur"sabes", ur"किया", ur"tendrías", ur"herein", ur"wohingegen", ur"facemmo", ur"nigdy", ur"ÔÃÖÅ", ur"ια", ur"sabem", +ur"saben", ur"quale", ur"me", ur"×ÅÄØ", ur"olet", ur"solament", ur"ma", ur"जा", ur"weiteres", ur"weiterer", ur"mi", ur"maiorias", ur"ने", ur"mu", ur"ÃÃÊ", ur"weiterem", +ur"era", ur"ÂÙÌÃ", ur"weiteren", ur"olen", ur"której", ur"जब", ur"ero", ur"my", ur"avaient", ur"wieviel", ur"czy", ur"étiez", ur"jest", ur"tuvieses", ur"czemu", +ur"consigue", ur"who's", ur"gegen", ur"wann", ur"tuoksi", ur"tuvierais", ur"auraient", ur"geben", ur"ambos", ur"wirklich", ur"want", ur"ना", ur"muesste", ur"hundert", +ur"újra", ur"buna", ur"anderes", ur"hoe", ur"end", ur"ene", ur"weiterhin", ur"czyli", ur"przy", ur"woraufhin", ur"off", ur"enn", ur"algmas", ur"startete", ur"how", +ur"ens", ur"bunu", ur"hos", ur"wenige", ur"stille", ur"anderen", ur"doesn't", ur"jsme", ur"mÃ…", ur"facesti", ur"vocês", ur"ÈÃÃ’ÃÛÃ", ur"sanki", ur"lag", ur"hubierais", +ur"mest", ur"वरà¥à¤—", ur"kimÅ›", ur"Ö", ur"lat", ur"sería", ur"lav", ur"mogÄ…", ur"las", ur"senkte", ur"gdyż", ur"je¶li", ur"mí", ur"estem", ur"cinque", ur"hasta", +ur"getragen", ur"letztlich", ur"reagiere", ur"mý", ur"sont", ur"stettero", ur"vart", ur"बहà¥à¤¤", ur"josta", ur"vars", ur"aient", ur"over", ur"zei", ur"teniu", ur"peut", +ur"hubiese", ur"nostra", ur"vara", ur"nostre", ur"ezzel", ur"nostri", ur"वे", ur"avevo", ur"vite", ur"nostro", ur"úgy", ur"begge", ur"gente", ur"bisher", ur"bundan", +ur"übel", ur"hon", ur"vilken", ur"rá", ur"valor", ur"teilen", ur"minden", ur"fin", ur"dorthin", ur"fim", ur"then", ur"them", ur"sinulta", ur"keissä", ur"deinem", +ur"deinen", ur"plötzlich", ur"deines", ur"deiner", ur"bana", ur"they", ur"mucho", ur"pelas", ur"wenn", ur"mindestens", ur"ausser", ur"nawet", ur"hubieran", ur"worden", +ur"dinge", ur"l", ur"estaréis", ur"até", ur"Õ", ur"ÌÕÞÛÅ", ur"each", ur"ενός", ur"ihn", ur"akkor", ur"verriet", ur"kterou", ur"diye", ur"darüberhinaus", ur"majÄ…", +ur"बाद", ur"estivermos", ur"nokon", ur"navn", ur"autre", ur"mikor", ur"zahlreich", ur"deira", ur"findest", ur"nötigenfalls", ur"aurais", ur"aurait", ur"deverá", +ur"behielt", ur"begann", ur"hätte", ur"sang", ur"god", ur"diesem", ur"diesen", ur"slutt", ur"re", ur"dieser", ur"dieses", ur"suyas", ur"werde", ur"avoir", +ur"geteilt", ur"frei", ur"nirgends", ur"verdadero", ur"icke", ur"verdadera", ur"consegueixo", ur"ÚÃ", ur"wiÄ™c", ur"doppelt", ur"elle", ur"brauchen", ur"weniger", +ur"inom", ur"hennar", ur"ÓËÃÚÃÔØ", ur"einführte", ur"legen", ur"intentan", ur"bár", ur"çünkü", ur"versorgten", ur"birkaç", ur"estas", ur"dahin", ur"ist", ur"att", +ur"eramos", ur"bräuchte", ur"solch", ur"gehabt", ur"podemos", ur"staranno", ur"intentas", ur"intentar", ur"einer", ur"eines", ur"serei", ur"avrebbe", ur"näitä", +ur"minä", ur"esté", ur"ÂÅÚ", ur"näissä", ur"tuon", ur"einen", ur"für", ur"hogyan", ur"ÔÃÇÄÃ", ur"unmöglicher", ur"drunter", ur"peggio", ur"τον", ur"är", +ur"perquè", ur"ingen", ur"tot", ur"estuvieseis", ur"brachten", ur"quinto", ur"toi", ur"ton", ur"solamente", ur"tom", ur"tuossa", ur"doppio", ur"ganze", +ur"beitrugen", ur"seré", ur"llarg", ur"beides", ur"poderá", ur"estavam", ur"nahm", ur"beiden", ur"του", ur"ależ", ur"verte", ur"bÃ¥de", ur"vielen", ur"sille", +ur"teiltä", ur"dürfen", ur"minua", ur"houve", ur"verraten", ur"kto", ur"hemos", ur"ancora", ur"sta", ur"vieles", ur"vieler", ur"sekä", ur"sposób", ur"yirmi", +ur"este", ur"esta", ur"jederlei", ur"nehmen", ur"durchaus", ur"esto", ur"mine", ur"vagyok", ur"korso", ur"jeres", ur"már", ur"further", ur"eröffnetes", ur"vorüber", +ur"häneltä", ur"habrás", ur"mint", ur"künftig", ur"niçin", ur"birþey", ur"fosti", ur"degl", ur"foste", ur"alors", ur"altri", ur"deres", ur"derer", ur"ÌÉ", ur"deren", +ur"derem", ur"feci", ur"tym", ur"eût", ur"oltre", ur"inzwischen", ur"dafür", ur"tylko", ur"ohne", ur"erano", ur"meidät", ur"doit", ur"ÂÙÌ", ur"état", ur"meidän", +ur"dois", ur"ihres", ur"sarò", ur"nämlich", ur"γι", ur"fusse", ur"avranno", ur"ahhoz", ur"hanno", ur"seks", ur"caÅ‚a", ur"m", ur"dog", ur"noihin", ur"caÅ‚y", ur"mithin", +ur"dos", ur"dov", ur"yani", ur"singen", ur"tuolta", ur"tatsächlich", ur"hur", ur"muß", ur"estais", ur"sage", ur"liest", ur"ebbi", ur"én", ur"nélkül", ur"sagt", +ur"somt", ur"och", ur"wirst", ur"egyetlen", ur"dessen", ur"henne", ur"höchstens", ur"danach", ur"sarebbero", ur"sto", ur"किसी", ur"daher", ur"estadas", ur"sien", +ur"sehen", ur"irá", ur"avrete", ur"nebenan", ur"do", ur"meget", ur"gdzieÅ›", ur"above", ur"klein", ur"di", ur"de", ur"stor", ur"da", ur"geen", ur"vsak", ur"du", +ur"einmal", ur"rispetto", ur"ikkje", ur"furent", ur"außerhalb", ur"stiamo", ur"anfangen", ur"των", ur"nämä", ur"rund", ur"nichts", ur"tenías", ur"estados", ur"iets", +ur"gjÛre", ur"starei", ur"blev", ur"iż", ur"dort", ur"ÚÄÅÓØ", ur"skulle", ur"tenham", ur"nur", ur"inny", ur"nun", ur"gefällt", ur"inne", ur"faig", +ur"machst", ur"inna", ur"schreiben", ur"iemand", ur"amikor", ur"blei", ur"inni", ur"eres", ur"staremmo", ur"houvéssemos", ur"weiter", ur"bekannt", ur"wogegen", +ur"bien", ur"estiveram", ur"ÔÅÃÅÒØ", ur"erhalten", ur"आप", ur"eren", ur"którego", ur"erem", ur"habrían", ur"we", ur"powinna", ur"welche", ur"legyen", ur"diese", +ur"wo", ur"soyons", ur"were", ur"anche", ur"sagten", ur"legten", ur"hätt", ur"stiegen", ur"niż", ur"möglicherweise", ur"ezen", ur"direkter", ur"ÖÉÚÎØ", ur"drei", +ur"ile", ur"questa", ur"clanku", ur"mancherorts", ur"ËÃË", ur"estuviera", ur"clanky", ur"coz", ur"questi", ur"against", ur"genug", ur"una", ur"kommer", ur"und", +ur"ils", ur"dÃ¥", ur"coi", ur"vorher", ur"com", ur"col", ur"con", ur"habían", ur"foram", ur"vaig", ur"tovább", ur"elf", ur"jakaÅ›", ur"durante", ur"niye", +ur"befragen", ur"ni¿", ur"vais", ur"ÜÔÉ", ur"ele", ur"habías", ur"podria", ur"fra", ur"aren't", ur"हैं", ur"tendrás", ur"tuolla", ur"been", ur"estaban", ur"estabas", +ur"tinc", ur"toen", ur"tenemos", ur"joiden", ur"jolta", ur"amelyekben", ur"jossa", ur"nagyon", ur"tendré", ur"i¿", ur"बनी", ur"pueden", ur"zich", ur"मे", ur"olisit", +ur"hvilken", ur"stavano", ur"suas", ur"mivel", ur"könnt", ur"letztendlich", ur"avessimo", ur"keistä", ur"aqueles", ur"auras", ur"þey", ur"ait", ur"avrei", ur"ayants", +ur"podriais", ur"egyik", ur"dello", ur"miltä", ur"serai", ur"ÎÉÂÕÄØ", ur"vagy", ur"aie", ur"delle", ur"della", ur"faremmo", ur"unos", ur"pokud", ur"unwichtig", +ur"indietro", ur"tässä", ur"is", ur"ir", ur"it", ur"desto", ur"estos", ur"ik", ur"im", ur"il", ur"io", ur"in", ur"dedans", ur"if", ur"quand", ur"meitä", ur"manchem", +ur"manchen", ur"manches", ur"mancher", ur"quant", ur"nokor", ur"tätä", ur"makt", ur"än", ur"angesetze", ur"elli", ur"keressünk", ur"manche", ur"gekonnt", ur"nim", +ur"nic", ur"coÅ›", ur"jetzt", ur"nie", ur"angesetzt", ur"elõtt", ur"sollt", ur"hayan", ur"kim", ur"ells", ur"kvarhelst", ur"ÃÃŽÃÇÃ", ur"depois", ur"he'll", ur"hacer", +ur"haces", ur"ihrem", ur"singt", ur"ihren", ur"tienes", ur"algun", ur"ÔÅÂÑ", ur"gekommen", ur"suyo", ur"drin", ur"enhver", ur"thi", ur"twój", ur"folgendes", ur"the", +ur"ihrer", ur"hacen", ur"yours", ur"jeszcze", ur"andere", ur"she'll", ur"denen", ur"anderm", ur"andern", ur"करने", ur"mientras", ur"था", ur"fueseis", ur"anderr", +ur"anders", ur"veja", ur"eus", ur"farei", ur"hai", ur"antes", ur"ausdrückt", ur"ham", ur"han", ur"kell", ur"vollständig", ur"hab", ur"ela", ur"had", ur"estuvieron", +ur"conseguimos", ur"hay", ur"niemals", ur"ÜÔÃÇÃ", ur"els", ur"har", ur"has", ur"hat", ur"zou", ur"opp", ur"trägt", ur"उनकी", ur"unter", ur"gewollt", ur"dessa", +ur"zurück", ur"unten", ur"ένα", ur"mille", ur"étantes", ur"között", ur"stavate", ur"również", ur"gemocht", ur"थे", ur"mykje", ur"थी", ur"näiden", +ur"की", ur"वाले", ur"करना", ur"ËÃÖÅÔÓÑ", ur"szemben", ur"ole", ur"kunne", ur"oli", ur"bort", ur"teria", ur"meer", ur"facendo", ur"habéis", ur"tendríamos", +ur"miêdzy", ur"seja", ur"vÃ¥rt", ur"ici", ur"ich", ur"consiguen", ur"for", ur"sota", ur"bizi", ur"ÂÕÄÅÔ", ur"valaki", ur"może", ur"reagieren", ur"muito", ur"olisin", +ur"uma", ur"seríamos", ur"tuviese", ur"consigues", ur"müßt", ur"ÜÔÃÊ", ur"foi", ur"elõ", ur"annak", ur"unse", ur"who", ur"इसी", ur"encima", ur"tutto", ur"arbeiten", +ur"machte", ur"conhecido", ur"eivät", ur"azután", ur"tentaram", ur"tomto", ur"ÎÅÇÃ", ur"houvera", ur"innych", ur"detta", ur"tenidas", ur"τις", ur"regelmäßig", +ur"zur", ur"darunter", ur"morgige", ur"theirs", ur"ÃÅÒÅÄ", ur"o", ur"serás", ur"serán", ur"algo", ur"kellett", ur"ÂÙÌÉ", ur"niin", ur"zum", ur"soc", ur"aber", +ur"sog", ur"fuisteis", ur"drüber", ur"som", ur"nÃ…", ur"erre", ur"son", ur"üç", ur"sou", ur"podle", ur"stavamo", ur"soy", ur"varte", ur"jene", ur"dürfte", +ur"novo", ur"hallo", ur"giu", ur"fûmes", ur"तो", ur"avait", ur"habríais", ur"nove", ur"keille", ur"uw", ur"avais", ur"forsÛke", ur"újabb", ur"minusta", ur"tilbake", +ur"éssent", ur"gib", ur"novy", ur"lage", ur"jeÅ›li", ur"wat", ur"was", ur"altijd", ur"podrias", ur"Ã…", ur"einigen", ur"uten", ur"some", ur"fora", ur"avions", +ur"très", ur"leider", ur"felé", ur"dieselbe", ur"alguno", ur"när", ur"podrian", ur"trug", ur"verdi", ur"hjÃ¥", ur"woher", ur"tengan", ur"estiverem", ur"nerde", ur"×ÓÀ", +ur"until", ur"gemacht", ur"sondern", ur"तक", ur"azt", ur"tengas", ur"tenía", ur"zeitweise", ur"facevano", ur"niinä", ur"ça", ur"zudem", ur"cokolwiek", ur"ÃÅÖÄÕ", +ur"gängig", ur"molt", ur"efter", ur"abbiano", ur"habíamos", ur"door", ur"bedarf", ur"ni", ur"allzu", ur"równie¿", ur"no", ur"wollten", ur"na", ur"tivemos", ur"fusses", +ur"when", ur"ne", ur"einstmals", ur"til", ur"ny", ur"wolltet", ur"zelf", ur"tid", ur"zuviel", ur"hát", ur"nu", ur"denn", ur"×ÃÃ", ur"tuyas", ur"ÖÅ", ur"kva", +ur"besteht", ur"dies", ur"lenni", ur"żadnych", ur"havemos", ur"kvi", ur"let's", ur"vÃ¥r", ur"×ÃÓ", ur"tendremos", ur"quindi", ur"apontar", ur"joita", ur"wiÄ™cej", +ur"wolltest", ur"bazý", ur"którzy", ur"gängiges", ur"ondan", ur"inkje", ur"sujet", ur"rief", ur"ÂÃÌÅÅ", ur"sicher", ur"oss", ur"weshalb", ur"muss", ur"aurions", +ur"sieht", ur"selbst", ur"sejam", ur"¿e", ur"primer", ur"lungo", ur"macht", ur"by³o", ur"ver", ur"ÞÔÃ", ur"habidas", ur"tust", ur"seither", ur"þuna", ur"quienes", +ur"deswegen", ur"by³a", ur"mache", ur"quasi", ur"by³y", ur"þunu", ur"व", ur"vem", ur"frÃ¥n", ur"fuiste", ur"befragten", ur"ÔÃÔ", ur"éramos", ur"hattet", ur"than", +ur"ihnen", ur"houveria", ur"anfing", ur"hatten", ur"koennen", ur"li", ur"befragter", ur"trabajais", ur"belki", ur"din", ur"estéis", ur"selber", ur"did", ur"die", +ur"warst", ur"dig", ur"ÃÅÎÑ", ur"meille", ur"mehrere", ur"somos", ur"avremo", ur"altý", ur"suoi", ur"prvni", ur"dit", ur"sogar", ur"dir", ur"jedenfalls", +ur"ville", ur"serons", ur"hvem", ur"cosa", ur"ciertas", ur"इसे", ur"einführen", ur"estuvieran", ur"anerkannter", ur"hver", ur"sÄ…", ur"versorgen", ur"दिया", ur"trop", +ur"facessi", ur"ÃÒÉ", ur"estou", ur"ausserdem", ur"szerint", ur"sagte", ur"joilla", ur"joille", ur"dem", ur"schätzte", ur"sareste", ur"jährige", ur"pouze", ur"saresti", +ur"serait", ur"ÂÙÌÃ", ur"nimmt", ur"infolge", ur"hadn't", ur"negli", ur"semmi", ur"É", ur"उस", ur"jednak", ur"fuer", ur"tuviéramos", ur"koennt", ur"niistä", ur"akik", +ur"magát", ur"legalább", ur"molts", ur"meillä", ur"molto", ur"molti", ur"bom", ur"bon", ur"wszystkich", ur"deg", ur"molta", ur"keineswegs", ur"keresztül", ur"amely", +ur"bevor", ur"nejsou", ur"hade", ur"hänellä", ur"prawie", ur"Ã…ÃÕ", ur"till", ur"że", ur"lesen", ur"estuvieras", ur"Ã¥t", ur"melyek", ur"pièce", ur"sÃ¥dana", ur"tages", +ur"ÃŽÃÄ", ur"ÓÃ×ÓÅÃ", ur"pred", ur"s±", ur"pero", ur"abban", ur"daneben", ur"ये", ur"sofern", ur"konnte", ur"ayante", ur"ÃÃÄ", ur"steige", ur"pres", ur"vous", +ur"eussent", ur"auront", ur"aurons", ur"ook", ur"unsere", ur"siate", ur"à¤à¤¸", ur"unserm", ur"sÃ…", ur"ambdós", ur"você", ur"abgerufen", ur"gestern", ur"seremos", +ur"só", ur"muitos", ur"sous", ur"dykk", ur"clanek", ur"schließlich", ur"à¤à¤•", ur"olimme", ur"sÃ¥", ur"ihre", ur"fossem", ur"ÞÅÇÃ", ur"tengamos", ur"noch", ur"सभी", +ur"nommés", ur"hayamos", ur"ÃÃÑ", ur"onlarýn", ur"bastante", ur"parce", ur"tuviesen", ur"होने", ur"aquel", ur"nyt", ur"però", ur"korleis", ur"machten", ur"पे", +ur"allerdings", ur"anderer", ur"mas", ur"habremos", ur"erhält", ur"पर", ur"anerkannte", ur"trilyon", ur"tuyos", ur"niemand", ur"aos", ur"bislang", ur"mag", +ur"lidt", ur"lhes", ur"dove", ur"mal", ur"man", ur"sofort", ur"häneen", ur"poikki", ur"deve", ur"geb", ur"devo", ur"avant", ur"su", ur"saranno", ur"το", ur"si", +ur"so", ur"vaya", ur"mange", ur"sa", ur"bardziej", ur"se", ur"τα", ur"contro", ur"täksi", ur"sejamos", ur"eravate", ur"×Ã", ur"hende", ur"immer", ur"facesse", +ur"okoÅ‚o", ur"obgleich", ur"stia", ur"×Ù", ur"þeyden", ur"आदि", ur"ved", ur"nimm", ur"mais", ur"he's", ur"habréis", ur"meiste", ur"estarías", ur"अपना", ur"gebracht", +ur"facciate", ur"estuviese", ur"estarían", ur"dieselben", ur"einerseits", ur"jiz", ur"into", ur"nirgendwo", ur"twoje", ur"non", ur"twoja", ur"noi", ur"beim", ur"nog", +ur"aquilo", ur"keitä", ur"अपनी", ur"halb", ur"अपने", ur"hiesige", ur"not", ur"qu", ur"ktoÅ›", ur"trabajamos", ur"nor", ur"nos", ur"ÓÅÂÅ", ur"bearbeitete", ur"avons", +ur"olit", ur"ketä", ur"इसमें", ur"desde", ur"ÓÅÂÑ", ur"anderem", ur"sabeis", ur"kann", ur"el", ur"en", ur"versorgt", ur"reeds", ur"ej", ur"ennek", ur"siihen", ur"eg", +ur"ÓÅÇÃÄÎÑ", ur"ÉÌÉ", ur"había", ur"versorge", ur"houverão", ur"et", ur"wegen", ur"es", ur"er", ur"außer", ur"fôramos", ur"stiano", ur"tuvieseis", ur"meistä", +ur"ponad", ur"ÅÊ", ur"hajam", ur"poco", ur"fazer", ur"bli", ur"valeur", ur"obwohl", ur"ble", ur"voltunk", ur"außen", ur"denselben", ur"geteilte", ur"tienen", ur"punkt", +ur"tuviera", ur"auch", ur"às", ur"terão", ur"czasem", ur"klares", ur"vier", ur"mimo", ur"ora", ur"starebbe", ur"takze", ur"terá", ur"eûmes", ur"×ÄÒÕÇ", +ur"horas", ur"siebte", ur"wichtig", ur"zal", ur"tenir", ur"noget", ur"à¤à¤µà¤‚", ur"ona", ur"teríamos", ur"yourself", ur"belül", ur"sizi", ur"ÇÄÅ", ur"völlig", +ur"behalten", ur"ons", ur"tenim", ur"ένας", ur"nogen", ur"ont", ur"onu", ur"jenem", ur"droite", ur"jenen", ur"anerkannt", ur"ÞÅÒÅÚ", ur"están", ur"ikke", ur"estás", +ur"setzen", ur"nutzen", ur"skal", ur"ähnlich", ur"jenes", ur"jener", ur"vilka", ur"altro", ur"más", ur"sodaß", ur"vort", ur"that", ur"fordert", ur"hun", ur"altre", +ur"laut", ur"padding", ur"qual", ur"quan", ur"bajo", ur"kvifor", ur"jährig", ur"नहीं", ur"podeu", ur"here's", ur"abbiamo", ur"konkrete", ur"έναν", ur"vostre", +ur"birkez", ur"reagiert", ur"pegar", ur"över", ur"houverá", ur"sechs", ur"koennten", ur"suyos", ur"gdzie", ur"avevano", ur"geht", ur"bestehen", ur"stessero", +ur"and", ur"alles", ur"aller", ur"pro", ur"dass", ur"pri", ur"ani", ur"tendrían", ur"sull", ur"azok", ur"ÃÃÔÃÃ", ur"hubiéramos", ur"ans", ur"allen", ur"allem", +ur"sap", ur"miksi", ur"their", ur"dorther", ur"étions", ur"bruke", ur"facessimo", ur"azon", ur"nebo", ur"zog", ur"taka", ur"take", ur"deux", ur"taki", +ur"benim", ur"sect", ur"meglio", ur"soweit", ur"têm", ur"dla", ur"falls", ur"vÃ¥ra", ur"mü", ur"dykkar", ur"ahogy", ur"joksi", ur"einseitige", ur"medan", ur"otuz", +ur"alguna", ur"derjenigen", ur"saremo", ur"heistä", ur"será", ur"alguns", ur"solche", ur"lenne", ur"corrente", ur"seria", ur"estejam", ur"eneste", ur"lassen", +ur"teilte", ur"tínhamos", ur"veröffentlicher", ur"tém", ur"elas", ur"veröffentlichen", ur"estoy", ur"qualquer", ur"bereits", ur"takie", ur"hace", ur"überdies", +ur"sobie", ur"weitere", ur"diz", ur"setzt", ur"siltä", ur"bringen", ur"daar", ur"serais", ur"dich", ur"éppen", ur"jakkolwiek", ur"तरह", ur"only", ur"ε", ur"olisi", +ur"tuviste", ur"hão", ur"aufhören", ur"info", ur"toch", ur"gemäss", ur"ehhez", ur"ÃÃÞÔÉ", ur"nell", ur"wiêc", ur"jó", ur"bylo", ur"keneltä", ur"cannot", ur"fragte", +ur"dasselbe", ur"já", ur"ergänze", ur"primo", ur"sollten", ur"abans", ur"för", ur"leur", ur"byli", ur"amíg", ur"wiewohl", ur"through", ur"where", ur"onlar", +ur"nouveaux", ur"fueran", ur"seas", ur"volna", ur"up", ur"freies", ur"freier", ur"jos", ur"ausgenommen", ur"sean", ur"estamos", ur"vermag", ur"hvorfor", ur"estad", +ur"einst", ur"haja", ur"καθ", ur"και", ur"estan", ur"estat", ur"chaque", ur"estar", ur"svym", ur"utolsó", ur"between", ur"दो", ur"tiverem", ur"podczas", ur"ÉÚ", +ur"ju", ur"tuolle", ur"tut", ur"mellan", ur"tästä", ur"tego", ur"ÉÈ", ur"jo", ur"ÉÃ", ur"ji", ur"como", ur"fez", ur"tuve", ur"je", ur"κατ", ur"come", ur"ja", +ur"koska", ur"ciertos", ur"eröffnen", ur"darin", ur"entweder", ur"avuti", ur"tämä", ur"allo", ur"eröffnet", ur"tous", ur"mand", ur"aura", ur"schnell", ur"quien", +ur"avuto", ur"gjorde", ur"somit", ur"mann", ur"comprido", ur"vuestro", ur"tun", ur"damals", ur"été", ur"hva", ur"devrait", ur"tuo", ur"por", ur"haceis", ur"teillä", +ur"tua", ur"ante", ur"pod", ur"seulement", ur"siete", ur"veröffentlicht", ur"oder", ur"tue", ur"ιαν", ur"aufgrund", ur"kdyz", ur"hepsi", ur"viele", +ur"aquellos", ur"tenían", ur"noen", ur"zpravy", ur"minuun", ur"ceux", ur"hoch", ur"ÃÄÉÎ", ur"those", ur"houverei", ur"myself", ur"κατά", ur"eit", ur"einzig", +ur"minulle", ur"minulla", ur"ergänzte", ur"εις", ur"vaikka", ur"ein", ur"ÄÃ", ur"estávamos", ur"eran", ur"eram", ur"joka", ur"soit", ur"legte", +ur"eras", ur"dört", ur"geehrt", ur"eri", ur"miért", ur"par", ur"pas", ur"yo", ur"επι", ur"einseitig", ur"same", ur"hvilke", ur"jól", ur"otto", +ur"möglich", ur"tout", ur"pak", ur"otte", ur"todos", ur"nÃ¥gra", ur"teraz", ur"eitt", ur"zwanzig", ur"persone", ur"sotto", ur"kenenä", ur"algunes", ur"stareste", +ur"entonces", ur"tenha", ur"defa", ur"naszego", ur"hebben", ur"tenho", ur"perché", ur"estivessem", ur"berichtet", ur"noko", ur"tivessem", ur"veröffentlichten", +ur"ausdrückte", ur"veröffentlichtes", ur"machen", ur"can't", ur"noka", ur"então", ur"wessen", ur"siitä", ur"promesso", ur"berichten", ur"konkreter", ur"konkretes", +ur"deze", ur"senken", ur"×", ur"nachdem", ur"being", ur"gdy", ur"keillä", ur"bietet", ur"verdad", ur"át", ur"tuviésemos", ur"þundan", ur"konkreten", ur"quella", +ur"quelle", ur"tim", ur"we've", ur"quelli", ur"quello", ur"jona", ur"vergangene", ur"konnten", ur"abgerufenes", ur"hacemos", ur"którym", ur"onder", ur"avevamo", +ur"ami", ur"ditt", ur"ama", ur"jako", ur"amb", ur"neuen", ur"usamos", ur"mot", ur"neuer", ur"neues", ur"moi", ur"mon", ur"einbaün", ur"tanto", ur"sÃ¥dan", +ur"वह", ur"serez", ur"darf", ur"już", ur"mod", ur"aurez", ur"acute", ur"eussiez", ur"साथ", ur"ahol", ur"soient", ur"vergangenes", ur"t", ur"où", ur"stava", +ur"ËÃËÃÑ", ur"intet", ur"avrai", ur"debaixo", ur"são", ur"τη", ur"aufzusuchen", ur"nÃ¥", ur"bloß", ur"sollen", ur"össze", ur"houveríamos", ur"eddig", ur"geehrte", +ur"naar", ur"blive", ur"avevi", ur"sommes", ur"στις", ur"aż", ur"solltest", ur"besser", ur"meinen", ur"meinem", ur"meiner", ur"meines", ur"tänä", ur"igitt", +ur"heihin", ur"klare", ur"kenen", ur"sarebbe", ur"továbbá", ur"starai", ur"seine", ur"gestrige", ur"fuésemos", ur"secondo", ur"serão", ur"kenet", ur"habe", +ur"siehe", ur"on", ur"om", ur"här", ur"og", ur"of", ur"od", ur"ob", ur"erneut", ur"neden", ur"it's", ur"acz", ur"ou", ur"ÃÃÑÔØ", ur"os", ur"or", ur"op", +ur"seriez", ur"keinä", ur"trabajan", ur"irgendeine", ur"tallä", ur"esses", ur"estés", ur"απ", ur"még", ur"näihin", ur"tuvisteis", ur"darfst", +ur"trabajas", ur"trabajar", ur"het", ur"unas", ur"welches", ur"welcher", ur"hep", ur"how's", ur"her", ur"there", ur"gesagt", ur"tehát", ur"los", ur"több", +ur"ehe", ur"heb", ur"euer", ur"hem", ur"hen", ur"welchem", ur"hei", ur"σε", ur"welchen", ur"tendríais", ur"vÃ…r", ur"sabemos", ur"eröffne", ur"bunda", +ur"jednakże", ur"gibi", ur"geehrter", ur"gibt", ur"mich", ur"último", ur"with", ur"gängigen", ur"vere", ur"they're", ur"vuestras", ur"wasn't", ur"õ", +ur"agora", ur"saját", ur"sera", ur"voient", ur"we'd", ur"sve", ur"ad", ur"af", ur"ai", ur"hänessä", ur"aj", ur"am", ur"al", ur"ao", ur"an", ur"intenta", +ur"ÔÃ", ur"tengo", ur"saremmo", ur"pourquoi", ur"uit", ur"av", ur"az", ur"tenga", ur"δια", ur"intento", ur"ÄÒÕÇÃÊ", ur"again", ur"estão", ur"wurde", ur"pfui", +ur"missä", ur"pedig", ur"bearbeiteten", ur"gleichwohl", ur"jsem", ur"jses", ur"personnes", ur"starò", ur"eigentlich", ur"woraus", ur"avessero", ur"यदि", +ur"στους", ur"fazia", ur"hubiste", ur"etwas", ur"möglichen", ur"wohlweislich", ur"important", ur"sullo", ur"gängiger", ur"sulla", ur"nutzung", ur"genommen", +ur"ιας", ur"sulle", ur"tenida", ur"ella", ur"tendréis", ur"derzeit", ur"unsen", ur"mellett", ur"unsem", ur"ÃÙ", ur"oraz", ur"eusse", ur"sokat", ur"u", +ur"unser", ur"unses", ur"mías", ur"all", ur"ali", ur"z.B.", ur"ampleamos", ur"ale", ur"noilta", ur"pta", ur"andererseits", ur"ÃŽÃËÃÎÅÃ", ur"näiltä", +ur"siinä", ur"noissa", ur"ÃŽÃ", ur"fortsetzt", ur"als", ur"bearbeiten", ur"ÎÉ", ur"müsste", ur"êtes", ur"ty", ur"ÃŽÃ", ur"tu", ur"gegeben", ur"ÃŽÃ…", ur"to", +ur"niiltä", ur"lavoro", ur"derselbe", ur"maioria", ur"ti", ur"umso", ur"kvar", ur"te", ur"dlatego", ur"Ã’ÃÚ×Å", ur"ta", ur"faz", ur"estando", ur"über", +ur"estaba", ur"very", ur"fas", ur"wohin", ur"sono", ur"verdadeiro", ur"fan", ur"hinein", ur"te¿", ur"való", ur"żadna", ur"tuvimos", ur"strana", ur"yetmiþ", +ur"żadne", ur"tät", ur"sant", ur"könnten", ur"anar", ur"sans", ur"sollte", ur"sinulla", ur"hendes", ur"joista", ur"sinulle", ur"teneis", ur"hattest", +ur"habré", ur"largo", ur"étés", ur"ecco", ur"habrá", ur"i'll", ur"twoim", ur"tej", ur"tem", ur"ten", ur"immerhin", ur"facevi", ur"faites", ur"kunnen", +ur"unmöglichen", ur"tes", ur"teu", ur"what", ur"sekiz", ur"tú", ur"hänestä", ur"sua", ur"mindig", ur"suo", ur"sul", ur"egyes", ur"sui", ur"letze", +ur"sus", ur"sur", ur"deles", ur"aby", ur"közül", ur"jede", ur"vamos", ur"stavi", ur"neni", ur"ÂÕÄÔÃ", ur"aquells", ur"habiendo", ur"einigermaßen", ur"seiten", +ur"quieto", ur"kimi", ur"ggf", ur"niiksi", ur"hast", ur"meisten", ur"guten", ur"hadde", ur"kime", ur"egész", ur"à", ur"avessi", ur"stavo", ur"meist", ur"avesse", +ur"when's", ur"unbedingt", ur"ÉÎÃÇÄÃ", ur"durch", ur"senden", ur"seréis", ur"hänelle", ur"zawsze", ur"joihin", ur"vid", ur"forderte", ur"vil", ur"την", +ur"habíais", ur"करते", ur"otros", ur"hogy", ur"nokre", ur"fueras", ur"hvordan", ur"minussa", ur"tutti", ur"etc", ur"wiele", ur"jejich", ur"trabaja", ur"houver", +ur"folgende", ur"seras", ur"darum", ur"रखें", ur"wielu", ur"trabajo", ur"more", ur"mellom", ur"þeyi", ur"milyon", ur"noina", ur"noille", ur"hubieras", ur"obok", +ur"kenestä", ur"schlechter", ur"potser", ur"fÃ¥", ur"ÄÃ", ur"wedÅ‚ug", ur"bizden", ur"unmögliche", ur"noilla", ur"tähän", ur"करता", ur"teistä", ur"muze", +ur"nerede", ur"stiate", ur"der", ur"des", ur"det", ur"minut", ur"ÜÔÃÔ", ur"της", ur"dei", ur"minhas", ur"fomos", ur"del", ur"fÃ…", ur"den", ur"tuas", ur"bunun", +ur"teille", ur"beitragen", ur"wieder", ur"sois", ur"erhielt", ur"iniciar", ur"lichten", ur"ÃŽÃÓ", ur"seríais", ur"też", ur"zumal", ur"sense", ur"mehr", ur"उनका", +ur"gratulierte", ur"avemmo", ur"sitt", ur"folgender", ur"étant", ur"können", ur"gewissermaßen", ur"voltak", ur"before", ur"vorbei", ur"nagyobb", ur"jährigen", +ur"twym", ur"másik", ur"fu", ur"gängige", ur"yedi", ur"Ã…Ã…", ur"notre", ur"vosaltres", ur"fa", ur"tuona", ur"numa", ur"não", ur"fi", ur"versorgtes", ur"teile", +ur"ËÃËÃÊ", ur"a", ur"egy", ur"estuviéramos", ur"kein", ur"उनके", ur"abgerufene", ur"proto", ur"unterhalb", ur"ÄÌÑ", ur"dentro", ur"या", ur"milyar", ur"ise", +ur"यह", ur"verrieten", ur"ferner", ur"mezi", ur"लिये", ur"that's", ur"don't", ur"sämtliche", ur"consigueix", ur"nÃ¥got", ur"zugleich", ur"hayáis", ur"pana", +ur"quelles", ur"bloss", ur"està", ur"pani", ur"its", ur"utána", ur"está", ur"allg", ur"alle", ur"alla", ur"sopra", ur"joissa", ur"sinusta", ur"teidän", +ur"hubiésemos", ur"voran", ur"allt", ur"teidät", ur"nimmer", ur"hvor", ur"nossos", ur"ÃÃÖÅÔ", ur"haven't", ur"musste", ur"müssen", ur"ya", ur"consigo", +ur"mitkä", ur"ces", ur"you've", ur"jÄ…", ur"tragen", ur"dnes", ur"abgerufener", ur"tausend", ur"mussten", ur"tuoi", ur"solange", ur"næsten", ur"ilyenkor", +ur"tuvieran", ur"fünf", ur"würden", ur"tra", ur"denne", ur"hvis", ur"denna", ur"inclòs", ur"vannak", ur"isn't", ur"nein", ur"staresti", ur"tuosta", +ur"stemmo", ur"hubieseis", ur"nossa", ur"möglicher", ur"teníamos", ur"ugyanis", ur"sagtest", ur"todo", ur"nosso", ur"somente", ur"einem", ur"houvemos", +ur"serions", ur"nuovo", ur"tenido", ur"nuovi", ur"ÎÕ", ur"buono", ur"ÔÃÃ", ur"jolle", ur"seáis", ur"they'll", ur"jolla", ur"estaremos", ur"lehet", ur"mukaan", +ur"dehors", ur"gefiel", ur"fecero", ur"puc", ur"verdade", ur"hiszen", ur"jakiż", ur"asi", ur"ÎÅÔ", ur"enquanto", ur"bekannter", ur"blieb", ur"jähriges", +ur"estada", ur"kon", ur"dabei", ur"voor", ur"हà¥à¤", ur"nosotros", ur"kimden", ur"हà¥à¤ˆ", ur"w", ur"estejamos", ur"tivesse", ur"हà¥à¤†", ur"jakiÅ›", ur"mindenki", +ur"hubiera", ur"dina", ur"onlari", ur"nach", ur"étants", ur"blitt", ur"tuvieras", ur"tedy", ur"cada", ur"donc", ur"dins", ur"étante", ur"jer", ur"tato", ur"kom", +ur"seksen", ur"teissä", ur"nome", ur"esas", ur"avec", ur"przez", ur"avez", ur"contra", ur"przed", ur"ÔÃÌØËÃ", ur"jeg", ur"jed", ur"jej", ur"jen", +ur"dlaczego", ur"wenigstens", ur"míos", ur"para", ur"jego", ur"teitä", ur"part", ur"darüber", ur"tive", ur"schon", ur"tak¿e", ur"ÃÃÓÌÅ", ur"musst", ur"aan", +ur"dans", ur"इस", ur"dann", ur"sillä", ur"dank", ur"seamos", ur"teve", ur"maga", ur"birþeyi", ur"überall", ur"teriam", ur"heiltä", ur"vielmals", ur"schreibens", +ur"ebenfalls", ur"aussi", ur"tiver", ur"svych", ur"benne", ur"oda", ur"elõször", ur"pomimo", ur"eingesetzt", ur"için", ur"anerkanntes", ur"sÃ¥nn", ur"adesso", +ur"invece", ur"sizden", ur"euch", ur"faccia", ur"später", ur"lik", ur"also", ur"zwölf", ur"näinä", ur"estuviesen", ur"quattro", ur"nuestras", ur"selv", ur"habrán", +ur"jakie", ur"such", ur"tentar", ur"ÅÓÌÉ", ur"dokuz", ur"any", ur"tuvo", ur"kan", ur"kam", ur"essa", ur"mely", ur"esse", ur"starteten", ur"tivera", +ur"bzw", ur"ke", ur"sehr", ur"minha", ur"meine", ur"ki", ur"varför", ur"hubieses", ur"swoje", ur"jeżeli", ur"ËÔÃ", ur"ansetzen", ur"stessimo", ur"wieso", ur"aztán", +ur"fosse", ur"haar", ur"sobÄ…", ur"unseres", ur"unserer", ur"tener", ur"új", ur"tinha", ur"fino", ur"font", ur"unseren", ur"fôssemos", ur"में", +ur"quem", ur"quel", ur"mina", ur"INSERmi", ur"irgend", ur"από", ur"στην", ur"fareste", ur"valami", ur"hatte", ur"svymi", ur"porque", ur"minun", ur"steste", +ur"गया", ur"algún", ur"esteja", ur"×ÃÔ", ur"vorgestern", ur"timto", ur"fûtes", ur"étée", ur"they'd", ur"mío", ur"bedurfte", ur"stando", ur"during", ur"hij", +ur"podeis", ur"him", ur"hin", ur"direkt", ur"ÃÃŽ", ur"fussent", ur"ÃÂ", ur"vilket", ur"schätzten", ur"etter", ur"vissza", ur"ÃÔ", ur"koennte", ur"seu", +ur"सकता", ur"ses", ur"ser", ur"होती", ur"forderten", ur"fuesen", ur"होते", ur"seg", ur"fueses", ur"vorne", ur"bare", ur"are", ur"sea", ur"sen", ur"llavors", +ur"tohle", ur"sei", ur"einführten", ur"fand", ur"varje", ur"ktery", ur"vont", ur"irgendwer", ur"ktera", ur"consecutivo", ur"estará", ur"consecutivi", ur"kteri", +ur"dein", ur"deim", ur"solo", ur"soll", ur"dalla", ur"jeden", ur"jedem", ur"dalle", ur"ebenso", ur"ncht", ur"solc", ur"ÔÒÉ", ur"ison", ur"estivemos", ur"trage", +ur"altmýþ", ur"hiç", ur"jedes", ur"jeder", ur"iki", ur"ligado", ur"sols", ur"both", ur"fortsetzen", ur"avesti", ur"wouldn't", ur"etliche", ur"yüz", +ur"angesetzter", ur"számára", ur"होता", ur"ÞÕÔØ", ur"सकते", ur"dadurch", ur"aveste", ur"cierto", ur"samma", ur"nter", ur"sonstwo", ur"était", ur"samme", +ur"olla", ur"pessoas", ur"इसका", ur"zpet", ur"cierta", ur"ÞÅÃ", ur"avrò", ur"estivesse", ur"auriez", ur"zusammen", ur"dizer", ur"moins", ur"arbeid", ur"fummo", +ur"estuvisteis", ur"न", ur"tälle", ur"weder", ur"due", ur"allmählich", ur"whom", ur"Ë", ur"forrige", ur"rett", ur"txt", ur"ollut", ur"dus", ur"po", ur"lett", +ur"ÃÃŽÃ…", ur"fire", ur"what's", ur"stattdessen", ur"amelyeket", ur"gar", ur"johon", ur"estuvierais", ur"heute", ur"gab", ur"सबसे", ur"fut", ur"अभी", ur"ez", +ur"×ÓÅ", ur"irgendwo", ur"sizin", ur"fossimo", ur"इसकी", ur"fue", ur"इसके", ur"möchten", ur"mögliche", ur"fui", ur"alatt", ur"ketkä", ur"vom", ur"von", +ur"étaient", ur"voi", ur"hänet", ur"itself", ur"vor", ur"pÃ…", ur"zieht", ur"nós", ur"triplo", ur"voy", ur"beiderlei", ur"steht", ur"pela", ur"acaba", +ur"direita", ur"fueron", ur"pÃ¥", ur"estes", ur"atrás", ur"utan", ur"esteu", ur"które", ur"ktere", ur"keiden", ur"warum", ur"która", ur"tellement", ur"zwar", +ur"geweest", ur"eues", ur"eure", ur"joilta", ur"neuem", ur"keine", ur"cikkeket", ur"który", ur"elsõ", ur"obschon", ur"entre", ur"hinterher", ur"noiksi", +ur"tengáis", ur"hago", ur"szét", ur"estuvieses", ur"eles", ur"senkten", ur"õk", ur"y", ur"ËÃÇÄÃ", ur"kívül", ur"konkret", ur"incluso", ur"eigenen", +ur"rechts", ur"tych", ur"fÛrst", ur"kenelle", ur"stesso", ur"mie", ur"freie", ur"nuestra", ur"mo¿na", ur"vielleicht", ur"amp", ur"eigenes", ur"mitä", +ur"ÓËÃÚÃÃŒ", ur"nuestro", ur"bliver", ur"finden", ur"mintha", ur"vagyis", ur"gueno", ur"kven", ur"danke", ur"arriba", ur"tus", ur"findet", ur"acerca", +ur"keihin", ur"durften", ur"cui", ur"bin", ur"emme", ur"wil", ur"bij", ur"lehetett", ur"womit", ur"folgenden", ur"aviez", ur"bé", ur"Ã", ur"habida", +ur"hayas", ur"biz", ur"żeby", ur"jste", ur"bir", ur"bis", ur"habido", ur"weiß", ur"facciamo", ur"d", ur"erste", ur"houveram", ur"jota", ur"valamint", +ur"een", ur"sokkal", ur"trabalho", ur"sehrwohl", ur"mycket", ur"folglich", ur"wir", ur"mögen", ur"sue", ur"estaríais", ur"kenellä", ur"hinten", ur"bowiem", +ur"hinter", ur"aquell", ur"allgemein", ur"bastant", ur"ilyen", ur"aquele", ur"nÃ…r", ur"ourselves", ur"aquela", ur"beträchtlich", ur"minulta", ur"terei", +ur"néhány", ur"peu", ur"depuis", ur"per", ur"poza", ur"estivera", ur"pelo", ur"bêdzie", ur"inicio", ur"czasami", ur"desligado", ur"proc", ur"ÔÃË", ur"be", +ur"nello", ur"acht", ur"nella", ur"siendo", ur"bo", ur"nelle", ur"avresti", ur"bu", ur"mutta", ur"weil", ur"bezüglich", ur"nosotras", ur"by", ur"υπό", +ur"être", ur"juste", ur"wenngleich", ur"bist", ur"darauf", ur"promeiro", ur"daraus", ur"ide", ur"benden", ur"yli", ur"inte", ur"allora", ur"ÃÃÔÃÃÕ", +ur"teniendo", ur"steigt", ur"bÄ™dÄ…", ur"diesseits", ur"gewesen", ur"kanssa", ur"vaan", ur"because", ur"fordern", ur"empleais", ur"przecież", ur"neki", +ur"poden", ur"podem", ur"degli", ur"fossero", ur"keneksi", ur"ezek", ur"avremmo", ur"fast", ur"häntä", ur"suis", ur"längstens", ur"liegt", ur"we're", +ur"aufgehört", ur"besonders", ur"fortsetzten", ur"atras", ur"poder", ur"ca.", ur"somme", ur"himself", ur"estabais", ur"derart", ur"collapsed", +ur"napiste", ur"voltam", ur"comprare", ur"ÞÔÃÂÙ", ur"habidos", ur"byÅ‚y", ur"sowohl", ur"Ã¥", ur"możliwe", ur"uz", ur"nasýl", ur"ut", ur"schwierig", +ur"bizim", ur"hasn't", ur"cikk", ur"leicht", ur"um", ur"majd", ur"un", ur"दà¥à¤µà¤¾à¤°à¤¾", ur"byÅ‚o", ur"doc", ur"byÅ‚a", ur"ud", ur"z", ur"nogle", ur"befragte", +ur"titel", ur"कà¥à¤²", ur"tiveram", ur"seront", ur"ÅÇÃ", ur"teilten", ur"as", ur"कà¥à¤›", ur"mochte", ur"nad", ur"fossi", ur"elles", ur"eller", ur"demnach", +ur"beide", ur"wollte", ur"nam", ur"nas", ur"nich", ur"hubiesen", ur"ellen", ur"hanem", ur"toho", ur"siden", ur"temos", ur"lediglich", ur"eurer", ur"eures", +ur"olleet", ur"consigueixen", ur"dall", ur"wohl", ur"aveva", ur"dalt", ur"derselben", ur"jakichÅ›", ur"egyéb", ur"euren", ur"consigueixes", ur"eurem", +ur"habrías", ur"langsam", ur"lang", ur"glücklicherweise", ur"agl", ur"e", ur"vice", ur"tämän", ur"muchos", ur"gehen", ur"she'd", ur"teto", ur"she's", +ur"tendría", ur"nasi", ur"having", ur"once", ur"benutzt", ur"noiden", ur"oberhalb", ur"dannen", ur"eûtes", ur"ganz", ur"sitta", ur"essas", ur"farò", +ur"heutige", ur"bÄ™dzie", ur"setzte", ur"essai", ur"ge", ur"unes", ur"go", ur"επ", ur"dagegen", ur"katrilyon", ur"zogen", ur"seni", ur"ÜÔÃÃ", ur"keneen", +ur"lille", ur"könnte", ur"entsprechend", ur"sarei", ur"sooft", ur"nuestros", ur"sieben", ur"tyto", ur"talán", ur"übrigens", ur"és", ur"wszystkim", +ur"tivermos", ur"tuto", ur"wszystkie", ur"maar", ur"eso", ur"naszych", ur"mustn't", ur"yourselves", ur"sinä", ur"möchtest", ur"εξ", ur"vos", ur"εκ", +ur"també", ur"onlardan", ur"tre", ur"they've", ur"ÃÃ", ur"roku", ur"általában", ur"bleiben", ur"niitä", ur"ÔÃËÃÊ", ur"él", ur"starebbero", +ur"nuo", ur"zo", ur"you'd", ur"fus", ur"gratulieren", ur"ze", ur"vele", ur"direkte", ur"za", ur"ÓËÃÚÃÃŒÃ", ur"gmbh", ur"στη", ur"στα", ur"nÃ¥gon", +ur"zu", ur"teljes", ur"στο", ur"übermorgen", ur"folk", ur"zapewne", ur"sinussa", ur"õket", ur"eurent", ur"unserem", ur"deras", ur"unmöglich", ur"biri", +ur"gÃ…", ur"einige", ur"indem", ur"wachen", ur"tivéramos", ur"tened", ur"ÎÉÞÅÇÃ", ur"cela", ur"έσα", ur"saps", ur"sí", ur"lei", ur"siÄ™", ur"quels", +ur"mikä", ur"kannst", ur"étais", ur"les", ur"tendrá", ur"cuando", ur"mnie", ur"gedurft", ur"sind", ur"sine", ur"bedürfen", ur"sina", ur"honom", +ur"avreste", ur"egyre", ur"olyan", ur"dell", ur"tegen", ur"gleichzeitig", ur"ersten", ur"erster", ur"nær", ur"रहे", ur"niets", ur"avendo", ur"ovat", +ur"mentre", ur"wie", ur"रहा", ur"hennes", ur"amelynek", ur"wij", ur"että", ur"volt", ur"veröffentlichte", ur"últim", ur"zijn", ur"mens", ur"meihin", +ur"viszont", ur"toteż", ur"dreißig", ur"from", ur"che", ur"usa", ur"uso", ur"chi", ur"fel", ur"fem", ur"gern", ur"usw", ur"few", ur"feu", ur"fer", +ur"kuin", ur"kunde", ur"fuese", ur"mindent", ur"siê", ur"themselves", ur"zij", ur"faresti", ur"fai", ur"fará", ur"farà", ur"wurden", ur"didn't", +ur"estarás", ur"azért", ur"Ñ", ur"unterbrach", ur"ette", ur"jeste", ur"olivat", ur"startet", ur"vuestra", ur"farebbe", ur"sembrava", ur"joiksi", +ur"this", ur"siksi", ur"nekem", ur"pour", ur"ÇÃ×ÃÒÉÌ", ur"jakoÅ›", ur"dritte", ur"sabe", ur"jeho", ur"votre", ur"faceste", ur"noita", ur"links", +ur"heidät", ur"caminho", ur"slik", ur"tüm", ur"beni", ur"heidän", ur"his", ur"zwischen", ur"tal", ur"tam", ur"seriam", ur"gefälligst", ur"tak", +ur"keinerlei", ur"usais", ur"sobald", ur"sit", ur"siz", ur"syv", ur"mein", ur"tai", ur"gratuliert", ur"sia", ur"diejenige", ur"sig", ur"fuéramos", +ur"sie", ur"cual", ur"delas", ur"itse", ur"sin", ur"einig", ur"fare", ur"hubisteis", ur"ËÃÎÅÞÎÃ", ur"klar", ur"facevate", ur"estivéssemos", +ur"amelyet", ur"ausdrücken", ur"frau", ur"stesti", ur"hän", ur"×ÃÃ’ÃÞÅÃ", ur"estivéramos", ur"hätten", ur"tenéis", ur"eher", ur"ÔÅÃ", ur"isso", +ur"ÔÙ", ur"worin", ur"कहा", ur"waere", ur"primero", ur"insofern", ur"subito", ur"olisitte", ur"sido", ur"eröffnete", ur"azonban", ur"comme", ur"own", +ur"won't", ur"ÓÃ", ur"da?", ur"míg", ur"znowu", ur"volte", ur"le", ur"la", ur"eue", ur"lo", ur"byt", ur"stanno", ur"før", ur"demselben", ur"aucuns", +ur"byl", ur"eux", ur"eut", ur"dess", ur"facevo", ur"lecz", ur"morgen", ur"erhielten", ur"waren", ur"tatsächlichen", ur"dal", ur"wäre", ur"dan", ur"danken", +ur"dai", ur"devem", ur"dat", ur"doch", ur"wolle", ur"das", ur"qué", ur"quê", ur"natomiast", ur"stette", ur"ÂÃÌØÛÅ", ur"komme", ur"stetti", ur"irgendwen", +ur"eben", ur"tras", ur"kommt", ur"modo", ur"solches", ur"riktig", ur"bearbeite", ur"houveriam", ur"ÎÅÊ", ur"habría", ur"doing", ur"mijn", ur"ÃŽÃ…Ã…", +ur"tente", ur"fortsetzte", ur"wszyscy", ur"our", ur"beginnen", ur"tento", ur"solchen", ur"solchem", ur"out", ur"böden", ur"tuya", ur"kiedy", ur"là", +ur"début", ur"tohoto", ur"sugl", ur"werdet", ur"tuyo", ur"ÃÃ’Ã", ur"your", ur"aquelles", ur"mate", ur"minkä", ur"omdat", ur"pan", ur"करें", ur"bekennen", +ur"fuerais", ur"faceva", ur"heillä", ur"eravamo", ur"meiltä", ur"versorgte", ur"näille", ur"tempo", ur"vergangen", ur"formos", ur"qua", ur"ill.", ur"τους", +ur"næste", ur"que", ur"kommen", ur"kaum", ur"qui", ur"fuimos", ur"hänen", ur"ÂÙ", ur"milyen", ur"tatsächliches", ur"tatsächlicher", ur"heraus", ur"eens", +ur"ono", ur"innen", ur"deshalb", ur"daß", ur"fait", ur"nachhinein", ur"tomuto", ur"ihr", ur"furono", ur"sjøl", ur"और", ur"powinien", +ur"suya", ur"damit", ur"vergangener", ur"illetve", ur"ihm", ur"byÅ‚", ur"you're", ur"ÃÎÉ", ur"haya", ur"ÚÃÞÅÃ", ur"ÃÃŽÃ", ur"estemos", ur"wodurch", +ur"starete", ur"mo¿e", ur"which", ur"abbia", ur"millä", ur"aufhörte", ur"plupart", ur"haver", ur"blivit", ur"fût", ur"bude", ur"ÞÅÌÃ×ÅË", ur"quando", ur"ebbero", +ur"jenseits", ur"too", ur"być", ur"brachte", ur"algunas", ur"herself", ur"sicherlich", ur"sinuun", ur"bei", ur"ben", ur"weren't", ur"bem", ur"quanti", ur"sok", +ur"bez", ur"num", ur"których", ur"azzal", ur"encore", ur"seinem", ur"seinen", ur"elég", ur"ÎÉËÃÇÄÃ", ur"ÔÕÔ", ur"heitä", ur"eusses", ur"blir", ur"have", +ur"manchmal", ur"bÃ¥e", ur"sem", ur"seiner", ur"seines", ur"ista", ur"itt", ur"mij", ur"iste", ur"mio", ur"min", ur"mia", ur"ÂÙÔØ", ur"fussiez", +ur"während", ur"mig", ur"isto", ur"veel", ur"को", ur"übrig", ur"beinahe", ur"के", ur"mir", ur"mit", ur"intentais", ur"कि", ur"का", ur"empleo", ur"tältä", +ur"dette", ur"कर", ur"senke", ur"where's", ur"jemand", ur"nous", ur"sedan", ur"sist", ur"heissä", ur"why", ur"senkt", ur"ingi", ur"veya", +ur"cima", ur"været", ur"nutzt", ur"muessen", ur"you'll", ur"beþ", ur"कई", ur"ÎÅÌØÚÑ", ur"tuotä", ur"így", ur"gdziekolwiek", ur"जैसे", ur"muy", ur"serías", +ur"nagy", ur"ismét", ur"niet", ur"zuerst", ur"×ÓÅÈ", ur"ÅÓÔØ", ur"soyez", ur"sÃ¥dant", ur"dunklen", ur"moet", ur"facevamo", ur"should", ur"nereye", ur"w³a¶nie", +ur"there's", ur"jak", ur"forem", ur"noin", ur"sonst", ur"intentamos", ur"ayez", ur"begonnen", ur"podia", ur"joina", ur"sinun", ur"deine", ur"sinua", +ur"avete", ur"ËÕÄÃ", ur"autor", ur"wordt", ur"Ó", ur"tilstand", ur"etwa", ur"nacher", ur"sinut", ur"aquí", ur"viel", ur"keiner", ur"keines", ur"ganzem", +ur"estaré", ur"ganzen", ur"seitdem", ur"στον", ur"gbr", ur"she", ur"ganzes", ur"ganzer", ur"keinem", ur"keinen", ur"muj", ur"×ÓÅÇÃ", ur"währenddessen", +ur"aquelas", ur"stets", ur"gefallen", ur"seite", ur"vært", ur"direkten", ur"podriamos", ur"soprattutto", ur"neben", ur"unnötig", ur"være", ur"schreibe", +ur"ert", ur"ponieważ", ur"miei", ur"wird", ur"statt", ur"seht", ur"ÓÃÃ", ur"setzten", ur"hiermit", ur"facciano", ur"berichtete", ur"below", ur"tene", +ur"tuvieron", ur"lub", ur"sehe", ur"byla", ur"nossas", ur"stato", ur"lui", ur"ús", ur"stati", ur"wollen", ur"houveremos", ur"olisivat", ur"moim", +ur"kei", ur"faremo", ur"tema", ur"trabalhar", ur"einfach", ur"dallo", ur"tat", ur"tentei", ur"ende", ur"kez", ur"avuta", ur"avute", ur"ets", ur"aqui", +ur"ett", ur"soeben", ur"è", ur"से", ur"conseguim", ur"conseguir", ur"también", ur"doksan", ur"houvessem", ur"möchte", ur"s", ur"suchen", +ur"ci", ur"co", ur"author", ur"sangen", ur"bsp.", ur"ca", ur"sitä", ur"étées", ur"ce", ur"trzeba", ur"cz", ur"ÄÃÖÅ", ur"ab", ur"heeft", ur"muesst", +ur"ÜÔÕ", ur"havde", ur"durfte", ur"niihin", ur"estaría", ur"aczkolwiek", ur"tiene", ur"he'd", ur"själv", ur"geehrten", ur"zehn", ur"jsou", ur"sara", +ur"farai", ur"keiksi", ur"faccio", ur"estén", ur"vors", ur"tenidos", ur"estava", ur"igen", ur"natürlich", ur"houverem", ur"allerlei", ur"estáis", +ur"alsbald", ur"queste", ur"aquellas", ur"c", ur"meus", ur"siamo", ur"sollst", ur"uns", ur"derartig", ur"ours", ur"jobban", ur"könn", ur"ott", +ur"estuvimos", ur"facessero", ur"indessen", ur"hubo", ur"tivéssemos", ur"é", ur"umas", ur"hube", ur"will", ur"estiver", ur"keiltä", ur"au", +ur"vilkas", ur"leer", ur"ill", ur"at", ur"kuka", ur"va", ur"questo", ur"ve", ur"letztens", ur"vi", ur"ÈÃÔØ", ur"längst", ur"ziehen", ur"nincs", +ur"vu", ur"nützt", ur"angesetzten", ur"mesmo", ur"sowie", ur"þunda", ur"parte", ur"δι", ur"sarà", ur"ÞÔÃÂ", ur"ju¿", ur"vore", ur"noe", ur"ergänzten", +ur"fleste", ur"nächste", ur"nada", ur"une", ur"tiempo", ur"näillä", ur"bald", ur"näistä", ur"tuohon", ur"essendo", ur"pelos", ur"estado", +ur"starà", ur"sugli", ur"soviel", ur"i", ur"serían", ur"ÕÖ", ur"avevate", ur"these", ur"estuviésemos", ur"oft", ur"mÃ…te", ur"senza", ur"terzo", +ur"uno", ur"bekannte", ur"onde", ur"emplean", ur"lesz", ur"Ã’ÃÚ", ur"empleas", ur"emplear", ur"avrà", ur"nosaltres", ur"meissä", ur"jeji", ur"कहते", +ur"weg", ur"przede", ur"çok", ur"estaríamos", ur"vÖre", ur"getan", ur"wen", ur"wem", ur"wel", ur"gleich", ur"wer", ur"habríamos", ur"werd", ur"protoze", +ur"vÖrt", ur"houvermos", ur"gute", ur"ought", ur"sich", ur"mis", ur"amit", ur"haut", ur"लिà¤", ur"þu", ur"jonka", ur"zostaÅ‚", ur"ayant", ur"niillä", +ur"þeyler", ur"you", ur"houvesse", ur"estarán", ur"budes", ur"kilka", ur"hubimos", ur"like", ur"×ÓÅÇÄÃ", ur"dennoch", ur"spielen", ur"cikkek", +ur"olitte", ur"mía", ur"vermutlich", ur"sagen", ur"jedoch", ur"teremos", ur"unterbrechen", ur"hossen", ur"budem", ur"why's", ur"kdo", ur"irgendwie", +ur"mihin", ur"schätzen", ur"otras", ur"kde", ur"vosotros", ur"ktokolwiek", ur"lagen", ur"jotka", ur"shan't", ur"csak", ur"est", ur"zwei", ur"dagl", +ur"fanno", ur"kleinen", ur"doen", ur"stieg", ur"kleines", ur"kleiner", ur"bardzo", ur"does", ur"esa", ur"miÄ™dzy", ur"olin", ur"sette", ur"estic", +ur"erais", ur"teihin", ur"puedo", ur"usan", ur"hajamos", ur"Ã…ÃÃ…", ur"mitt", ur"fordi", ur"puede", ur"agli", ur"ayons", ur"oben", ur"hoss", ur"usas", +ur"usar", ur"niille", ur"after", ur"vosotras", ur"about", ur"também", ur"anden", ur"estábamos", ur"daran", ur"lhe", ur"ander", ur"hier", ur"andet", +ur"irgendwas", ur"em", ur"wszystko", ur"eins", ur"ÃŽÃÄÃ", ur"solcher", ur"mert", ur"ön", ur"teus", ur"più", ur"donde", ur"eine", ur"ÔÃÃ", ur"ei", +ur"mere", ur"wollt", ur"jine", ur"है", ur"हो", ur"vai", ur"van", ur"vam", ur"ही", ur"vad", ur"quante", ur"eussions", ur"quanta", ur"ed", ur"var", ur"vas", +ur"quanto", ur"nÃ¥r", ur"hvornÃ¥r", ur"Ó×ÃÀ", ur"faranno", ur"persze", ur"i've", ur"haette", ur"andernfalls", ur"but", ur"kenessä", ur"ho", ur"farete", ur"ha", +ur"ultimo", ur"geblieben", ur"he", ur"ezért", ur"davor", ur"néha", ur"seit", ur"dagli", ur"houvéramos", ur"znów", ur"j", ur"ÕÖÅ", ur"zufolge", ur"wär", ur"olemme", +ur"seid", ur"sein", ur"davon", ur"hvad", ur"braucht", ur"stesse", ur"povo", ur"vuestros", ur"amelyek", ur"innerhalb", ur"ins", ur"vostri", ur"inn", ur"überallhin", +ur"jag", ur"vostro", ur"ind", ur"vostra", ur"dalsi", ur"mye", ur"piu", ur"aies", ur"arra", ur"tendrán", ur"deires", ur"siano", ur"other", ur"seus", ur"disse", +ur"prave", ur"sarete", ur"tenhamos", ur"ogsÃ¥", ur"után", ur"fois", ur"hubieron", ur"quarto", ur"ese", ur"müßte", ur"há", ur"stai", ur"reagierte", ur"ÎÉÈ", +ur"trotzdem", ur"ogsÃ…", ur"ÎÉÃ", ur"pode", ur"außerdem", ur"estuviste", ur"Ä×Ã", ur"allein", ur"mistä"]) + diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/stringdists.py b/interactive-mining-3rdparty-madis/madis/src/lib/stringdists.py new file mode 100644 index 0000000..9fb2321 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/stringdists.py @@ -0,0 +1,79 @@ +import difflib + +def dameraulevenshtein_dist(seq1, seq2): + """Calculate the Damerau-Levenshtein distance between sequences. + + This distance is the number of additions, deletions, substitutions, + and transpositions needed to transform the first sequence into the + second. Although generally used with strings, any sequences of + comparable objects will work. + + Transpositions are exchanges of *consecutive* characters; all other + operations are self-explanatory. + + This implementation is O(N*M) time and O(M) space, for N and M the + lengths of the two sequences. + + >>> dameraulevenshtein('ba', 'abc') + 2 + >>> dameraulevenshtein('fee', 'deed') + 2 + + It works with arbitrary sequences too: + >>> dameraulevenshtein('abcd', ['b', 'a', 'c', 'd', 'e']) + 2 + """ + # codesnippet:D0DE4716-B6E6-4161-9219-2903BF8F547F + # Conceptually, this is based on a len(seq1) + 1 * len(seq2) + 1 matrix. + # However, only the current and two previous rows are needed at once, + # so we only store those. + oneago = None + thisrow = range(1, len(seq2) + 1) + [0] + for x in xrange(len(seq1)): + # Python lists wrap around for negative indices, so put the + # leftmost column at the *end* of the list. This matches with + # the zero-indexed strings and saves extra calculation. + twoago, oneago, thisrow = oneago, thisrow, [0] * len(seq2) + [x + 1] + for y in xrange(len(seq2)): + delcost = oneago[y] + 1 + addcost = thisrow[y - 1] + 1 + subcost = oneago[y - 1] + (seq1[x] != seq2[y]) + thisrow[y] = min(delcost, addcost, subcost) + # This block deals with transpositions + if (x > 0 and y > 0 and seq1[x] == seq2[y - 1] + and seq1[x-1] == seq2[y] and seq1[x] != seq2[y]): + thisrow[y] = min(thisrow[y], twoago[y - 2] + 1) + return thisrow[len(seq2) - 1] + +def levenshtein_dist(a, b): + """ + Compute the Levenshtein distance between two given + strings (a and b). Taken from m.l. hetland + """ + n, m = len(a), len(b) + if n > m: + # Make sure n <= m, to use O(min(n,m)) space + a,b = b,a + n,m = m,n + current = xrange(n+1) + for i in xrange(1,m+1): + previous, current = current, [i]+[0] * m + for j in xrange(1, n+1): + add, delete = previous[j] + 1, current[j-1] + 1 + change = previous[j-1] + if a[j-1] != b[i-1]: + change +=1 + current[j] = min(add, delete, change) + return current[n] + +def quick_string_dist(a,b): + """ + Computes a quick string distance between two given + strings (a and b) using Python's difflib. + """ + + t=0 + for i in difflib.SequenceMatcher(None, a, b).get_opcodes(): + if i[0]=='equal': continue + t=t+max(i[4]-i[3],i[2]-i[1]) + return t diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/textcat.py b/interactive-mining-3rdparty-madis/madis/src/lib/textcat.py new file mode 100644 index 0000000..49b67c3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/textcat.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python + +# Copyright (c) 2006 Thomas Mangin + +# Modifications 25.11.2007 by Christoph Burgmer +# christoph.burgmer@stud.uni-karlsruhe.de +# Not the best match is taken but a language from a given list is prefered in +# the order the languages are given to the class: if a given language is found +# under the best five matches, it is prefered over the top match. + +#This program is distributed under Gnu General Public License +#(cf. the file COPYING in distribution). Alternatively, you can use +#the program under the conditions of the Artistic License (as Perl). + +#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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import re +import os + +nb_ngrams = 400 +lm_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'LM') + +class _NGram: + def __init__ (self, arg={}): + t = type(arg) + if t == type(""): + self.addText(arg) + self.normalise() + elif t == type({}): + self.ngrams = arg + self.normalise() + else: + self.ngrams = dict() + self.ngramsset=set(self.ngrams) + + def addText (self, text): + ngrams = dict() + + text = text.replace('\n', ' ') + text = re.sub('\s+', ' ', text) + words = text.split(' ') + + for word in words: + word = '_' + word + '_' + size = len(word) + for i in xrange(size): + for s in xrange(1, 5): + sub = word[i:i + s] + ngrams[sub] = ngrams.get(sub, 0) + 1 + + if i + s >= size: + break + self.ngrams = ngrams + return self + + def sorted (self): + sorted = [(self.ngrams[k], k) for k in self.ngrams] + sorted.sort(reverse=True) + sorted = sorted[:nb_ngrams] + return sorted + + def normalise (self): + count = 0 + ngrams = dict() + for v, k in self.sorted(): + ngrams[k] = count + count += 1 + + self.ngrams = ngrams + return self + + def addValues (self, key, value): + self.ngrams[key] = value + return self + + def compare (self, ngram): + d = 0 + ngrams = ngram.ngrams + ngram_intersection=self.ngramsset & ngram.ngramsset + for k in ngram_intersection: + d += abs(ngrams[k] - self.ngrams[k]) + d+=(len(self.ngrams)-len(ngram_intersection))*nb_ngrams + return d + + +import os +import glob + +class NGram: + def __init__ (self, folder=lm_path, ext='.lm', language_order=[]): + self.language_order = language_order + self.ngrams = dict() + folder = os.path.join(folder, '*' + ext) + size = len(ext) + count = 0 + + for fname in glob.glob(os.path.normcase(folder)): + count += 1 + lang = os.path.split(fname)[-1][:-size] + ngrams = dict() + file = open(fname, 'r') + + for line in file.readlines(): + parts = line[:-1].split('\t ') + if len(parts) != 2: + raise ValueError("invalid language file %s line : %s" % (fname, parts)) + try: + ngrams[parts[0]] = int(parts[1]) + except KeyboardInterrupt: + raise + except: + raise ValueError("invalid language file %s line : %s" % (fname, parts)) + + if len(ngrams.keys()): + self.ngrams[lang] = _NGram(ngrams) + + file.close() + + if not count: + raise ValueError("no language files found") + + def classify (self, text): + ngram = _NGram(text) + + langs = self.ngrams.keys() + r = langs.pop() + min = self.ngrams[r].compare(ngram) + + for lang in langs: + d = self.ngrams[lang].compare(ngram) + if d < min: + min = d + r = lang + + return r + + def getLanguages(self): + return self.ngrams.keys() + +class Generate: + def __init__ (self, folder, ext='.txt'): + self.ngrams = dict() + folder = os.path.join(folder, '*' + ext) + size = len(ext) + count = 0 + + for fname in glob.glob(os.path.normcase(folder)): + count += 1 + lang = os.path.split(fname)[-1][:-size] + n = _NGram() + + file = open(fname, 'r') + for line in file.readlines(): + n.addText(line) + file.close() + + n.normalise() + self.ngrams[lang] = n + + def save (self, folder, ext='.lm'): + for lang in self.ngrams.keys(): + fname = os.path.join(folder, lang + ext) + file = open(fname, 'w') + for v, k in self.ngrams[lang].sorted(): + file.write("%s\t %d\n" % (k, v)) + file.close() + +if __name__ == '__main__': + import sys + + # Should you want to generate your own .lm files + #conf = Generate('/tmp') + #conf.save('/tmp') + + text = sys.stdin.readline() + + l = NGram() + print l.classify(text) diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/unicodeops.py b/interactive-mining-3rdparty-madis/madis/src/lib/unicodeops.py new file mode 100644 index 0000000..48d50be --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/unicodeops.py @@ -0,0 +1,8 @@ +def unistr(s): + import types + if type(s)==types.StringType: + return unicode(s,'utf-8') + if type(s)==types.UnicodeType: + return s + else: + return unicode(s) \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/vtoutgtable.py b/interactive-mining-3rdparty-madis/madis/src/lib/vtoutgtable.py new file mode 100644 index 0000000..cc0840d --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/vtoutgtable.py @@ -0,0 +1,104 @@ +from gtable import gtablefileFull , gjsonfileFull ,gjsonFull +from iterutils import peekable +from sqlitetypes import typestoSqliteTypes +import types + + +def vtoutpugtformat(out,diter,simplejson=True): #### TODO Work on types patttern + """ + Reads diter stream of tuples(row,types) and formats row values to + the google json format or if simplejson is False to the google like format. + Writes formated tables in file like stream out the + """ + def unfold(it): + for row,h in it: + yield row + return + d=peekable(diter) + samplevals, sampleheads =d.peek() + names=[] + gtypes=[] + + mustguess=False + for val, headinfo in zip(samplevals, sampleheads): + names.append(headinfo[0].title()) + coltype=typestoSqliteTypes(headinfo[1]) + + if coltype=="INTEGER" or coltype=="REAL" or coltype=="NUMERIC": + gtypes.append('number') + elif coltype=="TEXT": + gtypes.append('string') + else: + mustguess=True + + gtypes.append("GUESS") + if mustguess: + samples=d.maxpeek(30) + samplestats=dict() + for i in xrange(len(gtypes)): + if gtypes[i]=="GUESS": + samplestats[i]={'string':False,"number":False} + for row in unfold(samples): + allknown=True + for uto in samplestats: + if not samplestats[uto]['string']: + allknown=False + if row[uto]!="": + samplestats[uto][typeguessing(row[uto])]=True + if allknown: + break + for uto in samplestats: + if samplestats[uto]['string']:# or not samplestats[uto]['number']: + gtypes[uto]='string' + else: + gtypes[uto]='number' + + + if simplejson: + #out.write(gjsonFull(unfold(d),names,gtypes).encode('utf-8')) + gjsonfileFull(unfold(d),out,names,gtypes) + else: + gtablefileFull(unfold(d),out,names,gtypes) + #out.write(gtableFull(unfold(d),names,gtypes).encode('utf-8')) + + + +def typeguessing(el): ####Oi upoloipoi typoi +# import types +# if type(el) not in types.StringTypes: +# print "Element is : --%s-- , Type is %s Type of element not string!!!!!!!!!!!!!" %(el,type(el)) +# raise Exception + if type(el) not in types.StringTypes: + el=str(el) + if el.startswith("0") and not el.startswith("0."): + return 'string' + try: + int(el) + return 'number' + except ValueError: + try: + float(el) + return 'number' + except ValueError: + return 'string' + + + +""" +cols property +--------------- +cols is an array of objects describing the ID and type of each column. Each property is an object with the following properties (case-sensitive): + + * type [Required] Data type of the data in the column. Supports the following string values (examples include the v: property, described later): + o 'boolean' - JavaScript boolean value ('true' or 'false'). Example value: v:'true' + o 'number' - JavaScript number value. Example values: v:7 , v:3.14, v:-55 + o 'string' - JavaScript string value. Example value: v:'hello' + o 'date' - JavaScript Date object (zero-based month), with the time truncated. Example value: v:new Date(2008, 0, 15) + o 'datetime' - JavaScript Date object including the time. Example value: v:new Date(2008, 0, 15, 14, 30, 45) + o 'timeofday' - Array of three numbers and an optional fourth, representing hour (0 indicates midnight), minute, second, and optional millisecond. Example values: v:[8, 15, 0], v: [6, 12, 1, 144] + * id [Optional] String ID of the column. Must be unique in the table. Use basic alphanumeric characters, so the host page does not require fancy escapes to access the column in JavaScript. Be careful not to choose a JavaScript keyword. Example: id:'col_1' + * label [Optional] String value that some visualizations display for this column. Example: label:'Height' + * pattern [Optional] String pattern that was used by a data source to format numeric, date, or time column values. This is for reference only; you probably won't need to read the pattern, and it isn't required to exist. The Google Visualization client does not use this value (it reads the cell's formatted value). If the DataTable has come from a data source in response to a query with a format clause, the pattern you specified in that clause will probably be returned in this value. The recommended pattern standards are the ICU DecimalFormat and SimpleDateFormat. + * p [Optional] An object that is a map of custom values applied to the cell. These values can be of any JavaScript type. If your visualization supports any cell-level properties, it will describe them; otherwise, this property will be ignored. Example: p:{style: 'border: 1px solid green;'}. + +""" \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/winunicode.py b/interactive-mining-3rdparty-madis/madis/src/lib/winunicode.py new file mode 100644 index 0000000..c05121f --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/winunicode.py @@ -0,0 +1,194 @@ +import sys +if sys.platform == "win32": + import codecs + from ctypes import WINFUNCTYPE, windll, POINTER, byref, c_int + from ctypes.wintypes import BOOL, HANDLE, DWORD, LPWSTR, LPCWSTR, LPVOID + + original_stderr = sys.stderr + + # If any exception occurs in this code, we'll probably try to print it on stderr, + # which makes for frustrating debugging if stderr is directed to our wrapper. + # So be paranoid about catching errors and reporting them to original_stderr, + # so that we can at least see them. + def _complain(message): + print >>original_stderr, isinstance(message, str) and message or repr(message) + + # Work around . + codecs.register(lambda name: name == 'cp65001' and codecs.lookup('utf-8') or None) + + # Make Unicode console output work independently of the current code page. + # This also fixes . + # Credit to Michael Kaplan + # and TZOmegaTZIOY + # . + try: + # + # HANDLE WINAPI GetStdHandle(DWORD nStdHandle); + # returns INVALID_HANDLE_VALUE, NULL, or a valid handle + # + # + # DWORD WINAPI GetFileType(DWORD hFile); + # + # + # BOOL WINAPI GetConsoleMode(HANDLE hConsole, LPDWORD lpMode); + + GetStdHandle = WINFUNCTYPE(HANDLE, DWORD)(("GetStdHandle", windll.kernel32)) + STD_OUTPUT_HANDLE = DWORD(-11) + STD_ERROR_HANDLE = DWORD(-12) + GetFileType = WINFUNCTYPE(DWORD, DWORD)(("GetFileType", windll.kernel32)) + FILE_TYPE_CHAR = 0x0002 + FILE_TYPE_REMOTE = 0x8000 + GetConsoleMode = WINFUNCTYPE(BOOL, HANDLE, POINTER(DWORD)) \ + (("GetConsoleMode", windll.kernel32)) + INVALID_HANDLE_VALUE = DWORD(-1).value + + def not_a_console(handle): + if handle == INVALID_HANDLE_VALUE or handle is None: + return True + return ((GetFileType(handle) & ~FILE_TYPE_REMOTE) != FILE_TYPE_CHAR + or GetConsoleMode(handle, byref(DWORD())) == 0) + + old_stdout_fileno = None + old_stderr_fileno = None + if hasattr(sys.stdout, 'fileno'): + old_stdout_fileno = sys.stdout.fileno() + if hasattr(sys.stderr, 'fileno'): + old_stderr_fileno = sys.stderr.fileno() + + STDOUT_FILENO = 1 + STDERR_FILENO = 2 + real_stdout = (old_stdout_fileno == STDOUT_FILENO) + real_stderr = (old_stderr_fileno == STDERR_FILENO) + + if real_stdout: + hStdout = GetStdHandle(STD_OUTPUT_HANDLE) + if not_a_console(hStdout): + real_stdout = False + + if real_stderr: + hStderr = GetStdHandle(STD_ERROR_HANDLE) + if not_a_console(hStderr): + real_stderr = False + + if real_stdout or real_stderr: + # BOOL WINAPI WriteConsoleW(HANDLE hOutput, LPWSTR lpBuffer, DWORD nChars, + # LPDWORD lpCharsWritten, LPVOID lpReserved); + + WriteConsoleW = WINFUNCTYPE(BOOL, HANDLE, LPWSTR, DWORD, POINTER(DWORD), \ + LPVOID)(("WriteConsoleW", windll.kernel32)) + + class UnicodeOutput: + def __init__(self, hConsole, stream, fileno, name): + self._hConsole = hConsole + self._stream = stream + self._fileno = fileno + self.closed = False + self.softspace = False + self.mode = 'w' + self.encoding = 'utf-8' + self.name = name + self.flush() + + def isatty(self): + return False + def close(self): + # don't really close the handle, that would only cause problems + self.closed = True + def fileno(self): + return self._fileno + def flush(self): + if self._hConsole is None: + try: + self._stream.flush() + except Exception, e: + _complain("%s.flush: %r from %r" + % (self.name, e, self._stream)) + raise + + def write(self, text): + try: + if self._hConsole is None: + if isinstance(text, unicode): + text = text.encode('utf-8') + self._stream.write(text) + else: + if not isinstance(text, unicode): + text = str(text).decode('utf-8') + remaining = len(text) + while remaining > 0: + n = DWORD(0) + # There is a shorter-than-documented limitation on the + # length of the string passed to WriteConsoleW (see + # . + retval = WriteConsoleW(self._hConsole, text, + min(remaining, 10000), + byref(n), None) + if retval == 0 or n.value == 0: + raise IOError("WriteConsoleW returned %r, n.value = %r" + % (retval, n.value)) + remaining -= n.value + if remaining == 0: break + text = text[n.value:] + except Exception, e: + _complain("%s.write: %r" % (self.name, e)) + raise + + def writelines(self, lines): + try: + for line in lines: + self.write(line) + except Exception, e: + _complain("%s.writelines: %r" % (self.name, e)) + raise + + if real_stdout: + sys.stdout = UnicodeOutput(hStdout, None, STDOUT_FILENO, + '') + else: + sys.stdout = UnicodeOutput(None, sys.stdout, old_stdout_fileno, + '') + + if real_stderr: + sys.stderr = UnicodeOutput(hStderr, None, STDERR_FILENO, + '') + else: + sys.stderr = UnicodeOutput(None, sys.stderr, old_stderr_fileno, + '') + except Exception, e: + _complain("exception %r while fixing up sys.stdout and sys.stderr" % (e,)) + + + # While we're at it, let's unmangle the command-line arguments: + + # This works around . + GetCommandLineW = WINFUNCTYPE(LPWSTR)(("GetCommandLineW", windll.kernel32)) + CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int)) \ + (("CommandLineToArgvW", windll.shell32)) + + argc = c_int(0) + argv_unicode = CommandLineToArgvW(GetCommandLineW(), byref(argc)) + + argv = [argv_unicode[i].encode('utf-8') for i in xrange(0, argc.value)] + + if not hasattr(sys, 'frozen'): + # If this is an executable produced by py2exe or bbfreeze, then it will + # have been invoked directly. Otherwise, unicode_argv[0] is the Python + # interpreter, so skip that. + argv = argv[1:] + + # Also skip option arguments to the Python interpreter. + while len(argv) > 0: + arg = argv[0] + if not arg.startswith(u"-") or arg == u"-": + break + argv = argv[1:] + if arg == u'-m': + # sys.argv[0] should really be the absolute path of the module source, + # but never mind + break + if arg == u'-c': + argv[0] = u'-c' + break + + # if you like: + sys.argv = argv \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/lib/ziputils.py b/interactive-mining-3rdparty-madis/madis/src/lib/ziputils.py new file mode 100644 index 0000000..4d1e265 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/lib/ziputils.py @@ -0,0 +1,35 @@ +import zipfile +import tempfile +class ZipIter: + def __init__(self,filename,mode="r"): + if mode!="r" and mode!="rb" and mode!="w" and mode!="wb": + raise Exception("Unknown mode") + self.mode=mode + if mode[0]=="r": #READ MODE + self.zipfolder=zipfile.ZipFile(filename,mode) + self.name=self.zipfolder.namelist()[0] + self.zipfolder.extract(self.name) + self.zipfolder.close() + self.f=open(self.name,mode) + + pass + if mode[0]=="w": #WRITE MODE + self.zipfolder=zipfile.ZipFile(filename+".zip",mode) + self.name=filename + self.f=open(filename,mode) + def __iter__(self): + return self + def __getattr__(self, attr): + if self.__dict__.has_key(attr): + return self.__dict__[attr] + return getattr(self.f, attr) + + + + def close(self): + self.f.close() + if self.mode[0]=="w": + self.zipfolder.write(self.name,self.name.rsplit('/',1)[-1]) + self.zipfolder.close() + import os + os.remove(self.name) \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/libexternal/__init__.py b/interactive-mining-3rdparty-madis/madis/src/libexternal/__init__.py new file mode 100644 index 0000000..2a1dfa1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/libexternal/__init__.py @@ -0,0 +1 @@ +# Place here external libraries which will be called via pyfun diff --git a/interactive-mining-3rdparty-madis/madis/src/madis.py b/interactive-mining-3rdparty-madis/madis/src/madis.py new file mode 100644 index 0000000..1d17c95 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/madis.py @@ -0,0 +1 @@ +import functions diff --git a/interactive-mining-3rdparty-madis/madis/src/mexec.py b/interactive-mining-3rdparty-madis/madis/src/mexec.py new file mode 100644 index 0000000..6c4a9bb --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/mexec.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python + +from optparse import OptionParser +import sys +import apsw +import madis +import json + +def exitwitherror(txt): + sys.stderr.write(txt+'\n') + sys.exit(1) + +def main(): + desc="""Use this program to run madSQL queries on data coming from standard input. You may provide a database to run your queries. Results are streamed to standard output. + """ + parser = OptionParser(description=desc, usage="usage: %prog [options] [dbname] flowname", + version="%prog 1.0") + parser.add_option("-f", "--flow", + help="flow file to execute") + parser.add_option("-d", "--db", + help="db to connect") + parser.add_option("-w", "--dbw", + help="db to connect (open in create mode)") + + + (options, args) = parser.parse_args() + + dbname = '' + flags = apsw.SQLITE_OPEN_READWRITE | apsw.SQLITE_OPEN_CREATE + try: + dbname = args[0] + flags = apsw.SQLITE_OPEN_READWRITE + except: + pass + + if options.db != None: + dbname = options.db + flags = apsw.SQLITE_OPEN_READWRITE + + if options.dbw != None: + dbname = options.dbw + + try: + Connection=madis.functions.Connection(dbname, flags) + + except Exception, e: + exitwitherror("Error in opening DB: " + str(dbname) + "\nThe error was: " + str(e)) + + flowname = None + try: + flowname = args[1] + except: + pass + + if options.flow != None: + flowname = options.flow + + if flowname == None: + parser.print_help() + sys.exit(1) + + try: + f = open(flowname,'r') + except Exception, e: + exitwitherror("Error in opening SQL flow: " + str(e)) + + + statement = f.readline() + if not statement: + sys.exit() + + while True: + while not apsw.complete(statement): + line = f.readline() + statement += line + if not line: + if statement.rstrip('\r\n')!='': + sys.stderr.write("Incomplete query:"+statement) + f.close() + sys.exit() + try : + for row in Connection.cursor().execute(statement): + if len(row) > 1: + print(json.dumps(row, separators=(',',':'), ensure_ascii=False).encode('utf_8', 'replace')) + else: + print(unicode(row[0]).encode('utf_8', 'replace')) + statement = '' + except Exception, e: + exitwitherror("Error when executing query: \n"+statement+"\nThe error was: "+ str(e)) + + +if __name__ == '__main__': + main() + + diff --git a/interactive-mining-3rdparty-madis/madis/src/mterm.py b/interactive-mining-3rdparty-madis/madis/src/mterm.py new file mode 100755 index 0000000..94bbd86 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/mterm.py @@ -0,0 +1,960 @@ +#!/usr/bin/env python + +import os +import sys + +# Workaround for MAC utf-8 encoding +if sys.platform == 'darwin': + os.environ['LC_ALL']='en_US.UTF-8' + reload(sys) + sys.setdefaultencoding("utf-8") + +# Workaround for windows - DISABLED +#try: import lib.winunicode +#except ImportError: pass +#else: del lib.winunicode + +import functions +import re +import apsw +import traceback +import json +import math +import random + +pipedinput=not sys.stdin.isatty() +errorexit = True +nobuf = False + +if pipedinput: + # If we get piped input use dummy readline + readline=lambda x:x + readline.remove_history_item=lambda x:x + readline.read_history_file=lambda x:x + readline.write_history_file=lambda x:x + readline.set_completer=lambda x:x + readline.add_history=lambda x:x + readline.parse_and_bind=lambda x:x + readline.set_completer_delims=lambda x:x +else: + # Workaround for absence of a real readline module in win32 + import lib.reimport + if sys.platform == 'win32': + import pyreadline as readline + else: + import readline + +import datetime +import time +import locale +import os + +from lib.dsv import writer +import csv + +try: + if pipedinput: + raise 'go to except' + import lib.colorama as colorama + from colorama import Fore, Back, Style + colnums = True +except: + colorama=lambda x:x + def dummyfunction(): + pass + colorama.deinit = colorama.init = dummyfunction + Fore = Style = Back = dummyfunction + Fore.RED = Style.BRIGHT = Style.RESET_ALL = '' + colnums = False + pass + +DELIM = Fore.RED+Style.BRIGHT+'|'+Style.RESET_ALL + +class mtermoutput(csv.Dialect): + def __init__(self): + self.delimiter='|' + if not allquote: + self.quotechar='|' + self.quoting=csv.QUOTE_MINIMAL + else: + self.quotechar='"' + self.quoting=csv.QUOTE_NONNUMERIC + self.escapechar="\\" + self.lineterminator='\n' + +def createConnection(db): + try: + if 'SQLITE_OPEN_URI' in apsw.__dict__: + connection = functions.Connection(db, flags=apsw.SQLITE_OPEN_READWRITE | apsw.SQLITE_OPEN_CREATE | apsw.SQLITE_OPEN_URI) + else: + connection = functions.Connection(db) + functions.register(connection) + connection.enableloadextension(True) + except Exception, e: + exitwitherror(e) + + # Change TEMP store to where the mterm is run from + try: + connection.cursor().execute("PRAGMA temp_store_directory='.';PRAGMA page_size=16384;PRAGMA default_cache_size=3000;") + # if pipedinput: + except: + pass + + functions.settings['stacktrace'] = True + + return connection + +def reloadfunctions(): + global connection, automatic_reload, db + + if not automatic_reload: + return + + modified=lib.reimport.modified() + + if len(modified)==0 or (modified==['__main__']): + return + + tmp_settings=functions.settings + tmp_vars=functions.variables + connection.close() + try: + lib.reimport.reimport(*[x for x in modified if x != '__main__']) + except ValueError: + pass + + try: + lib.reimport.reimport('functionslocal') + except ValueError: + pass + + connection = createConnection(db) + functions.settings=tmp_settings + functions.variables=tmp_vars + +def raw_input_no_history(*args): + global pipedinput + + if pipedinput: + try: + input = raw_input() + except EOFError: + connection.close() + exit(0) + return input + + try: + input = raw_input(*args) + except: + return None + if input!='': + try: + readline.remove_history_item(readline.get_current_history_length()-1) + except: + pass + return input + +def update_tablelist(): + global alltables, alltablescompl, connection + alltables=[] + alltablescompl=[] + cursor = connection.cursor() + cexec=cursor.execute('PRAGMA database_list;') + for row in cexec: + cursor1 = connection.cursor() + if row[1]=='temp': + cexec1 = cursor1.execute("select name from sqlite_temp_master where type='table';") + else: + cexec1 = cursor1.execute("select name from "+row[1]+".sqlite_master where type='table';") + + for row1 in cexec1: + tname=row1[0].lower().encode('ascii') + if row[1] in ('main', 'temp'): + alltables.append(tname) + alltablescompl.append(tname) + else: + dbtname=(row[1]+'.'+tname).lower().encode('ascii') + alltables.append(dbtname) + alltablescompl.append(dbtname) + if tname not in alltablescompl: + alltablescompl.append(tname) + cursor1.close() + cursor.close() + +def get_table_cols(t): + global connection + + if '.' in t: + ts=t.split('.') + dbname=ts[0] + tname='.'.join(ts[1:]) + else: + dbname='main' + tname=t + cursor = connection.cursor() + if dbname=='main': + cexec=cursor.execute('pragma table_info('+str(tname)+')') + cols=[x[1] for x in cexec] + else: + cexec=cursor.execute('select * from '+str(tname)) + cols=[x[0] for x in cursor.getdescriptionsafe()] + return cols + +def sizeof_fmt(num, use_kibibyte=False): + base, infix = [(1000.,''),(1024.,'i')][use_kibibyte] + for x in ['','K%s'%infix,'M%s'%infix,'G%s'%infix]: + if num < base and num > -base: + if x == '': + return str(int(num)) + else: + return "%3.1f%s" % (num, x) + num /= base + return "%3.1f %s" % (num, 'T%sB'%infix) + +def approx_rowcount(t): + timer = time.time() + minrowid = list(connection.cursor().execute('select min(_rowid_) from ' + t, parse=False))[0][0] + maxrowid = list(connection.cursor().execute('select max(_rowid_) from ' + t, parse=False))[0][0] + if maxrowid is None or minrowid is None: + return 0 + idrange = maxrowid - minrowid + 1 + if (time.time() - timer) > 0.5: + return idrange + samplesize = min(int(math.sqrt(idrange)), 100) + if samplesize == 0: + return 0 + step = idrange / samplesize + sample = range(random.randrange(0, step) + minrowid, maxrowid + 1, step) + samplesize = len(sample) + samplehits = 0 + samplestep = 1 + timer = time.time() + while sample != []: + samplehits += list(connection.cursor().execute( + 'select count(*) from ' + t + + ' where _rowid_ in (' + ','.join([str(x) for x in sample[:samplestep]]) + ');', parse=False))[0][0] + sample = sample[samplestep:] + samplestep *= 2 + estimt = samplesize * (time.time() - timer) / (samplesize - len(sample)) + if estimt > 0.5: + return idrange + return int(idrange * float(samplehits) / samplesize) + + +def update_cols_for_table(t): + global alltablescompl, colscompl, lastcols, connection, updated_tables + if t!='': + if t[-1]=='.': + t=t[0:-1] + if t[-2:]=='..': + t=t[0:-2] + + if t in alltablescompl and t not in updated_tables: + try: + cols=get_table_cols(t) + updated_tables.add(t) + colscompl+= ['.'.join([ t, x ]) for x in cols] + colscompl+= [x for x in cols] + colscompl+=[t+'..'] + except: + pass + try: + if '.' in t: + ts=t.split('.') + dbname=ts[0] + tname='.'.join(ts[1:]) + else: + dbname='main' + tname=t + cursor = connection.cursor() + cexec=cursor.execute('select * from '+dbname+".sqlite_master where type='index' and tbl_name='"+str(tname)+"'") + icompl= [x[1] for x in cexec] + colscompl+= ['.'.join([ t, x ]) for x in icompl] + colscompl+= icompl + except: + pass + try: + colscompl=list(set(colscompl)-set(lastcols)) + except: + pass + +_update_cols_from_tables_last_text='' +def update_cols_from_tables_in_text(t): + global alltablescompl, _update_cols_from_tables_last_text + + if t==_update_cols_from_tables_last_text: + return + + _update_cols_from_tables_last_text=t + + stablesreg='|'.join( (x.replace('$','\$').replace('.', '\.') for x in sorted(alltablescompl, key=len, reverse=True)) ) + foundtables=re.findall(r'[^a-zA-Z0-9_$]('+stablesreg+r')[,.\s)]', t+u' ') + + for i in foundtables: + update_cols_for_table(i) + + +def mcomplete(textin,state): + global number_of_kb_exceptions + number_of_kb_exceptions = 0 + + def normalizename(col): + if re.match(ur'\.*[\w_$\d.]+\s*$', col,re.UNICODE): + return col + else: + return "`"+col.lower()+"`" + + def numberedlist(c): + maxcolchars=len(str(len(c)+1)) + formatstring='{:'+'>'+str(maxcolchars)+'}' + o=[] + for num in xrange(len(c)): + o.append( formatstring.format(num+1)+'|'+c[num] ) + return o + + text=textin + + #Complete \t to tabs + if text[-2:]=='\\t': + if state==0: return text[:-2]+'\t' + else: return + + prefix='' + + localtables=[] + completions=[] + + linebuffer=readline.get_line_buffer() + + beforecompl= linebuffer[0:readline.get_begidx()] + + # Only complete '.xxx' completions when space chars exist before completion + if re.match(r'\s*$', beforecompl): + completions+=dotcompletions + # If at the start of the line, show all tables + if beforecompl=='' and text=='': + localtables=alltables[:] + + # Check if all tables start with the same character + if localtables!=[]: + prefcharset=set( (x[0] for x in localtables) ) + if len(prefcharset)==1: + localtables+=[' '] + completions=localtables + # If completion starts at a string boundary, complete from local dir + elif beforecompl!='' and beforecompl[-1] in ("'", '"'): + completions=os.listdir(os.getcwdu()) + hits=[x for x in completions if x[:len(text)]==unicode(text)] + if state=0: + # Show all tables when completing 0 + if icol==0 and newcols!=[]: + if len(newcols)==1: + if state>0: return + return prefix+normalizename(newcols[0]) + hits = numberedlist(newcols) + if statecharspercolname and len(cols)>1: + i=i[0:charspercolname-1]+'..' + else: + i=i+' ' + sys.stdout.write(Fore.RED+'['+Style.BRIGHT+str(i1)+Style.NORMAL+'|'+Style.RESET_ALL+i) + i1+=1 + sys.stdout.write('\n') + +def printrow(row): + global rawprinter, colnums + + if not colnums: + rawprinter.writerow(row) + return + + rowlen=len(row) + i1=1 + for d in row: + if rowlen>3: + if i1==1: + sys.stdout.write(Fore.RED+Style.BRIGHT+'['+'1'+'|'+Style.RESET_ALL) + else: + sys.stdout.write(Fore.RED+'['+str(i1)+Style.BRIGHT+'|'+Style.RESET_ALL) + else: + if i1!=1: + sys.stdout.write(Fore.RED+Style.BRIGHT+'|'+Style.RESET_ALL) + if type(d) in (int, float, long): + d=str(d) + elif d is None: + d=Style.BRIGHT+'null'+Style.RESET_ALL + try: + sys.stdout.write(d) + except KeyboardInterrupt: + raise + except: + sys.stdout.write(d.encode('utf_8', 'replace')) + + i1+=1 + sys.stdout.write('\n') + +def printterm(*args, **kwargs): + global pipedinput + + msg=','.join([unicode(x) for x in args]) + + if not pipedinput: + print(msg) + +def exitwitherror(*args): + msg=','.join([unicode(x) for x in args]) + + if errorexit: + print + sys.exit(msg) + else: + print(json.dumps({"error":msg}, separators=(',',':'), ensure_ascii=False).encode('utf_8', 'replace')) + print + sys.stdout.flush() + +def process_args(): + global connection, functions, errorexit, db, nobuf + + args = sys.argv[1:] + + # Continue on error when input is piped in + if len(args) >= 1 and pipedinput: + setargs = set(args) + if '-bailoff' in setargs or '-coe' in setargs: + try: + setargs.remove('-bailoff') + except KeyError: + pass + + try: + setargs.remove('-coe') + except KeyError: + pass + + errorexit = False + + if '-nobuf' in setargs: + setargs.remove('-nobuf') + nobuf = True + + args = list(setargs) + + if len(args) >= 1: + db = args[-1] + if db == "-q": + db = ':memory:' + + connection = createConnection(db) + + if db == '' or db == ':memory': + functions.variables.execdb = None + else: + functions.variables.execdb = str(os.path.abspath(os.path.expandvars(os.path.expanduser(os.path.normcase(db))))) + + # Found query in args + if len(args)>2: + st = ' '.join(args[2:]) + st = st.decode(output_encoding) + + c = connection.cursor() + try: + for r in c.execute(st): + rawprinter.writerow(r) + c.close() + except KeyboardInterrupt: + sys.exit() + finally: + try: + c.close() + except: + pass + sys.exit() + +VERSION='1.0' +mtermdetails="mTerm - version "+VERSION +intromessage="""Enter ".help" for instructions +Enter SQL statements terminated with a ";" """ + +helpmessage=""".functions Lists all functions +.help Show this message (also accepts '.h' ) +.help FUNCTION Show FUNCTION's help page +.quit Exit this program +.schema TABLE Show the CREATE statements +.quote Toggle between normal quoting mode and quoting all mode +.beep Make a sound when a query finishes executing +.tables List names of tables (you can also use ".t" or double TAB) +.t TABLE Browse table +.explain Explain query plan +.colnums Toggle showing column numbers +.separator SEP Change separator to SEP. For tabs use 'tsv' or '\\t' as SEP + Separator is used only when NOT using colnums +.vacuum Vacuum DB using a temp file in current path +.queryplan query Displays the queryplan of the query + +Use: FILE or CLIPBOARD function for importing data + OUTPUT or CLIPOUT function for exporting data""" + +if 'HOME' not in os.environ: # Windows systems + if 'HOMEDRIVE' in os.environ and 'HOMEPATH' in os.environ: + os.environ['HOME'] = os.path.join(os.environ['HOMEDRIVE'], os.environ['HOMEPATH']) + else: + os.environ['HOME'] = "C:\\" + +histfile = os.path.join(os.environ["HOME"], ".mterm") + +automatic_reload=False +if not pipedinput: + try: + readline.read_history_file(histfile) + except IOError: + pass + import atexit + atexit.register(readline.write_history_file, histfile) + + automatic_reload=True + readline.set_completer(mcomplete) + readline.parse_and_bind("tab: complete") + readline.set_completer_delims(' \t\n`!@#$^&*()=+[{]}|;:\'",<>?') + +separator = "|" +allquote = False +beeping = False +db = "" +language, output_encoding = locale.getdefaultlocale() + +if output_encoding==None: + output_encoding='UTF8' + +functions.variables.flowname='main' + +rawprinter=buildrawprinter(separator) + +process_args() + +sqlandmtermstatements=['select ', 'create ', 'where ', 'table ', 'group by ', 'drop ', 'order by ', 'index ', 'from ', 'alter ', 'limit ', 'delete ', '..', + "attach database '", 'detach database ', 'distinct', 'exists '] +dotcompletions=['.help ', '.colnums', '.schema ', '.functions ', '.tables', '.explain ', '.vacuum', '.queryplan '] +allfuncs=functions.functions['vtable'].keys()+functions.functions['row'].keys()+functions.functions['aggregate'].keys() +alltables=[] +alltablescompl=[] +updated_tables=set() +update_tablelist() +lastcols=[] +newcols=[] +colscompl=[] + +#Intro Message +if not pipedinput: + print mtermdetails + print "running on Python: "+'.'.join([str(x) for x in sys.version_info[0:3]])+', APSW: '+apsw.apswversion()+', SQLite: '+apsw.sqlitelibversion(), + try: + sys.stdout.write(", madIS: "+functions.VERSION+'\n') + except: + print + print intromessage + +number_of_kb_exceptions=0 +while True: + statement = raw_input_no_history("mterm> ") + if statement==None: + number_of_kb_exceptions+=1 + print + if number_of_kb_exceptions<2: + continue + else: + readline.write_history_file(histfile) + break + + #Skip comments + if statement.startswith('--'): + continue + + number_of_kb_exceptions=0 + statement=statement.decode(output_encoding) + #scan for commands + iscommand=re.match("\s*\.(?P\w+)\s*(?P([\w\.]*))(?P.*)$", statement) + validcommand=False + queryplan = False + + if iscommand: + validcommand=True + command=iscommand.group('command') + argument=iscommand.group('argument') + rest=iscommand.group('rest') + origstatement=statement + statement=None + + if command=='separator': + tmpseparator=separator + if argument=='csv': + separator = "," + elif argument in ('tsv','\\t','\t'): + separator = "\t" + else: + separator = argument + + if separator == '': + colnums = True + separator = '|' + + if separator!=tmpseparator: + colnums = False + rawprinter=buildrawprinter(separator) + + elif command=='explain': + statement=re.sub("^\s*\.explain\s+", "explain query plan ", origstatement) + + elif command=='queryplan': + try: + statement = re.match(r"\s*\.queryplan\s+(.+)", origstatement).groups()[0] + queryplan = True + except IndexError: + pass + + elif command=='quote': + allquote^=True + if allquote: + printterm("Quoting output, uncoloured columns") + colnums=False + else: + printterm("Not quoting output, coloured columns") + colnums=True + rawprinter=buildrawprinter(separator) + + elif command=='beep': + beeping^=True + if beeping: + printterm("Beeping enabled") + else: + printterm("Beeping disabled") + + elif command=='colnums': + colnums^=True + if colnums: + printterm("Colnums enabled") + else: + printterm("Colnums disabled") + + elif 'tables'.startswith(command): + update_tablelist() + argument=argument.rstrip('; ') + if not argument: + maxtlen = 0 + for i in sorted(alltables): + maxtlen = max(maxtlen, len(i)) + maxtlen += 1 + + for i in sorted(alltables): + l = ('{:<' + str(maxtlen) + '}').format(i) + + try: + l += DELIM + " cols:{:<4}".format(str(len(get_table_cols(i)))) + except KeyboardInterrupt: + print + break + except: + pass + + try: + l += DELIM + " ~rows:" + sizeof_fmt(approx_rowcount(i)) + except KeyboardInterrupt: + print + break + except: + pass + + printterm(l) + else: + statement = 'select * from '+argument+' limit 2;' + + elif 'select'.startswith(command): + update_tablelist() + argument = argument.rstrip('; ') + if not argument: + for i in sorted(alltables): + printterm(i) + else: + statement = 'select * from '+argument + ';' + + elif command=='vacuum': + statement="PRAGMA temp_store_directory = '.';VACUUM;PRAGMA temp_store_directory = '';" + + elif command=='schema': + if not argument: + statement="select sql from (select * from sqlite_master union all select * from sqlite_temp_master) where sql is not null;" + else: + argument=argument.rstrip('; ') + update_tablelist() + if argument not in alltables: + printterm("No table found") + else: + db='main' + if '.' in argument: + sa=argument.split('.') + db=sa[0] + argument=''.join(sa[1:]) + statement="select sql from (select * from "+db+".sqlite_master union all select * from sqlite_temp_master) where tbl_name like '%s' and sql is not null;" %(argument) + + elif "quit".startswith(command): + connection.close() + exit(0) + + elif command=="functions": + for ftype in functions.functions: + for f in functions.functions[ftype]: + printterm(f+' :'+ftype) + + elif "help".startswith(command): + if not argument: + printterm(helpmessage) + else: + for i in functions.functions: + if argument in functions.functions[i]: + printterm("Function "+ argument + ":") + printterm(functions.mstr(functions.functions[i][argument].__doc__)) + + elif command=="autoreload": + automatic_reload=automatic_reload ^ True + printterm("Automatic reload is now: " + str(automatic_reload)) + + else: + validcommand=False + printterm("""unknown command. Enter ".help" for help""") + + if validcommand: + histstatement='.'+command+' '+argument+rest + try: + readline.add_history(histstatement.encode('utf-8')) + except: + pass + + if statement: + histstatement=statement + while not apsw.complete(statement): + more = raw_input_no_history(' ..> ') + if more==None: + statement=None + break + more=more.decode(output_encoding) + statement = statement + '\n'.decode(output_encoding) + more + histstatement=histstatement+' '+more + + reloadfunctions() + number_of_kb_exceptions=0 + if not statement: + printterm() + continue + try: + if not validcommand: + readline.add_history(histstatement.encode('utf-8')) + except: + pass + + before = datetime.datetime.now() + try: + if queryplan: + cexec = connection.queryplan(statement) + desc = cexec.next() + else: + cursor = connection.cursor() + cexec = cursor.execute(statement) + try: + desc = cursor.getdescriptionsafe() + lastcols[0:len(desc)] = [x for x, y in desc] + except apsw.ExecutionCompleteError, e: + desc = [] + + newcols=[x for x,y in desc] + + colorama.init() + rownum=0 + + if not pipedinput: + for row in cexec: + printrow(row) + rownum+=1 + else: + print(json.dumps({"schema":desc}, separators=(',',':'), ensure_ascii=False).encode('utf_8', 'replace')) + for row in cexec: + print(json.dumps(row, separators=(',',':'), ensure_ascii=False).encode('utf_8', 'replace')) + if nobuf: + sys.stdout.flush() + print + sys.stdout.flush() + + if not queryplan: + cursor.close() + + after=datetime.datetime.now() + tmdiff=after-before + + schemaprint(newcols) + if not pipedinput: + if rownum==0: + printterm( "Query executed in %s min. %s sec %s msec." %((int(tmdiff.days)*24*60+(int(tmdiff.seconds)/60),(int(tmdiff.seconds)%60),(int(tmdiff.microseconds)/1000))) ) + else: + print "Query executed and displayed %s"%(rownum), + if rownum==1: print "row", + else: print "rows", + print "in %s min. %s sec %s msec." %((int(tmdiff.days)*24*60+(int(tmdiff.seconds)/60),(int(tmdiff.seconds)%60),(int(tmdiff.microseconds)/1000))) + if beeping: + printterm('\a\a') + + colscompl=[] + updated_tables=set() + + #Autoupdate in case of schema change + if re.search(r'(?i)(create|attach|drop)', statement): + update_tablelist() + + except KeyboardInterrupt: + print + schemaprint(newcols) + printterm("KeyboardInterrupt exception: Query execution stopped", exit=True) + continue + except (apsw.SQLError, apsw.ConstraintError , functions.MadisError), e: + emsg=unicode(e) + if pipedinput: + exitwitherror(functions.mstr(emsg)) + else: + try: + if u'Error:' in emsg: + emsgsplit=emsg.split(u':') + print Fore.RED+Style.BRIGHT+ emsgsplit[0] +u':'+Style.RESET_ALL+ u':'.join(emsgsplit[1:]) + else: + print e + except: + print e + + continue + except Exception, e: + trlines = [] + + for i in reversed(traceback.format_exc(limit=sys.getrecursionlimit()).splitlines()): + trlines.append(i) + if i.strip().startswith('File'): + break + + msg=Fore.RED+Style.BRIGHT+"Unknown error:" + Style.RESET_ALL + "\nTraceback is:\n" + '\n'.join(reversed(trlines)) + if pipedinput: + exitwitherror(functions.mstr(msg)) + else: + print msg + + finally: + colorama.deinit() + try: + cursor.close() + except: + #print "Not proper clean-up" + pass + diff --git a/interactive-mining-3rdparty-madis/madis/src/pypylib/apsw.py b/interactive-mining-3rdparty-madis/madis/src/pypylib/apsw.py new file mode 100644 index 0000000..9dfd329 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/pypylib/apsw.py @@ -0,0 +1,1961 @@ +######################################################### +# Simplified PyPy SQLite wrapper compatible with APSW +######################################################### + +from collections import OrderedDict +from cffi import FFI +from functools import wraps +import weakref +from codecs import utf_8_decode +from threading import _get_ident as thread_get_ident +from types import NoneType +from threading import _get_ident as _thread_get_ident +import sys +import os + +if hasattr(sys, 'pypy_version_info'): + from __pypy__ import newlist_hint +else: + newlist_hint = lambda size: [] + +ffi = FFI() +sqlite = ffi.dlopen("sqlite3") + +# pysqlite version information +version = "2.6.0" + +# pysqlite constants +PARSE_COLNAMES = 1 +PARSE_DECLTYPES = 2 + +SQLITE_OPEN_READWRITE = 2 +SQLITE_OPEN_CREATE = 4 +SQLITE_DENY = 1 + + + + + +########################################### +# BEGIN Wrapped SQLite C API and constants +########################################### + +ffi.cdef(""" +typedef struct sqlite3 sqlite3; +typedef struct sqlite3_stmt sqlite3_stmt; +typedef void (*sqlite3_destructor_type)(void*); +typedef struct sqlite3_context sqlite3_context; +typedef struct Mem sqlite3_value; +const char *sqlite3_errmsg(sqlite3*); +int sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs); +int sqlite3_close(sqlite3*); +int sqlite3_busy_timeout(sqlite3 *, int ms); +int sqlite3_total_changes(sqlite3*); +int sqlite3_prepare(sqlite3 *db,const char *zSql,int nByte,sqlite3_stmt **ppStmt,const char **pzTail); +int sqlite3_prepare_v2(sqlite3 *db,const char *zSql,int nByte,sqlite3_stmt **ppStmt,const char **pzTail); +int sqlite3_step(sqlite3_stmt*); +int sqlite3_reset(sqlite3_stmt *pStmt); +int sqlite3_finalize(sqlite3_stmt *pStmt); +int sqlite3_column_count(sqlite3_stmt *pStmt); +const char *sqlite3_column_name(sqlite3_stmt*, int N); +int sqlite3_column_type(sqlite3_stmt*, int iCol); +int sqlite3_extended_result_codes(sqlite3*, int onoff); +int64_t sqlite3_column_int64(sqlite3_stmt*, int iCol); +double sqlite3_column_double(sqlite3_stmt*, int iCol); +int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +const char *sqlite3_column_text(sqlite3_stmt*, int iCol); +const char *sqlite3_column_text16(sqlite3_stmt*, int iCol); +const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); +const char *sqlite3_column_decltype(sqlite3_stmt*,int); +int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +int sqlite3_bind_double(sqlite3_stmt*, int, double); +int sqlite3_bind_int(sqlite3_stmt*, int, int); + +int sqlite3_bind_null(sqlite3_stmt*, int); +int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); +int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); +int sqlite3_clear_bindings(sqlite3_stmt*); +int sqlite3_value_type(sqlite3_value*); +int64_t sqlite3_value_int64(sqlite3_value*); +int sqlite3_value_int(sqlite3_value*); +double sqlite3_value_double(sqlite3_value*); +int sqlite3_bind_parameter_count(sqlite3_stmt*); +int sqlite3_value_bytes(sqlite3_value*); +const unsigned char *sqlite3_value_text(sqlite3_value*); //Not used. +const void *sqlite3_value_blob(sqlite3_value*); +int sqlite3_changes(sqlite3*); +void sqlite3_result_error(sqlite3_context*, const char*, int); +void sqlite3_result_error_code(sqlite3_context*, int); +void sqlite3_result_int64(sqlite3_context*, int64_t); +void sqlite3_result_int(sqlite3_context*, int); +void sqlite3_result_double(sqlite3_context*, double); +void sqlite3_result_null(sqlite3_context*); +void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +void sqlite3_result_text16(sqlite3_context*, const char*, int, void(*)(void*)); +void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); +int sqlite3_complete(const char *sql); +int sqlite3_errcode(sqlite3 *db); +const char *sqlite3_libversion(void); +int sqlite3_open(char *, sqlite3 **ppDb); +typedef void (*ljsqlite3_cbstep)(sqlite3_context*,int,sqlite3_value**); +typedef void (*ljsqlite3_cbfinal)(sqlite3_context*); + +int sqlite3_create_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +int sqlite3_get_autocommit(sqlite3*); +int sqlite3_create_collation( + void*, + const char *, + int eTextRep, + void *pArg, + int(*)(void *, int, void*, int, void*) + ); +int sqlite3_process_handler(void *, int, int(*)(void *), void *); + +int sqlite3_set_authorizer( + sqlite3*, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pUserData +); + +int64_t sqlite3_last_insert_rowid(sqlite3*); +int sqlite3_bind_int64(sqlite3_stmt*, int, int64_t); +/* +typedef struct { + sqlite3* _ptr; + bool _closed; +} ljsqlite3_conn; + +typedef struct { + sqlite3_stmt* _ptr; + bool _closed; + sqlite3* _conn; + int32_t _code; +} ljsqlite3_stmt; + +*/ + +struct sqlite3_index_info { + /* Inputs */ + int nConstraint; /* Number of entries in aConstraint */ + struct sqlite3_index_constraint { + int iColumn; /* Column on left-hand side of constraint */ + unsigned char op; /* Constraint operator */ + unsigned char usable; /* True if this constraint is usable */ + int iTermOffset; /* Used internally - xBestIndex should ignore */ + } *aConstraint; /* Table of WHERE clause constraints */ + int nOrderBy; /* Number of terms in the ORDER BY clause */ + struct sqlite3_index_orderby { + int iColumn; /* Column number */ + unsigned char desc; /* True for DESC. False for ASC. */ + } *aOrderBy; /* The ORDER BY clause */ + /* Outputs */ + struct sqlite3_index_constraint_usage { + int argvIndex; /* if >0, constraint is part of argv to xFilter */ + unsigned char omit; /* Do not code a test for this constraint */ + } *aConstraintUsage; + int idxNum; /* Number used to identify the index */ + char *idxStr; /* String, possibly obtained from sqlite3_malloc */ + int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ + int orderByConsumed; /* True if output is already ordered */ + double estimatedCost; /* Estimated cost of using this index */ + /* Fields below are only available in SQLite 3.8.2 and later */ + long long estimatedRows; /* Estimated number of rows returned */ +}; + +typedef struct sqlite3_vtab sqlite3_vtab; +typedef struct sqlite3_index_info sqlite3_index_info; +typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; +typedef struct sqlite3_module sqlite3_module; +typedef long long int sqlite_int64; +typedef unsigned long long int sqlite_uint64; +typedef sqlite_int64 sqlite3_int64; +typedef sqlite_uint64 sqlite3_uint64; + +struct sqlite3_vtab { + const sqlite3_module *pModule; /* The module for this virtual table */ + int nRef; /* Used internally */ + char *zErrMsg; /* Error message from sqlite3_mprintf() */ + /* Virtual table implementations will typically add additional fields */ +}; +struct sqlite3_vtab_cursor { + sqlite3_vtab *pVtab; /* Virtual table of this cursor */ + /* Virtual table implementations will typically add additional fields */ +int n; +}; +struct sqlite3_module { + int iVersion; + int (*xCreate)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xConnect)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); + int (*xDisconnect)(sqlite3_vtab *pVTab); + int (*xDestroy)(sqlite3_vtab *pVTab); + int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); + int (*xClose)(sqlite3_vtab_cursor*); + int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, + int argc, sqlite3_value **argv); + int (*xNext)(sqlite3_vtab_cursor*); + int (*xEof)(sqlite3_vtab_cursor*); + int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); + int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); + int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); + int (*xBegin)(sqlite3_vtab *pVTab); + int (*xSync)(sqlite3_vtab *pVTab); + int (*xCommit)(sqlite3_vtab *pVTab); + int (*xRollback)(sqlite3_vtab *pVTab); + int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg); + int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); + /* The methods above are in version 1 of the sqlite_module object. Those + ** below are for version 2 and greater. */ + int (*xSavepoint)(sqlite3_vtab *pVTab, int); + int (*xRelease)(sqlite3_vtab *pVTab, int); + int (*xRollbackTo)(sqlite3_vtab *pVTab, int); +}; +int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable); +int sqlite3_create_module( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData /* Client data for xCreate/xConnect */ + ); + void *sqlite3_malloc(int); +void *sqlite3_realloc(void*, int); +void sqlite3_free(void*); +char *sqlite3_mprintf(const char*,...); +""" +) + +_sqresult_text = sqlite.sqlite3_result_text +_sqresult_text16 = sqlite.sqlite3_result_text16 +SQLITE_TRANSIENT = ffi.cast("const void *", -1) +SQLITE_STATIC = ffi.cast("const void *", 0) +FTS3_FULLSCAN_SEARCH = 0 +SQLITE_OK = 0 +SQLITE_ERROR = 1 +SQLITE_INTERNAL = 2 +SQLITE_PERM = 3 +SQLITE_ABORT = 4 +SQLITE_BUSY = 5 +SQLITE_LOCKED = 6 +SQLITE_NOMEM = 7 +SQLITE_READONLY = 8 +SQLITE_INTERRUPT = 9 +SQLITE_IOERR = 10 +SQLITE_CORRUPT = 11 +SQLITE_NOTFOUND = 12 +SQLITE_FULL = 13 +SQLITE_CANTOPEN = 14 +SQLITE_PROTOCOL = 15 +SQLITE_EMPTY = 16 +SQLITE_SCHEMA = 17 +SQLITE_TOOBIG = 18 +SQLITE_CONSTRAINT = 19 +SQLITE_MISMATCH = 20 +SQLITE_MISUSE = 21 +SQLITE_NOLFS = 22 +SQLITE_AUTH = 23 +SQLITE_FORMAT = 24 +SQLITE_RANGE = 25 +SQLITE_NOTADB = 26 +SQLITE_ROW = 100 +SQLITE_DONE = 101 +SQLITE_INTEGER = 1 +SQLITE_FLOAT = 2 +SQLITE_BLOB = 4 +SQLITE_NULL = 5 +SQLITE_TEXT = 3 +SQLITE3_TEXT = 3 + + +SQLITE_INDEX_CONSTRAINT_MATCH = 64 +SQLITE_INDEX_CONSTRAINT_EQ = 2 +SQLITE_INDEX_CONSTRAINT_GE = 32 +SQLITE_INDEX_CONSTRAINT_GT = 4, +SQLITE_INDEX_CONSTRAINT_LE = 8, +SQLITE_INDEX_CONSTRAINT_LT = 16, + +SQLITE_UTF8 = 1 + +SQLITE_DENY = 1 +SQLITE_IGNORE = 2 + +mapping_authorizer_function = {} +mapping_authorizer_function[1] = "SQLITE_CREATE_INDEX" +mapping_authorizer_function[2] = "SQLITE_CREATE_TABLE" +mapping_authorizer_function[3] = "SQLITE_CREATE_TEMP_INDEX" +mapping_authorizer_function[4] = "SQLITE_CREATE_TEMP_TABLE" +mapping_authorizer_function[5] = "SQLITE_CREATE_TEMP_TRIGGER" +mapping_authorizer_function[6] = "SQLITE_CREATE_TEMP_VIEW" +mapping_authorizer_function[7] = "SQLITE_CREATE_TRIGGER" +mapping_authorizer_function[8] = "SQLITE_CREATE_VIEW" +mapping_authorizer_function[9] = "SQLITE_DELETE" +mapping_authorizer_function[10] = "SQLITE_DROP_INDEX" +mapping_authorizer_function[11] = "SQLITE_DROP_TABLE" +mapping_authorizer_function[12] = "SQLITE_DROP_TEMP_INDEX" +mapping_authorizer_function[13] = "SQLITE_DROP_TEMP_TABLE" +mapping_authorizer_function[14] = "SQLITE_DROP_TEMP_TRIGGER" +mapping_authorizer_function[15] = "SQLITE_DROP_TEMP_VIEW" +mapping_authorizer_function[16] = "SQLITE_DROP_TRIGGER" +mapping_authorizer_function[17] = "SQLITE_DROP_VIEW" +mapping_authorizer_function[18] = "SQLITE_INSERT" +mapping_authorizer_function[19] = "SQLITE_PRAGMA" +mapping_authorizer_function[20] = "SQLITE_READ" +mapping_authorizer_function[21] = "SQLITE_SELECT" +mapping_authorizer_function[22] = "SQLITE_TRANSACTION" +mapping_authorizer_function[23] = "SQLITE_UPDATE" +mapping_authorizer_function[24] = "SQLITE_ATTACH" +mapping_authorizer_function[25] = "SQLITE_DETACH" +mapping_authorizer_function[26] = "SQLITE_ALTER_TABLE" +mapping_authorizer_function[27] = "SQLITE_REINDEX" +mapping_authorizer_function[28] = "SQLITE_ANALYZE" +mapping_authorizer_function[29] = "SQLITE_CREATE_VTABLE" +mapping_authorizer_function[30] = "SQLITE_DROP_VTABLE" +mapping_authorizer_function[31] = "SQLITE_FUNCTION" + + +SQLITE_CREATE_INDEX = 1 +SQLITE_CREATE_TABLE = 2 +SQLITE_CREATE_TEMP_INDEX = 3 +SQLITE_CREATE_TEMP_TABLE = 4 +SQLITE_CREATE_TEMP_TRIGGER = 5 +SQLITE_CREATE_TEMP_VIEW = 6 +SQLITE_CREATE_TRIGGER = 7 +SQLITE_CREATE_VIEW = 8 +SQLITE_DELETE = 9 +SQLITE_DROP_INDEX = 10 +SQLITE_DROP_TABLE = 11 +SQLITE_DROP_TEMP_INDEX = 12 +SQLITE_DROP_TEMP_TABLE = 13 +SQLITE_DROP_TEMP_TRIGGER = 14 +SQLITE_DROP_TEMP_VIEW = 15 +SQLITE_DROP_TRIGGER = 16 +SQLITE_DROP_VIEW = 17 +SQLITE_INSERT = 18 +SQLITE_PRAGMA = 19 +SQLITE_READ = 20 +SQLITE_SELECT = 21 +SQLITE_TRANSACTION = 22 +SQLITE_UPDATE = 23 +SQLITE_ATTACH = 24 +SQLITE_DETACH = 25 +SQLITE_ALTER_TABLE = 26 +SQLITE_REINDEX = 27 +SQLITE_ANALYZE = 28 +SQLITE_CREATE_VTABLE = 29 +SQLITE_DROP_VTABLE = 30 +SQLITE_FUNCTION = 31 + +# SQLite C API +HAS_LOAD_EXTENSION = hasattr(sqlite, "sqlite3_enable_load_extension") +if HAS_LOAD_EXTENSION: + ffi.cdef("""int sqlite3_enable_load_extension(sqlite3 *db, int onoff);""") + +########################################## +# END Wrapped SQLite C API and constants +########################################## + +# SQLite version information +sqlite_version = sqlite.sqlite3_libversion() + +_tcache = None +_tfun = None + +class ExecutionCompleteError(StandardError): + pass + +class Error(StandardError): + pass + +class SQLError(StandardError): + pass + #def __init__(self, exc): + # if not msg.startswith(type(exc)): + # self.message = type(exc)+str(exc) + # else: + # self.message = msg + #def __str__(self): + # return self.message + #def __unicode__(self): + # return self.message + +class Warning(StandardError): + pass + +class InterfaceError(Error): + pass + +class DatabaseError(Error): + pass + +class InternalError(DatabaseError): + pass + +class AbortError(DatabaseError): + pass + +class OperationalError(DatabaseError): + pass + +class ProgrammingError(DatabaseError): + pass + +class IntegrityError(DatabaseError): + pass + +class DataError(DatabaseError): + pass + +class NotSupportedError(DatabaseError): + pass + +class ConstraintError(DatabaseError): + pass + +def complete(*args): + return sqlite.sqlite3_complete(args[0].encode('utf-8')) + +def apswversion(): + return "MSPW ver 0.01" + +def sqlitelibversion(): + return ffi.string(sqlite.sqlite3_libversion()) + +def connect(database, **kwargs): + factory = kwargs.get("factory", Connection) + return factory(str(database), **kwargs) + +class StatementCache(object): + def __init__(self, connection, maxcount): + self.connection = connection + self.maxcount = maxcount + self.cache = OrderedDict() + + def get(self, sql): + try: + stat = self.cache[sql] + except KeyError: + stat = Statement(self.connection, sql) + self.cache[sql] = stat + if len(self.cache) > self.maxcount: + self.cache.popitem(0) + + if stat.in_use: + stat = Statement(self.connection, sql) + + return stat, stat.next_char + +class Connection(object): + def __init__(self, database, timeout=None, detect_types=0, isolation_level="", + check_same_thread=True, factory=None, cached_statements=100): + + db_p = ffi.new("sqlite3 **") + if sqlite.sqlite3_open(str(database), db_p) != SQLITE_OK: + raise SQLError("Could not open database") + + if database != '': + self.filename = os.path.abspath(database) + else: + self.filename = '' + + self._db = db_p[0] + sqlite.sqlite3_extended_result_codes(self._db, 1) + if timeout is not None: + timeout = int(timeout * 1000) # pysqlite2 uses timeout in seconds + sqlite.sqlite3_busy_timeout(self._db, timeout) + + self.closed = False + self.statements = [] + self.statement_counter = 0 + self._isolation_level = isolation_level + self.detect_types = detect_types + self.statement_cache = StatementCache(self, cached_statements) + self.cursors = [] + self.__func_cache = {} + self.authorizer = 0 + self.Error = Error + self.Warning = Warning + self.InterfaceError = InterfaceError + self.DatabaseError = DatabaseError + self.InternalError = InternalError + self.SQLError = SQLError + self.OperationalError = OperationalError + self.ProgrammingError = ProgrammingError + self.IntegrityError = IntegrityError + self.DataError = DataError + self.NotSupportedError = NotSupportedError + self.func_cache = {} + self._aggregates = {} + self._vtdatasource = {} + self._vtmodules = {} + self._vttables = {} + self._vtcursors = [] + self._vtcursorinstances = tuple() + self._vtcursorcolumn = [] + self._vtcursoreof = tuple() + self._vtcursortables = [] + self.aggregate_instances = {} + self._collations = {} + if check_same_thread: + self.__thread_ident = _thread_get_ident() + self.exectracefun = None + + def _check_closed(self): + if not self.__initialized: + raise ProgrammingError("Base Connection.__init__ not called.") + if not self._db: + raise ProgrammingError("Cannot operate on a closed database.") + + def _check_thread(self): + try: + if self.__thread_ident == _thread_get_ident(): + return + except AttributeError: + pass + else: + raise ProgrammingError( + "SQLite objects created in a thread can only be used in that " + "same thread. The object was created in thread id %d and this " + "is thread id %d", self.__thread_ident, _thread_get_ident()) + + def _check_thread_wrap(func): + @wraps(func) + def wrapper(self, *args, **kwargs): + self._check_thread() + return func(self, *args, **kwargs) + return wrapper + + def _check_closed_wrap(func): + @wraps(func) + def wrapper(self, *args, **kwargs): + self._check_closed() + return func(self, *args, **kwargs) + return wrapper + + def _get_exception(self, error_code=None): + if error_code is None: + error_code = sqlite.sqlite3_errcode(self._db) + error_message = ffi.string(sqlite.sqlite3_errmsg(self._db)) + + if error_code == SQLITE_OK: + raise ValueError("error signalled but got SQLITE_OK") + elif error_code in (SQLITE_INTERNAL, SQLITE_NOTFOUND): + exc = InternalError + elif error_code == SQLITE_NOMEM: + exc = MemoryError + elif error_code == SQLITE_INTERRUPT: + return KeyboardInterrupt + elif error_code in ( SQLITE_ERROR, SQLITE_PERM, SQLITE_ABORT, SQLITE_BUSY, SQLITE_LOCKED, + SQLITE_READONLY, SQLITE_IOERR, SQLITE_FULL, SQLITE_CANTOPEN, + SQLITE_PROTOCOL, SQLITE_EMPTY, SQLITE_SCHEMA): + exc = SQLError + elif error_code == SQLITE_CORRUPT: + exc = DatabaseError + elif error_code == SQLITE_TOOBIG: + exc = DataError + elif error_code in (SQLITE_CONSTRAINT, SQLITE_MISMATCH): + exc = IntegrityError + elif error_code == SQLITE_MISUSE: + exc = ProgrammingError + else: + exc = DatabaseError + #print exc + if "Error:" not in error_message: + error_message = exc.__name__ + ": " + error_message + + exc = exc(error_message) + exc.error_code = error_code + return exc + + def _remember_statement(self, statement): + self.statements.append(weakref.ref(statement)) + self.statement_counter += 1 + + if self.statement_counter % 100 == 0: + self.statements = [ref for ref in self.statements if ref() is not None] + + def _reset_cursors(self): + for cursor_ref in self.cursors: + cursor = cursor_ref() + if cursor: + cursor.reset = True + + def setexectrace(self, f): + self.exectracefun = f + + def cursor(self, factory=None): + if factory is None: + factory = Cursor + cur = factory(self) + return cur + + def executemany(self, *args): + cur = Cursor(self) + return cur.executemany(*args) + + def execute(self, *args): + cur = Cursor(self) + return cur.execute(*args) + + def executescript(self, *args): + cur = Cursor(self) + return cur.executescript(*args) + + def __call__(self, sql): + if not isinstance(sql, (str, unicode)): + raise Warning("SQL is of wrong type. Must be string or unicode.") + statement = self.statement_cache.get(sql) + return statement + + def _get_isolation_level(self): + return self._isolation_level + def _set_isolation_level(self, val): + if val is None: + self.commit() + if isinstance(val, unicode): + val = str(val) + self._isolation_level = val + isolation_level = property(_get_isolation_level, _set_isolation_level) + + def _begin(self): + if self._isolation_level is None: + return + if sqlite.sqlite3_get_autocommit(self._db): + + sql = "BEGIN " + self._isolation_level + statement_p = ffi.new("sqlite3_stmt **") + next_char = ffi.new("char *") + + ret = sqlite.sqlite3_prepare_v2(self._db, sql, -1, statement_p, next_char) + + statement = statement_p[0] + + if ret != SQLITE_OK: + raise self._get_exception(ret) + ret = sqlite.sqlite3_step(statement) + if ret != SQLITE_DONE: + raise self._get_exception(ret) + + sqlite.sqlite3_finalize(statement) + + def commit(self): + if sqlite.sqlite3_get_autocommit(self._db): + return + + for statement in self.statements: + obj = statement() + if obj is not None: + obj.reset() + try: + sql = "COMMIT" + statement_p = ffi.new("sqlite3_stmt **") + next_char = ffi.new("char *") + ret = sqlite.sqlite3_prepare_v2(self._db, sql, -1, statement_p, next_char) + statement = statement_p[0] + if ret != SQLITE_OK: + raise self._get_exception(ret) + ret = sqlite.sqlite3_step(statement) + if ret != SQLITE_DONE: + raise self._get_exception(ret) + finally: + sqlite.sqlite3_finalize(statement) + + def rollback(self): + if sqlite.sqlite3_get_autocommit(self._db): + return + + for statement in self.statements: + obj = statement() + if obj is not None: + obj.reset() + + try: + sql = "ROLLBACK" + statement_p = ffi.new("char **") + next_char = ffi.new("char *") + ret = sqlite.sqlite3_prepare_v2(self._db, sql, -1, statement_p, next_char) + statement = statement_p[0] + if ret != SQLITE_OK: + raise self._get_exception(ret) + ret = sqlite.sqlite3_step(statement) + if ret != SQLITE_DONE: + raise self._get_exception(ret) + finally: + sqlite.sqlite3_finalize(statement) + self._reset_cursors() + + def _check_closed(self): + return + if getattr(self, 'closed', True): + raise ProgrammingError("Cannot operate on a closed database.") + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, exc_tb): + if exc_type is None and exc_value is None and exc_tb is None: + self.commit() + else: + self.rollback() + + def _get_total_changes(self): + return sqlite.sqlite3_total_changes(self._db) + total_changes = property(_get_total_changes) + + def close(self): + if self.closed: + return + for statement in self.statements: + obj = statement() + if obj is not None: + obj.finalize() + + self.closed = True + ret = sqlite.sqlite3_close(self._db) + self._reset_cursors() + if ret != SQLITE_OK: + raise self._get_exception(ret) + + def create_collation(self, name, callback): + name = name.upper() + if not name.replace('_', '').isalnum(): + raise ProgrammingError("invalid character in collation name") + + if callback is None: + del self._collations[name] + c_collation_callback = cast(None, COLLATION) + else: + if not callable(callback): + raise TypeError("parameter must be callable") + + def collation_callback(context, len1, str1, len2, str2): + text1 = ffi.string(str1) + text2 = ffi.string(str2) + + return callback(text1, text2) + + c_collation_callback = COLLATION(collation_callback) + self._collations[name] = c_collation_callback + + ret = sqlite.sqlite3_create_collation(self._db, name, + SQLITE_UTF8, + None, + c_collation_callback) + if ret != SQLITE_OK: + raise self._get_exception(ret) + + def set_progress_handler(self, callable, nsteps): + if callable is None: + c_progress_handler = cast(None, PROGRESS) + else: + try: + c_progress_handler, _ = self.func_cache[callable] + except KeyError: + def progress_handler(userdata): + try: + ret = callable() + return bool(ret) + except Exception: + # abort query if error occurred + return 1 + c_progress_handler = PROGRESS(progress_handler) + + self.func_cache[callable] = c_progress_handler, progress_handler + ret = sqlite.sqlite3_progress_handler(self._db, nsteps, + c_progress_handler, + None) + if ret != SQLITE_OK: + raise self._get_exception(ret) + + @_check_thread_wrap + @_check_closed_wrap + def setauthorizer(self, callback): + if callback != None: + self.authorizer = callback + try: + authorizer = self.__func_cache[callback] + except KeyError: + @ffi.callback("int(void*, int, const char*, const char*, " + "const char*, const char*)") + def authorizer(userdata, action, arg1, arg2, dbname, source): + try: + arg1 = unicode(ffi.string(arg1)) + except: + arg1 = None + try: + arg2 = unicode(ffi.string(arg2)) + except: + arg2 = None + try: + dbname = unicode(ffi.string(dbname)) + except: + dbname = None + try: + source = unicode(ffi.string(source)) + except: + source = None + + try: + ret = callback(action, arg1, arg2, dbname, source) + assert isinstance(ret, int) + # try to detect cases in which cffi would swallow + # OverflowError when casting the return value + assert int(ffi.cast('int', ret)) == ret + return ret + except Exception: + return SQLITE_DENY + self.__func_cache[callback] = authorizer + ret = sqlite.sqlite3_set_authorizer(self._db, authorizer, ffi.NULL) + if callback == None: + ret = sqlite.sqlite3_set_authorizer(self._db, ffi.NULL, ffi.NULL) + if ret != SQLITE_OK: + raise self._get_exception(ret) + + def createscalarfunction(self, name, callback, num_args=-1): + try: + c_closure, _ = self.func_cache[callback] + except KeyError: + def closure(context, nargs, params): + # try: + # _python_to_sqlite(context, callback(*[self._sqlite_to_python_value[sqlite.sqlite3_value_type(params[ci])](params[ci]) for ci in xrange(nargs)])) + + # try: + # _python_to_sqlite(context, callback(*[_sqlite_to_python(params[ci]) for ci in xrange(nargs)])) + + if nargs == 0: + t = sqlite.sqlite3_value_type(params[0]) + if t == 1: + inparams = sqlite.sqlite3_value_int64(params[0]) + elif t == 2: + inparams = sqlite.sqlite3_value_double(params[0]) + elif t == 3: + inparams = utf_8_decode(ffi.string(sqlite.sqlite3_value_text(params[0])))[0] + elif t == 4: + inparams = buffer(ffi.buffer(sqlite.sqlite3_value_blob(params[0]), sqlite.sqlite3_value_bytes(params[0]))[:]) + else: + inparams = None + + try: + _python_to_sqlite(context, callback(inparams)) + except KeyboardInterrupt: + sqlite.sqlite3_result_error_code(context, SQLITE_INTERRUPT) + return + except Exception, e: + msg = "user-defined function raised exception: "+str(e) + sqlite.sqlite3_result_error(context, msg, len(msg)) + return + + inparams = newlist_hint(nargs) + ci = 0 + while ci < nargs: + # inparams.append(self._sqlite_to_python_value[sqlite.sqlite3_value_type(params[ci])](params[ci])) + # inparams.append(_sqlite_to_python(params[ci])) + t = sqlite.sqlite3_value_type(params[ci]) + if t == 1: + inparams.append(sqlite.sqlite3_value_int64(params[ci])) + elif t == 2: + inparams.append(sqlite.sqlite3_value_double(params[ci])) + elif t == 3: + inparams.append(utf_8_decode(ffi.string(sqlite.sqlite3_value_text(params[ci])))[0]) + elif t == 4: + inparams.append(buffer(ffi.buffer(sqlite.sqlite3_value_blob(params[ci]), sqlite.sqlite3_value_bytes(params[ci]))[:])) + else: + inparams.append(None) + ci += 1 + + try: + _python_to_sqlite(context, callback(*inparams)) + except KeyboardInterrupt: + sqlite.sqlite3_result_error_code(context, SQLITE_INTERRUPT) + return + except Exception, e: + msg = "user-defined function raised exception: "+str(e) + sqlite.sqlite3_result_error(context, msg, len(msg)) + + c_closure = ffi.callback("void(sqlite3_context*,int,sqlite3_value**)", closure) + self.func_cache[callback] = c_closure, closure + try: + ret = sqlite.sqlite3_create_function(self._db, name, num_args, + SQLITE_UTF8, ffi.NULL, + c_closure, + ffi.NULL, + ffi.NULL) + except KeyboardInterrupt : + msg = str('Keyboard Interrupt') + raise self.OperationalError(msg) + + if ret != SQLITE_OK: + raise self.OperationalError("Error creating function") + + + def createaggregatefunction(self, name, cls, num_args = -1): + try: + step_callback, final_callback = self._aggregates[cls] + except KeyError: + @ffi.callback("void(sqlite3_context*, int, sqlite3_value**)") + def step_callback(context, nargs, params): + aggregate_ptr = ffi.cast("size_t[1]", + sqlite.sqlite3_aggregate_context( + context, ffi.sizeof("size_t"))) + + if not aggregate_ptr[0]: + try: + aggregate, _, _ = cls() + except KeyboardInterrupt: + sqlite.sqlite3_result_error_code(context, SQLITE_INTERRUPT); + except Exception: + msg = ("user-defined aggregate's '__init__' " + "method raised error") + sqlite.sqlite3_result_error(context, msg, len(msg)) + return + aggregate_id = id(aggregate) + self.aggregate_instances[aggregate_id] = aggregate + aggregate_ptr[0] = aggregate_id + + if nargs == 1: + t = sqlite.sqlite3_value_type(params[0]) + if t == 1: + inparams = sqlite.sqlite3_value_int64(params[0]) + elif t == 2: + inparams = sqlite.sqlite3_value_double(params[0]) + elif t == 3: + inparams = utf_8_decode(ffi.string(sqlite.sqlite3_value_text(params[0])))[0] + elif t == 4: + inparams = buffer(ffi.buffer(sqlite.sqlite3_value_blob(params[0]), sqlite.sqlite3_value_bytes(params[0]))[:]) + else: + inparams = None + + try: + self.aggregate_instances[aggregate_ptr[0]].step(inparams) + except KeyboardInterrupt: + sqlite.sqlite3_result_error_code(context, SQLITE_INTERRUPT) + except Exception: + msg = ("user-defined aggregate's 'step' " + "method raised error") + sqlite.sqlite3_result_error(context, msg, len(msg)) + return + + inparams = newlist_hint(nargs) + ci = 0 + while ci < nargs: + # inparams.append(self._sqlite_to_python_value[sqlite.sqlite3_value_type(params[ci])](params[ci])) + # inparams.append(_sqlite_to_python(params[ci])) + t = sqlite.sqlite3_value_type(params[ci]) + if t == 1: + inparams.append(sqlite.sqlite3_value_int64(params[ci])) + elif t == 2: + inparams.append(sqlite.sqlite3_value_double(params[ci])) + elif t == 3: + inparams.append(utf_8_decode(ffi.string(sqlite.sqlite3_value_text(params[ci])))[0]) + elif t == 4: + inparams.append(buffer(ffi.buffer(sqlite.sqlite3_value_blob(params[ci]), sqlite.sqlite3_value_bytes(params[ci]))[:])) + else: + inparams.append(None) + ci += 1 + + try: + self.aggregate_instances[aggregate_ptr[0]].step(*inparams) + except KeyboardInterrupt: + sqlite.sqlite3_result_error_code(context, SQLITE_INTERRUPT) + except Exception: + msg = ("user-defined aggregate's 'step' " + "method raised error") + sqlite.sqlite3_result_error(context, msg, len(msg)) + + @ffi.callback("void(sqlite3_context*)") + def final_callback(context): + aggregate_ptr = ffi.cast("size_t[1]", + sqlite.sqlite3_aggregate_context( + context, ffi.sizeof("size_t"))) + + if aggregate_ptr[0]: + aggregate = self.aggregate_instances[aggregate_ptr[0]] + + try: + val = aggregate.final() + except KeyboardInterrupt: + sqlite.sqlite3_result_error_code(context, SQLITE_INTERRUPT); + except Exception: + msg = ("user-defined aggregate's 'finalize' " + "method raised error") + + sqlite.sqlite3_result_error(context, msg, len(msg)) + else: + try: + _python_to_sqlite(context, val) + except KeyboardInterrupt: + sqlite.sqlite3_result_error_code(context, SQLITE_INTERRUPT) + + finally: + del self.aggregate_instances[aggregate_ptr[0]] + + self._aggregates[cls] = (step_callback, final_callback) + + ret = sqlite.sqlite3_create_function(self._db, name, num_args, + SQLITE_UTF8, ffi.NULL, + ffi.NULL, + step_callback, + final_callback) + if ret != SQLITE_OK: + raise self._get_exception(ret) + + def createmodule(self, name, datasource): + self._vtdatasource[datasource] = datasource + + # Represents a table + try: + vtmodule = self._vtmodules[name](0) + except KeyError: + closure = lambda x:x + closure.lastrow = None + closure.lastcursorid = None + + def xCreate(db, paux, argc, argv, ppvtab, pzErr): #int (*xCreate)(sqlite3*, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char**); + try: + schema, table = datasource.Create(self, ffi.string(argv[0]), ffi.string(argv[1]), ffi.string(argv[2]), *tuple([ffi.string(argv[i]) for i in xrange(3,argc)])) + except Exception as e: + error_msg = str(e) + if "Error:" not in error_msg: + error_msg = type(e).__name__ +": " + error_msg + pzErr[0] = sqlite.sqlite3_mprintf(error_msg) + return SQLITE_ERROR + + newvtab = ffi.new("sqlite3_vtab *") + ppvtab[0] = newvtab + self._vttables[newvtab] = table + vret = sqlite.sqlite3_declare_vtab(db, schema.encode('utf-8')) + if ret != SQLITE_OK: + pzErr[0] = sqlite.sqlite3_mprintf(str(self._get_exception(vret))) + return SQLITE_ERROR + return SQLITE_OK + xConnect = xCreate + + def xBestIndex(pvtab, pInfo): #int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); + orderby = [] + constraints = [] + + for i in xrange(pInfo.nOrderBy): + orderby.append((pInfo.aOrderBy[i].iColumn, pInfo.aOrderBy[i].desc)) + + for ci in xrange(pInfo.nConstraint): + if pInfo.aConstraint[ci].usable: + constraints.append((pInfo.aConstraint[ci].iColumn, pInfo.aConstraint[ci].op)) + constraints, idxNum, idxStr, orderByConsumed, estimatedCost=self._vttables[pvtab].BestIndex(tuple(constraints), tuple(orderby)) + + pInfo.idxNum = idxNum + pInfo.orderByConsumed = orderByConsumed + pInfo.estimatedCost = estimatedCost + + if idxStr: + pInfo.idxStr = sqlite.sqlite3_mprintf(idxStr.encode('utf-8')) + pInfo.needToFreeIdxStr = 1 + + if constraints: + pci = 0 + for ci in xrange(pInfo.nConstraint): + if pInfo.aConstraint[ci].usable: + c = constraints[pci] + if c: + if type(c) in (list, tuple): + pInfo.aConstraintUsage[ci].argvIndex = c[0] + 1 + pInfo.aConstraintUsage[ci].omit = c[1] + else: + pInfo.aConstraintUsage[ci].argvIndex = c + 1 + pci += 1 + + return SQLITE_OK + + def xDisconnect(pvtab): #int (*xDisconnect)(sqlite3_vtab *pVTab); + if hasattr(self._vttables[pvtab], 'xDisconnect'): + self._vttables[pvtab].xDisconnect() + __delVT__(pvtab) + return SQLITE_OK + + + def xDestroy(pvtab): #int (*xDisconnect)(sqlite3_vtab *pVTab); + self._vttables[pvtab].Destroy() + __delVT__(pvtab) + return SQLITE_OK + + def __delVT__(pvtab): + del self._vttables[pvtab] + try: + for i in self._vtcursortables: + if self._vtcursortables == pvtab: + xCloseID(i) + except KeyboardInterrupt: + return SQLITE_INTERRUPT + except: + pass + return SQLITE_OK + + + def xOpen(pvtab, ppcursor): # int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); + newcursor = ffi.new("sqlite3_vtab_cursor *") + instance = self._vttables[pvtab].Open() + length = len(self._vtcursors) + + try: + newcursor.n = self._vtcursors.index(None) + except: + newcursor.n = length + i = newcursor.n + + if i == length: + self._vtcursors.append(newcursor) + self._vtcursorinstances += tuple([instance]) + self._vtcursorcolumn.append(instance.Column) + self._vtcursoreof += tuple([instance.Eof]) + self._vtcursortables.append(pvtab) + else: + self._vtcursors[i] = newcursor + + tmp = list(self._vtcursorinstances) + tmp[i] = instance + self._vtcursorinstances = tuple(tmp) + + tmp = list(self._vtcursoreof) + tmp[i] = instance.Eof + self._vtcursoreof = tuple(tmp) + + self._vtcursorcolumn[i] = instance.Column + self._vtcursortables[i] = pvtab + + ppcursor[0] = newcursor + return SQLITE_OK + + def xClose(vtabcursor): # int (*xClose)(sqlite3_vtab_cursor*); + try: + self._vtcursors[vtabcursor.n] = None + self._vtcursorcolumn[vtabcursor.n] = None + tmp = list(self._vtcursoreof) + tmp[vtabcursor.n] = None + self._vtcursoreof = tuple(tmp) + self._vtcursorinstances[vtabcursor.n].Close() + tmp = list(self._vtcursorinstances) + tmp[vtabcursor.n] = None + self._vtcursorinstances = tuple(tmp) + self._vtcursortables[vtabcursor.n] = None + except: + pass + + return SQLITE_OK + + def xCloseID(n): + # try: + self._vtcursors[n] = None + self._vtcursorcolumn[n] = None + tmp = list(self._vtcursoreof) + tmp[n] = None + self._vtcursoreof = tuple(tmp) + self._vtcursorinstances[n].Close() + tmp = list(self._vtcursorinstances) + tmp[n] = None + self._vtcursorinstances = tuple(tmp) + self._vtcursortables[n] = None + # except: + # pass + + return SQLITE_OK + + def xFilter(vtabcursor, idxnum, cidxstr, argc, argv) : # int (*xFilter)(sqlite3_vta788b_cursor*, int idxNum, const char *idxStr, int argc, sqlite3_value **argv); + try: + if cidxstr == ffi.NULL: + idxstr = None + else: + idxstr = ffi.string(cidxstr) + constraints = newlist_hint(argc) + ci = 0 + while ci < argc: + t = sqlite.sqlite3_value_type(argv[ci]) + if t == 1: + constraints.append(sqlite.sqlite3_value_int64(argv[ci])) + elif t == 2: + constraints.append(sqlite.sqlite3_value_double(argv[ci])) + elif t == 3: + constraints.append(utf_8_decode(ffi.string(sqlite.sqlite3_value_text(argv[ci])))[0]) + elif t == 4: + constraints.append(buffer(ffi.buffer(sqlite.sqlite3_value_blob(argv[ci]), sqlite.sqlite3_value_bytes(argv[ci]))[:])) + else: + constraints.append(None) + ci += 1 + self._vtcursorinstances[vtabcursor.n].Filter(idxnum, idxstr, tuple(constraints)) + except KeyboardInterrupt, e: + self._vttables[vtabcursor.pVtab].Disconnect() + return SQLITE_INTERRUPT + except Exception, e: + vtabcursor.pVtab.zErrMsg = sqlite.sqlite3_mprintf(unicode(e).encode('utf-8')) + return SQLITE_ERROR + + return 0 #return SQLITE_OK + + def xNext(vtabcursor): #int (*xNext)(sqlite3_vtab_cursor*) + #print 'xNext' + #print vtabcursor.n + try: + self._vtcursorinstances[vtabcursor.n].Next() + return SQLITE_OK + except KeyboardInterrupt: + return SQLITE_INTERRUPT + + def xEof(vtabcursor): #int (*xEof)(sqlite3_vtab_cursor*); + try: + # return self._vtcursoreof[vtabcursor.n]() + return self._vtcursorinstances[vtabcursor.n].eof + except KeyboardInterrupt: + return SQLITE_INTERRUPT + except: + return 1 + + def xNextFast(vtabcursor): + try: + self._vtcursorinstances[vtabcursor.n].Next() + except KeyboardInterrupt: + return SQLITE_INTERRUPT + return 0 #return SQLITE_OK + + def xColumnFast(vtabcursor, context, col): + _python_to_sqlitedict[type(self._vtcursorinstances[vtabcursor.n].row[col])](context, self._vtcursorinstances[vtabcursor.n].row[col]) + return 0 + # val = self._vtcursorinstances[vtabcursor.n].row[col] + + # cl = type(_val) + # if cl is unicode: + # sqlite.sqlite3_result_text(context, _val.encode('utf-8'), -1, SQLITE_TRANSIENT) + # else: + # _python_to_sqlitedict[cl](context, _val) + # return 0 + + # cl = type(val) + # if cl is unicode: + # sqlite.sqlite3_result_text(context, val.encode('utf-8'), -1, SQLITE_TRANSIENT) + # elif cl is int: + # sqlite.sqlite3_result_int64(context, val) + # elif cl is float: + # sqlite.sqlite3_result_double(context, val) + # elif cl is str: + # sqlite.sqlite3_result_text(context, val, -1, SQLITE_TRANSIENT) + # elif cl is bool: + # sqlite.sqlite3_result_int(context, val) + # elif cl is long: + # sqlite.sqlite3_result_text(context, str(val), -1, SQLITE_TRANSIENT) + # elif cl is NoneType: + # sqlite.sqlite3_result_null(context) + # elif cl is buffer: + # sqlite.sqlite3_result_blob(context, str(val), len(val), SQLITE_TRANSIENT) + # return 0 #return SQLITE_OK + + def xColumn(vtabcursor, context, col): # int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); + _python_to_sqlite(context, self._vtcursorcolumn[vtabcursor.n](col)) + return SQLITE_OK + + def xRowid(vtabcursor, pRowid): # int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); + pRowid[0] = ffi.cast('sqlite3_int64', self._vtcursorinstances[vtabcursor.n].Rowid()) + + def xUpdate(pvtab, val, num) : #int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); + return SQLITE_OK + + def xCommit(pvtab): #int (*xCommit)(sqlite3_vtab *pVTab); + return SQLITE_OK + + def xSync(pvtab): #int (*xCommit)(sqlite3_vtab *pVTab); + return SQLITE_OK + + def xBegin(pvtab): #int (*xCommit)(sqlite3_vtab *pVTab); + return SQLITE_OK + + def xRollback(pvtab): # int (*xRollback)(sqlite3_vtab *pVTab); + print 17 + + def xRename(pvtab, znew): # int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); + print 18 + + def xSavepoint(pvtab, num): # int (*xSavepoint)(sqlite3_vtab *pVTab, int); + print 19 + + def xRelease(pvtab , num): # int (*xRelease)(sqlite3_vtab *pVTab, int); + print 20 + return SQLITE_OK + + def xRollbackTo(pvtab , num): # int (*xRollbackTo)(sqlite3_vtab *pVTab, int); + print 21 + + vtmodule = ffi.new("sqlite3_module *") + + xCreateCallback = ffi.callback("int(sqlite3*, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char**)", xCreate) + xConnectCallback = ffi.callback("int(sqlite3*, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char**)", xConnect) + xBestIndexCallback = ffi.callback("int(sqlite3_vtab *pVTab, sqlite3_index_info*)", xBestIndex) + xDestroyCallback = ffi.callback("int(sqlite3_vtab *pVTab)", xDestroy) + xDisconnectCallback = ffi.callback("int(sqlite3_vtab *pVTab)", xDisconnect) + xOpenCallback = ffi.callback("int(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursfactoryor)", xOpen) + xCloseCallback = ffi.callback("int(sqlite3_vtab_cursor*)", xClose) + xFilterCallback = ffi.callback("int(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, int argc, sqlite3_value **argv)", xFilter, SQLITE_ERROR) + xEofCallback = ffi.callback("int(sqlite3_vtab_cursor*)", xEof) + xRowidCallback = ffi.callback("int(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid)", xRowid) + xUpdateCallback = ffi.callback("int(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *)", xUpdate) + xBeginCallback = ffi.NULL #ffi.callback("int(sqlite3_vtab *pVTab)", xBegin) + xSyncCallback = ffi.NULL # ffi.callback("int(sqlite3_vtab *pVTab)", xSync) + xCommitCallback = ffi.NULL #ffi.callback("int(sqlite3_vtab *pVTab)", xCommit) + xRollbackCallback = ffi.callback("int(sqlite3_vtab *pVTab)", xRollback) + xRenameCallback = ffi.callback("int(sqlite3_vtab *pVtab, const char *zNew)", xRename) + xSavepointCallback = ffi.callback("int(sqlite3_vtab *pVTab, int)", xSavepoint) + xReleaseCallback = ffi.callback("int(sqlite3_vtab *pVTab, int)", xRelease) + xRollbackToCallback = ffi.callback("int(sqlite3_vtab *pVTab, int)", xRollbackTo) + xFindFunctionCallback = ffi.NULL + + if '_madisVT' in datasource.__dict__ and datasource._madisVT == True : + xNextCallback = ffi.callback("int(sqlite3_vtab_cursor*)", xNextFast) + xColumnCallback = ffi.callback("int(sqlite3_vtab_cursor*, sqlite3_context*, int)", xColumnFast) + else: + xNextCallback = ffi.callback("int(sqlite3_vtab_cursor*)", xNext) + xColumnCallback = ffi.callback("int(sqlite3_vtab_cursor*, sqlite3_context*, int)", xColumn) + + vtmodule.xCreate = xCreateCallback + vtmodule.xConnect = xConnectCallback + vtmodule.xBestIndex = xBestIndexCallback + vtmodule.xDisconnect = xDisconnectCallback + vtmodule.xDestroy = xDestroyCallback + vtmodule.xOpen = xOpenCallback + vtmodule.xClose = xCloseCallback + vtmodule.xFilter = xFilterCallback + vtmodule.xNext = xNextCallback + vtmodule.xEof = xEofCallback + vtmodule.xColumn = xColumnCallback + vtmodule.xRowid = xRowidCallback + vtmodule.xUpdate = xUpdateCallback + vtmodule.xBegin = xBeginCallback + vtmodule.xSync = xSyncCallback + vtmodule.xCommit = xCommitCallback + vtmodule.xRollback = xRollbackCallback + vtmodule.xRename = xRenameCallback + vtmodule.xSavepoint = xSavepointCallback + vtmodule.xRelease = xReleaseCallback + vtmodule.xRollbackTo = xRollbackToCallback + vtmodule.xFindFunction = xFindFunctionCallback + + self._vtmodules[datasource] = \ + (vtmodule, xCreate, xConnect, xBestIndex, xDisconnect, xDestroy, xOpen, + xClose, xFilter, xNext, xEof, xColumn, xRowid, xUpdate, xBegin, xSync, xCommit, xRollback, xRename, + xSavepoint, xRelease, xRollbackTo, xCreateCallback, xConnectCallback, xBestIndexCallback, + xDestroyCallback, xDisconnectCallback, xOpenCallback, xCloseCallback, xFilterCallback, xNextCallback, + xEofCallback, xColumnCallback, xRowidCallback, xUpdateCallback, xBeginCallback, xSyncCallback, + xCommitCallback, xRollbackCallback, xRenameCallback, xSavepointCallback, xReleaseCallback, + xRollbackToCallback, xFindFunctionCallback, xNextFast, xColumnFast + ) + +# int sqlite3_create_module_v2( +# sqlite3 *db, /* SQLite connection to register module with */ +# const char *zName, /* Name of the module */ +# const sqlite3_module *p, /* Methods for the module */ +# void *pClientData, /* Client data for xCreate/xConnect */ +# void(*xDestroy)(void*) /* Module destructor function */ +# ); + + ret = sqlite.sqlite3_create_module(self._db, name , vtmodule ,ffi.NULL) + if ret != SQLITE_OK: + raise self._get_exception(ret) + + + def iterdump(self): + from sqlite3.dump import _iterdump + return _iterdump(self) + + #if HAS_LOAD_EXTENSION: + def enableloadextension(self, enabled): + return + rc = sqlite.sqlite3_enable_load_extension(self._db, int(enabled)) + + if rc != SQLITE_OK: + raise OperationalError("Error enabling load extension") + +DML, DQL, DDL = range(3) + + +class CursorLock(object): + def __init__(self, cursor): + self.cursor = cursor + + def __enter__(self): + if self.cursor.locked: + raise ProgrammingError("Recursive use of cursors not allowed.") + self.cursor.locked = True + + def __exit__(self, *args): + self.cursor.locked = False + + +class Cursor(object): + def __init__(self, con): + if not isinstance(con, Connection): + raise TypeError + con._check_closed() + con.cursors.append(weakref.ref(self)) + self.connection = con + self._description = None + self.arraysize = 1 + self.rowcount = -1 + self.statement = None + self.reset = False + self.locked = False + self.next_char = None + self.params = None + self.column_count = 0 + self.connection = con + self._description = None + self.exhausted = False + self.iter = None + self.next = self.__iter__().next + + def setexectrace(self, f): + self.connection.exectracefun = f + + def _check_closed(self): + if not getattr(self, 'connection', None): + raise ProgrammingError("Cannot operate on a closed cursor.") + self.connection._check_closed() + + def _check_and_lock(self): + return CursorLock(self) + + def execute(self, sql, params=None): + self.params = params + if self.locked: + raise ProgrammingError("Recursive use of cursors not allowed.") + self.locked = True + self._description = None + self.reset = False + + try: + self.statement, self.next_char = self.connection.statement_cache.get(sql) + except: + raise + + try: + self.exhausted = True + while True: + if self.connection.exectracefun: + if self.connection.exectracefun(self, self.statement, params) == 0: + return + self.statement.set_params(params) + stst = self.statement.statement + + # Actually execute the SQL statement + ret = sqlite.sqlite3_step(stst) + + if ret != SQLITE_DONE: + break + + if self.next_char == '': + self.locked = False + return self + + self.statement, self.next_char = self.connection.statement_cache.get(self.next_char) + if self.statement is None: + self.locked = False + + if ret == SQLITE_ROW: + self.exhausted = False + self.locked = False + self.column_count = sqlite.sqlite3_column_count(stst) + return self + + self.statement.reset() + self.reset = True + raise self.connection._get_exception(ret) + except: + self.locked = False + raise + + if self.exhausted: + self.locked = False + + return self + + def __iter__(self): + while not self.exhausted: + ret = SQLITE_ROW + stst = self.statement.statement + self.column_count = sqlite.sqlite3_column_count(stst) + scount = self.column_count + 0 + row = [None] * scount + l_sqlite_to_python_statement = tuple([ + None, + sqlite.sqlite3_column_int64, + sqlite.sqlite3_column_double, + lambda st, c: utf_8_decode(ffi.string(sqlite.sqlite3_column_text(st, c)))[0], + lambda st, c: buffer(ffi.buffer(sqlite.sqlite3_column_blob(st, c), sqlite.sqlite3_column_bytes(st, c))[:]), + lambda st, c: None + ]) + + while ret == 100: #SQLITE_ROW: + ci = 0 + while ci < scount: + row[ci] = l_sqlite_to_python_statement[sqlite.sqlite3_column_type(stst, ci)](stst, ci) + ci += 1 + + ret = sqlite.sqlite3_step(stst) + yield tuple(row) + + if ret == SQLITE_DONE: + if self.next_char != '': + self.statement, self.next_char = self.connection.statement_cache.get(self.next_char) + if self.statement is None: + self.locked = False + raise StopIteration + while True: + self.statement.set_params(self.params) + + # Actually execute the SQL statement + ret = sqlite.sqlite3_step(self.statement.statement) + + if ret != SQLITE_DONE: + break + + if self.next_char == '': + self.locked = False + raise StopIteration + + self.statement, self.next_char = self.connection.statement_cache.get(self.next_char) + if self.statement is None: + self.locked = False + else: + self.exhausted = True + else: + exc = self.connection._get_exception(ret) + self.statement.reset() + raise exc + + self.locked = False + raise StopIteration + + def prepare(self, sql): + if type(sql) is unicode: + sql = sql.encode("utf-8") + self._description = None + self.reset = False + + try: + stat = Statement(self.connection, sql) + except: + raise + + return stat + + def executedirect(self, st, params=None): + i1 = 1 + for p in params: + cl = type(p) + if cl is unicode: + sqlite.sqlite3_bind_text(st.statement, i1, p.encode('utf-8'), -1, SQLITE_TRANSIENT) + elif cl is int: + sqlite.sqlite3_bind_int64(st.statement, i1, p) + elif cl is float: + sqlite.sqlite3_bind_double(st.statement, i1, p) + elif cl is str: + sqlite.sqlite3_bind_text(st.statement, i1, p, -1, SQLITE_TRANSIENT) + elif cl is NoneType: + sqlite.sqlite3_bind_null(st.statement, i1) + elif cl is bool: + sqlite.sqlite3_bind_int(st.statement, i1, p) + elif cl is long: + sqlite.sqlite3_bind_text(st.statement, i1, str(p), -1, SQLITE_TRANSIENT) + elif cl is buffer: + sqlite.sqlite3_bind_blob(st.statement, i1, str(p), len(p), SQLITE_TRANSIENT) + i1 += 1 + + # Actually execute the SQL statement + sqlite.sqlite3_step(st.statement) + sqlite.sqlite3_reset(st.statement) + + def executemany(self, sql, many_params): + if type(sql) is unicode: + sql = sql.encode("utf-8") + + with self._check_and_lock(): + self._description = None + self.reset = False + self.statement, next = self.connection.statement_cache.get(sql) + + if self.statement.kind == DQL: + self.connection._begin() + else: + raise ProgrammingError("executemany is only for DML statements") + + st = self.statement.statement + sqlite_transient = ffi.cast("const void *", -1) + for params in many_params: + sqlite.sqlite3_reset(st) + i1 = 1 + for p in params: + cl = type(p) + if cl is unicode: + sqlite.sqlite3_bind_text(st, i1, p.encode('utf-8'), -1, sqlite_transient) + elif cl is int: + sqlite.sqlite3_bind_int64(st, i1, p) + elif cl is float: + sqlite.sqlite3_bind_double(st, i1, p) + elif cl is NoneType: + sqlite.sqlite3_bind_null(st, i1) + elif cl is bool: + sqlite.sqlite3_bind_int(st, i1, p) + elif cl is long: + sqlite.sqlite3_bind_text(st, i1, str(p), -1, sqlite_transient) + elif cl is str: + sqlite.sqlite3_bind_text(st, i1, p, -1, sqlite_transient) + elif cl is buffer: + sqlite.sqlite3_bind_blob(st, i1, str(p), len(p), sqlite_transient) + i1 += 1 + + # Actually execute the SQL statement + ret = sqlite.sqlite3_step(st) + if ret != SQLITE_DONE: + raise self.connection._get_exception(ret) + + return self + + def executesplit(self, sql): + if type(sql) is unicode: + sql = sql.encode("utf-8") + + with self._check_and_lock(): + self._description = None + self.reset = False + self.statement, next = self.connection.statement_cache.get(sql) + + if self.statement.kind == DQL: + self.connection._begin() + else: + raise ProgrammingError("executemany is only for DML statements") + + st = self.statement.statement + sqlite_transient = ffi.cast("const void *", -1) + params = yield() + plen = len(params) + while True: + sqlite.sqlite3_reset(st) + i1 = 1 + while i1 < plen: + p = params[i1] + cl = type(p) + if cl is unicode: + sqlite.sqlite3_bind_text(st, i1, p.encode('utf-8'), -1, sqlite_transient) + elif cl is int: + sqlite.sqlite3_bind_int64(st, i1, p) + elif cl is float: + sqlite.sqlite3_bind_double(st, i1, p) + elif cl is NoneType: + sqlite.sqlite3_bind_null(st, i1) + elif cl is bool: + sqlite.sqlite3_bind_int(st, i1, p) + elif cl is long: + sqlite.sqlite3_bind_text(st, i1, str(p), -1, sqlite_transient) + elif cl is str: + sqlite.sqlite3_bind_text(st, i1, p, -1, sqlite_transient) + elif cl is buffer: + sqlite.sqlite3_bind_blob(st, i1, str(p), len(p), sqlite_transient) + i1 += 1 + ret = sqlite.sqlite3_step(st) + params = yield() + # Actually execute the SQL statement + if ret != SQLITE_DONE: + raise self.connection._get_exception(ret) + + + def executescript(self, sql): + self._description = None + self.reset = False + if type(sql) is unicode: + sql = sql.encode("utf-8") + + statement = None + statement_p = ffi.new("sqlite3_stmt **", statement) + + c_sql = ffi.new("char[]", sql) + + c_sql_p = ffi.new("char**", c_sql) + + self.connection.commit() + while True: + rc = sqlite.sqlite3_prepare(self.connection._db, c_sql, -1, statement_p, c_sql_p) + + c_sql = c_sql_p[0] + statement = statement_p[0] + if rc != SQLITE_OK: + raise self.connection._get_exception(rc) + + rc = SQLITE_ROW + while rc == SQLITE_ROW: + if not statement: + rc = SQLITE_OK + else: + rc = sqlite.sqlite3_step(statement) + + if rc != SQLITE_DONE: + sqlite.sqlite3_finalize(statement) + if rc == SQLITE_OK: + return self + else : + raise self.connection._get_exception(rc) + rc = sqlite.sqlite3_finalize(statement) + if rc != SQLITE_OK: + raise self.connection._get_exception(rc) + + if not c_sql: + break + return self + + def _check_reset(self): + if self.reset: + raise self.connection.InterfaceError("Cursor needed to be reset because " + "of commit/rollback and can " + "no longer be fetched from.") + + # do all statements + def fetchone(self): + if self.statement is None: + return None + + try: + return self.next() + except StopIteration: + return None + + def fetchmany(self, size=None): + if self.statement is None: + return [] + if size is None: + size = self.arraysize + lst = [] + for row in self: + lst.append(row) + if len(lst) == size: + break + return lst + + def fetchall(self): + if self.statement is None: + return [] + return list(self) + + def _getdescription(self): + if self._description is None: + self._description = self.statement._get_description() + return self._description + + def _getlastrowid(self): + return sqlite.sqlite3_last_insert_rowid(self.connection._db) + + def close(self, *args): + if not self.connection: + return + + if self.statement: + self.statement.reset() + self.statement = None + self.connection.cursors.remove(weakref.ref(self)) + self.connection = None + + def setinputsizes(self, *args): + pass + def setoutputsize(self, *args): + pass + + description = property(_getdescription) + getdescription = _getdescription + lastrowid = property(_getlastrowid) + +class Statement(object): + def __init__(self, connection, sql): + self.statement = None + self.column_count = None + + if type(sql) is unicode: + sql = sql.encode("utf-8") + if not isinstance(sql, str): + raise ValueError("sql must be a string") + + self.con = connection + self.sql = sql # DEBUG ONLY + self.kind = DQL + self.exhausted = False + self.in_use = False + self.statement_p = ffi.new("sqlite3_stmt **", self.statement) + self.next_char = ffi.new("char[]", "") + mynext_char = ffi.new("char**", self.next_char) + sql_char = ffi.new("char[]", sql) + + try: + ret = sqlite.sqlite3_prepare_v2(self.con._db, sql_char, -1, self.statement_p, mynext_char) + + except Exception, e: + raise SQLError(e) + + self.next_char = ffi.string(mynext_char[0]) + self.statement = self.statement_p[0] + + if ret == SQLITE_OK and self.statement is None: + + # an empty statement, we work around that, as it's the least trouble + try: + ret = sqlite.sqlite3_prepare_v2(self.con._db, "select 42", -1, self.statement_p, self.next_char) + except: + + raise + + self.kind = DQL + + if ret != SQLITE_OK: + raise self.con._get_exception(ret) + + self.con._remember_statement(self) + + def set_params(self, params): + ret = sqlite.sqlite3_reset(self.statement) + + if ret != SQLITE_OK: + raise self.con._get_exception(ret) + self.mark_dirty() + + if params is None: + if sqlite.sqlite3_bind_parameter_count(self.statement) != 0: + raise ProgrammingError("wrong number of arguments") + return + + if type(params) is not dict: + if len(params) != sqlite.sqlite3_bind_parameter_count(self.statement): + raise ProgrammingError("wrong number of arguments") + + for ci in xrange(len(params)): + _bind_param[type(params[ci])](self.statement, ci+1, params[ci]) + else: + for idx in xrange(1, sqlite.sqlite3_bind_parameter_count(self.statement) + 1): + param_name = sqlite.sqlite3_bind_parameter_name(self.statement, idx) + if param_name is None: + raise ProgrammingError("need named parameters") + param_name = param_name[1:] + try: + param = params[param_name] + except KeyError: + raise ProgrammingError("missing parameter '%s'" % param) + _bind_param[type(param)](self.statement, idx, param) + + def reset(self): + self.row_cast_map = None + ret = sqlite.sqlite3_reset(self.statement) + self.in_use = False + self.exhausted = False + return ret + + def finalize(self): + sqlite.sqlite3_finalize(self.statement) + self.statement = None + self.in_use = False + + def mark_dirty(self): + self.in_use = True + + def __del__(self): + if self.statement != None : + sqlite.sqlite3_finalize(self.statement) + self.statement = None + + def _get_description(self): + if self.kind == DML: + return () + desc = [] + for ci in xrange(sqlite.sqlite3_column_count(self.statement)): + name = ffi.string(sqlite.sqlite3_column_name(self.statement, ci)).split("[")[0].strip() + desc.append((name, None)) + return desc + +def _sqlite_to_python(val): + t = sqlite.sqlite3_value_type(val) + if t < 2: + if t == 1: + return sqlite.sqlite3_value_int64(val) + else: + return sqlite.sqlite3_value_double(val) + else: + if t == 3: + return utf_8_decode(ffi.string(sqlite.sqlite3_value_text(val)))[0] + else: + if t == 4: + return buffer(ffi.buffer(sqlite.sqlite3_value_blob(val), sqlite.sqlite3_value_bytes(val))[:]) + else: + return None + +def _python_to_sqlite(context, val): + cl = type(val) + if cl is unicode: + sqlite.sqlite3_result_text(context, val.encode('utf-8'), -1, SQLITE_TRANSIENT) + elif cl is int: + sqlite.sqlite3_result_int64(context, val) + elif cl is str: + sqlite.sqlite3_result_text(context, val, -1, SQLITE_TRANSIENT) + elif cl is float: + sqlite.sqlite3_result_double(context, val) + elif cl is bool: + sqlite.sqlite3_result_int(context, val) + elif cl is long: + sqlite.sqlite3_result_text(context, str(val), len(val), SQLITE_TRANSIENT) + elif val is None: + sqlite.sqlite3_result_null(context) + elif cl is buffer: + sqlite.sqlite3_result_blob(context, str(val), len(val), SQLITE_TRANSIENT) + +_sqlite_to_python_value = tuple([ + None, + sqlite.sqlite3_value_int64, + sqlite.sqlite3_value_double, + lambda x: ffi.string(sqlite.sqlite3_value_text(x)).decode('utf-8'), + lambda x: buffer(ffi.buffer(sqlite.sqlite3_value_blob(x), sqlite.sqlite3_value_bytes(x))[:]), + lambda x: None +]) + +_bind_param = { + unicode: lambda st, idx, param: sqlite.sqlite3_bind_text(st, idx, param.encode('utf-8'), -1, SQLITE_TRANSIENT), + int: sqlite.sqlite3_bind_int64, + float: sqlite.sqlite3_bind_double, + str: lambda st, idx, param: sqlite.sqlite3_bind_text(st, idx, param, len(param), SQLITE_TRANSIENT), + long: lambda st, idx, param: sqlite.sqlite3_bind_text(st, idx, str(param), len(str(param)), SQLITE_TRANSIENT), + type(None): lambda st, idx, param: sqlite.sqlite3_bind_null(st, idx), + bool: sqlite.sqlite3_bind_int, + buffer: lambda st, idx, param: sqlite.sqlite3_bind_blob(st, idx, str(param), len(param), SQLITE_TRANSIENT) +} + +_sqlite_to_python_statement = tuple([ + None, + lambda st, ci: sqlite.sqlite3_column_int64(st, ci), + lambda st, ci: sqlite.sqlite3_column_double(st, ci), + lambda st, ci: unicode(ffi.string(sqlite.sqlite3_column_text(st, ci))), + lambda st, ci: buffer(ffi.buffer(sqlite.sqlite3_column_blob( + st, ci), sqlite.sqlite3_column_bytes(st, ci))[:]), + lambda st, ci: None +]) + +_python_to_sqlitedict = { + unicode: lambda c, val: sqlite.sqlite3_result_text(c, val.encode('utf-8'), -1, SQLITE_TRANSIENT), + int: sqlite.sqlite3_result_int64, + float: sqlite.sqlite3_result_double, + str: lambda c, val: sqlite.sqlite3_result_text(c, val, -1, SQLITE_TRANSIENT), + long: lambda c, val: sqlite.sqlite3_result_text(c, str(val), -1, SQLITE_TRANSIENT), + NoneType: lambda c, val: sqlite.sqlite3_result_null(c), + bool: sqlite.sqlite3_result_int, + buffer: lambda c, val: sqlite.sqlite3_result_blob(c, str(val), len(val), SQLITE_TRANSIENT) +} \ No newline at end of file diff --git a/interactive-mining-3rdparty-madis/madis/src/pypylib/msgpack/COPYING b/interactive-mining-3rdparty-madis/madis/src/pypylib/msgpack/COPYING new file mode 100644 index 0000000..f067af3 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/pypylib/msgpack/COPYING @@ -0,0 +1,14 @@ +Copyright (C) 2008-2011 INADA Naoki + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/interactive-mining-3rdparty-madis/madis/src/pypylib/msgpack/__init__.py b/interactive-mining-3rdparty-madis/madis/src/pypylib/msgpack/__init__.py new file mode 100644 index 0000000..6c5ae53 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/pypylib/msgpack/__init__.py @@ -0,0 +1,54 @@ +# coding: utf-8 +from msgpack._version import version +from msgpack.exceptions import * + +from collections import namedtuple + + +class ExtType(namedtuple('ExtType', 'code data')): + """ExtType represents ext type in msgpack.""" + def __new__(cls, code, data): + if not isinstance(code, int): + raise TypeError("code must be int") + if not isinstance(data, bytes): + raise TypeError("data must be bytes") + if not 0 <= code <= 127: + raise ValueError("code must be 0~127") + return super(ExtType, cls).__new__(cls, code, data) + + +import os +if os.environ.get('MSGPACK_PUREPYTHON'): + from msgpack.fallback import Packer, unpack, unpackb, Unpacker +else: + try: + from msgpack._packer import Packer + from msgpack._unpacker import unpack, unpackb, Unpacker + except ImportError: + from msgpack.fallback import Packer, unpack, unpackb, Unpacker + + +def pack(o, stream, **kwargs): + """ + Pack object `o` and write it to `stream` + + See :class:`Packer` for options. + """ + packer = Packer(**kwargs) + stream.write(packer.pack(o)) + + +def packb(o, **kwargs): + """ + Pack object `o` and return packed bytes + + See :class:`Packer` for options. + """ + return Packer(**kwargs).pack(o) + +# alias for compatibility to simplejson/marshal/pickle. +load = unpack +loads = unpackb + +dump = pack +dumps = packb diff --git a/interactive-mining-3rdparty-madis/madis/src/pypylib/msgpack/_version.py b/interactive-mining-3rdparty-madis/madis/src/pypylib/msgpack/_version.py new file mode 100644 index 0000000..dddfe49 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/pypylib/msgpack/_version.py @@ -0,0 +1 @@ +version = (0, 4, 2) diff --git a/interactive-mining-3rdparty-madis/madis/src/pypylib/msgpack/exceptions.py b/interactive-mining-3rdparty-madis/madis/src/pypylib/msgpack/exceptions.py new file mode 100644 index 0000000..f7678f1 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/pypylib/msgpack/exceptions.py @@ -0,0 +1,29 @@ +class UnpackException(Exception): + pass + + +class BufferFull(UnpackException): + pass + + +class OutOfData(UnpackException): + pass + + +class UnpackValueError(UnpackException, ValueError): + pass + + +class ExtraData(ValueError): + def __init__(self, unpacked, extra): + self.unpacked = unpacked + self.extra = extra + + def __str__(self): + return "unpack(b) received extra data." + +class PackException(Exception): + pass + +class PackValueError(PackException, ValueError): + pass diff --git a/interactive-mining-3rdparty-madis/madis/src/pypylib/msgpack/fallback.py b/interactive-mining-3rdparty-madis/madis/src/pypylib/msgpack/fallback.py new file mode 100644 index 0000000..8ab3ad2 --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/pypylib/msgpack/fallback.py @@ -0,0 +1,748 @@ +"""Fallback pure Python implementation of msgpack""" + +import sys +import array +import struct + +if sys.version_info[0] == 3: + PY3 = True + int_types = int + Unicode = str + xrange = range + def dict_iteritems(d): + return d.items() +else: + PY3 = False + int_types = (int, long) + Unicode = unicode + def dict_iteritems(d): + return d.iteritems() + + +if hasattr(sys, 'pypy_version_info'): + # cStringIO is slow on PyPy, StringIO is faster. However: PyPy's own + # StringBuilder is fastest. + from __pypy__ import newlist_hint + from __pypy__.builders import StringBuilder + USING_STRINGBUILDER = True + class StringIO(object): + def __init__(self, s=b''): + if s: + self.builder = StringBuilder(len(s)) + self.builder.append(s) + else: + self.builder = StringBuilder() + def write(self, s): + self.builder.append(s) + def getvalue(self): + return self.builder.build() +else: + USING_STRINGBUILDER = False + from io import BytesIO as StringIO + newlist_hint = lambda size: [] + +from msgpack.exceptions import ( + BufferFull, + OutOfData, + UnpackValueError, + PackValueError, + ExtraData) + +from msgpack import ExtType + + +EX_SKIP = 0 +EX_CONSTRUCT = 1 +EX_READ_ARRAY_HEADER = 2 +EX_READ_MAP_HEADER = 3 + +TYPE_IMMEDIATE = 0 +TYPE_ARRAY = 1 +TYPE_MAP = 2 +TYPE_RAW = 3 +TYPE_BIN = 4 +TYPE_EXT = 5 + +DEFAULT_RECURSE_LIMIT = 511 + + +def unpack(stream, **kwargs): + """ + Unpack an object from `stream`. + + Raises `ExtraData` when `packed` contains extra bytes. + See :class:`Unpacker` for options. + """ + unpacker = Unpacker(stream, **kwargs) + ret = unpacker._fb_unpack() + if unpacker._fb_got_extradata(): + raise ExtraData(ret, unpacker._fb_get_extradata()) + return ret + + +def unpackb(packed, **kwargs): + """ + Unpack an object from `packed`. + + Raises `ExtraData` when `packed` contains extra bytes. + See :class:`Unpacker` for options. + """ + unpacker = Unpacker(None, **kwargs) + unpacker.feed(packed) + try: + ret = unpacker._fb_unpack() + except OutOfData: + raise UnpackValueError("Data is not enough.") + if unpacker._fb_got_extradata(): + raise ExtraData(ret, unpacker._fb_get_extradata()) + return ret + + +class Unpacker(object): + """ + Streaming unpacker. + + `file_like` is a file-like object having a `.read(n)` method. + When `Unpacker` is initialized with a `file_like`, `.feed()` is not + usable. + + `read_size` is used for `file_like.read(read_size)`. + + If `use_list` is True (default), msgpack lists are deserialized to Python + lists. Otherwise they are deserialized to tuples. + + `object_hook` is the same as in simplejson. If it is not None, it should + be callable and Unpacker calls it with a dict argument after deserializing + a map. + + `object_pairs_hook` is the same as in simplejson. If it is not None, it + should be callable and Unpacker calls it with a list of key-value pairs + after deserializing a map. + + `ext_hook` is callback for ext (User defined) type. It called with two + arguments: (code, bytes). default: `msgpack.ExtType` + + `encoding` is the encoding used for decoding msgpack bytes. If it is + None (default), msgpack bytes are deserialized to Python bytes. + + `unicode_errors` is used for decoding bytes. + + `max_buffer_size` limits the buffer size. 0 means INT_MAX (default). + + Raises `BufferFull` exception when it is unsufficient. + + You should set this parameter when unpacking data from an untrustred source. + + example of streaming deserialization from file-like object:: + + unpacker = Unpacker(file_like) + for o in unpacker: + do_something(o) + + example of streaming deserialization from socket:: + + unpacker = Unpacker() + while 1: + buf = sock.recv(1024*2) + if not buf: + break + unpacker.feed(buf) + for o in unpacker: + do_something(o) + """ + + def __init__(self, file_like=None, read_size=0, use_list=True, + object_hook=None, object_pairs_hook=None, list_hook=None, + encoding=None, unicode_errors='strict', max_buffer_size=0, + ext_hook=ExtType): + if file_like is None: + self._fb_feeding = True + else: + if not callable(file_like.read): + raise TypeError("`file_like.read` must be callable") + self.file_like = file_like + self._fb_feeding = False + self._fb_buffers = [] + self._fb_buf_o = 0 + self._fb_buf_i = 0 + self._fb_buf_n = 0 + # When Unpacker is used as an iterable, between the calls to next(), + # the buffer is not "consumed" completely, for efficiency sake. + # Instead, it is done sloppily. To make sure we raise BufferFull at + # the correct moments, we have to keep track of how sloppy we were. + self._fb_sloppiness = 0 + self._max_buffer_size = max_buffer_size or 2**31-1 + if read_size > self._max_buffer_size: + raise ValueError("read_size must be smaller than max_buffer_size") + self._read_size = read_size or min(self._max_buffer_size, 4096) + self._encoding = encoding + self._unicode_errors = unicode_errors + self._use_list = use_list + self._list_hook = list_hook + self._object_hook = object_hook + self._object_pairs_hook = object_pairs_hook + self._ext_hook = ext_hook + + if list_hook is not None and not callable(list_hook): + raise TypeError('`list_hook` is not callable') + if object_hook is not None and not callable(object_hook): + raise TypeError('`object_hook` is not callable') + if object_pairs_hook is not None and not callable(object_pairs_hook): + raise TypeError('`object_pairs_hook` is not callable') + if object_hook is not None and object_pairs_hook is not None: + raise TypeError("object_pairs_hook and object_hook are mutually " + "exclusive") + if not callable(ext_hook): + raise TypeError("`ext_hook` is not callable") + + def feed(self, next_bytes): + if isinstance(next_bytes, array.array): + next_bytes = next_bytes.tostring() + elif isinstance(next_bytes, bytearray): + next_bytes = bytes(next_bytes) + assert self._fb_feeding + if (self._fb_buf_n + len(next_bytes) - self._fb_sloppiness + > self._max_buffer_size): + raise BufferFull + self._fb_buf_n += len(next_bytes) + self._fb_buffers.append(next_bytes) + + def _fb_sloppy_consume(self): + """ Gets rid of some of the used parts of the buffer. """ + if self._fb_buf_i: + for i in xrange(self._fb_buf_i): + self._fb_buf_n -= len(self._fb_buffers[i]) + self._fb_buffers = self._fb_buffers[self._fb_buf_i:] + self._fb_buf_i = 0 + if self._fb_buffers: + self._fb_sloppiness = self._fb_buf_o + else: + self._fb_sloppiness = 0 + + def _fb_consume(self): + """ Gets rid of the used parts of the buffer. """ + if self._fb_buf_i: + for i in xrange(self._fb_buf_i): + self._fb_buf_n -= len(self._fb_buffers[i]) + self._fb_buffers = self._fb_buffers[self._fb_buf_i:] + self._fb_buf_i = 0 + if self._fb_buffers: + self._fb_buffers[0] = self._fb_buffers[0][self._fb_buf_o:] + self._fb_buf_n -= self._fb_buf_o + else: + self._fb_buf_n = 0 + self._fb_buf_o = 0 + self._fb_sloppiness = 0 + + def _fb_got_extradata(self): + if self._fb_buf_i != len(self._fb_buffers): + return True + if self._fb_feeding: + return False + if not self.file_like: + return False + if self.file_like.read(1): + return True + return False + + def __iter__(self): + return self + + def read_bytes(self, n): + return self._fb_read(n) + + def _fb_rollback(self): + self._fb_buf_i = 0 + self._fb_buf_o = 0 + + def _fb_get_extradata(self): + bufs = self._fb_buffers[self._fb_buf_i:] + if bufs: + bufs[0] = bufs[0][self._fb_buf_o:] + return b''.join(bufs) + + def _fb_read(self, n, write_bytes=None): + buffs = self._fb_buffers + # We have a redundant codepath for the most common case, such that + # pypy optimizes it properly. This is the case that the read fits + # in the current buffer. + if (write_bytes is None and self._fb_buf_i < len(buffs) and + self._fb_buf_o + n < len(buffs[self._fb_buf_i])): + self._fb_buf_o += n + return buffs[self._fb_buf_i][self._fb_buf_o - n:self._fb_buf_o] + + # The remaining cases. + ret = b'' + while len(ret) != n: + sliced = n - len(ret) + if self._fb_buf_i == len(buffs): + if self._fb_feeding: + break + to_read = sliced + if self._read_size > to_read: + to_read = self._read_size + tmp = self.file_like.read(to_read) + if not tmp: + break + buffs.append(tmp) + self._fb_buf_n += len(tmp) + continue + ret += buffs[self._fb_buf_i][self._fb_buf_o:self._fb_buf_o + sliced] + self._fb_buf_o += sliced + if self._fb_buf_o >= len(buffs[self._fb_buf_i]): + self._fb_buf_o = 0 + self._fb_buf_i += 1 + if len(ret) != n: + self._fb_rollback() + raise OutOfData + if write_bytes is not None: + write_bytes(ret) + return ret + + def _read_header(self, execute=EX_CONSTRUCT, write_bytes=None): + typ = TYPE_IMMEDIATE + n = 0 + obj = None + c = self._fb_read(1, write_bytes) + b = ord(c) + if b & 0b10000000 == 0: + obj = b + elif b & 0b11100000 == 0b11100000: + obj = struct.unpack("b", c)[0] + elif b & 0b11100000 == 0b10100000: + n = b & 0b00011111 + obj = self._fb_read(n, write_bytes) + typ = TYPE_RAW + elif b & 0b11110000 == 0b10010000: + n = b & 0b00001111 + typ = TYPE_ARRAY + elif b & 0b11110000 == 0b10000000: + n = b & 0b00001111 + typ = TYPE_MAP + elif b == 0xc0: + obj = None + elif b == 0xc2: + obj = False + elif b == 0xc3: + obj = True + elif b == 0xc4: + typ = TYPE_BIN + n = struct.unpack("B", self._fb_read(1, write_bytes))[0] + obj = self._fb_read(n, write_bytes) + elif b == 0xc5: + typ = TYPE_BIN + n = struct.unpack(">H", self._fb_read(2, write_bytes))[0] + obj = self._fb_read(n, write_bytes) + elif b == 0xc6: + typ = TYPE_BIN + n = struct.unpack(">I", self._fb_read(4, write_bytes))[0] + obj = self._fb_read(n, write_bytes) + elif b == 0xc7: # ext 8 + typ = TYPE_EXT + L, n = struct.unpack('Bb', self._fb_read(2, write_bytes)) + obj = self._fb_read(L, write_bytes) + elif b == 0xc8: # ext 16 + typ = TYPE_EXT + L, n = struct.unpack('>Hb', self._fb_read(3, write_bytes)) + obj = self._fb_read(L, write_bytes) + elif b == 0xc9: # ext 32 + typ = TYPE_EXT + L, n = struct.unpack('>Ib', self._fb_read(5, write_bytes)) + obj = self._fb_read(L, write_bytes) + elif b == 0xca: + obj = struct.unpack(">f", self._fb_read(4, write_bytes))[0] + elif b == 0xcb: + obj = struct.unpack(">d", self._fb_read(8, write_bytes))[0] + elif b == 0xcc: + obj = struct.unpack("B", self._fb_read(1, write_bytes))[0] + elif b == 0xcd: + obj = struct.unpack(">H", self._fb_read(2, write_bytes))[0] + elif b == 0xce: + obj = struct.unpack(">I", self._fb_read(4, write_bytes))[0] + elif b == 0xcf: + obj = struct.unpack(">Q", self._fb_read(8, write_bytes))[0] + elif b == 0xd0: + obj = struct.unpack("b", self._fb_read(1, write_bytes))[0] + elif b == 0xd1: + obj = struct.unpack(">h", self._fb_read(2, write_bytes))[0] + elif b == 0xd2: + obj = struct.unpack(">i", self._fb_read(4, write_bytes))[0] + elif b == 0xd3: + obj = struct.unpack(">q", self._fb_read(8, write_bytes))[0] + elif b == 0xd4: # fixext 1 + typ = TYPE_EXT + n, obj = struct.unpack('b1s', self._fb_read(2, write_bytes)) + elif b == 0xd5: # fixext 2 + typ = TYPE_EXT + n, obj = struct.unpack('b2s', self._fb_read(3, write_bytes)) + elif b == 0xd6: # fixext 4 + typ = TYPE_EXT + n, obj = struct.unpack('b4s', self._fb_read(5, write_bytes)) + elif b == 0xd7: # fixext 8 + typ = TYPE_EXT + n, obj = struct.unpack('b8s', self._fb_read(9, write_bytes)) + elif b == 0xd8: # fixext 16 + typ = TYPE_EXT + n, obj = struct.unpack('b16s', self._fb_read(17, write_bytes)) + elif b == 0xd9: + typ = TYPE_RAW + n = struct.unpack("B", self._fb_read(1, write_bytes))[0] + obj = self._fb_read(n, write_bytes) + elif b == 0xda: + typ = TYPE_RAW + n = struct.unpack(">H", self._fb_read(2, write_bytes))[0] + obj = self._fb_read(n, write_bytes) + elif b == 0xdb: + typ = TYPE_RAW + n = struct.unpack(">I", self._fb_read(4, write_bytes))[0] + obj = self._fb_read(n, write_bytes) + elif b == 0xdc: + n = struct.unpack(">H", self._fb_read(2, write_bytes))[0] + typ = TYPE_ARRAY + elif b == 0xdd: + n = struct.unpack(">I", self._fb_read(4, write_bytes))[0] + typ = TYPE_ARRAY + elif b == 0xde: + n = struct.unpack(">H", self._fb_read(2, write_bytes))[0] + typ = TYPE_MAP + elif b == 0xdf: + n = struct.unpack(">I", self._fb_read(4, write_bytes))[0] + typ = TYPE_MAP + else: + raise UnpackValueError("Unknown header: 0x%x" % b) + return typ, n, obj + + def _fb_unpack(self, execute=EX_CONSTRUCT, write_bytes=None): + typ, n, obj = self._read_header(execute, write_bytes) + + if execute == EX_READ_ARRAY_HEADER: + if typ != TYPE_ARRAY: + raise UnpackValueError("Expected array") + return n + if execute == EX_READ_MAP_HEADER: + if typ != TYPE_MAP: + raise UnpackValueError("Expected map") + return n + # TODO should we eliminate the recursion? + if typ == TYPE_ARRAY: + if execute == EX_SKIP: + for i in xrange(n): + # TODO check whether we need to call `list_hook` + self._fb_unpack(EX_SKIP, write_bytes) + return + ret = newlist_hint(n) + for i in xrange(n): + ret.append(self._fb_unpack(EX_CONSTRUCT, write_bytes)) + if self._list_hook is not None: + ret = self._list_hook(ret) + # TODO is the interaction between `list_hook` and `use_list` ok? + return ret if self._use_list else tuple(ret) + if typ == TYPE_MAP: + if execute == EX_SKIP: + for i in xrange(n): + # TODO check whether we need to call hooks + self._fb_unpack(EX_SKIP, write_bytes) + self._fb_unpack(EX_SKIP, write_bytes) + return + if self._object_pairs_hook is not None: + ret = self._object_pairs_hook( + (self._fb_unpack(EX_CONSTRUCT, write_bytes), + self._fb_unpack(EX_CONSTRUCT, write_bytes)) + for _ in xrange(n)) + else: + ret = {} + for _ in xrange(n): + key = self._fb_unpack(EX_CONSTRUCT, write_bytes) + ret[key] = self._fb_unpack(EX_CONSTRUCT, write_bytes) + if self._object_hook is not None: + ret = self._object_hook(ret) + return ret + if execute == EX_SKIP: + return + if typ == TYPE_RAW: + if self._encoding is not None: + obj = obj.decode(self._encoding, self._unicode_errors) + return obj + if typ == TYPE_EXT: + return self._ext_hook(n, obj) + if typ == TYPE_BIN: + return obj + assert typ == TYPE_IMMEDIATE + return obj + + def next(self): + try: + ret = self._fb_unpack(EX_CONSTRUCT, None) + self._fb_sloppy_consume() + return ret + except OutOfData: + self._fb_consume() + raise StopIteration + __next__ = next + + def skip(self, write_bytes=None): + self._fb_unpack(EX_SKIP, write_bytes) + self._fb_consume() + + def unpack(self, write_bytes=None): + ret = self._fb_unpack(EX_CONSTRUCT, write_bytes) + self._fb_consume() + return ret + + def read_array_header(self, write_bytes=None): + ret = self._fb_unpack(EX_READ_ARRAY_HEADER, write_bytes) + self._fb_consume() + return ret + + def read_map_header(self, write_bytes=None): + ret = self._fb_unpack(EX_READ_MAP_HEADER, write_bytes) + self._fb_consume() + return ret + + +class Packer(object): + """ + MessagePack Packer + + usage: + + packer = Packer() + astream.write(packer.pack(a)) + astream.write(packer.pack(b)) + + Packer's constructor has some keyword arguments: + + :param callable default: + Convert user type to builtin type that Packer supports. + See also simplejson's document. + :param str encoding: + Convert unicode to bytes with this encoding. (default: 'utf-8') + :param str unicode_errors: + Error handler for encoding unicode. (default: 'strict') + :param bool use_single_float: + Use single precision float type for float. (default: False) + :param bool autoreset: + Reset buffer after each pack and return it's content as `bytes`. (default: True). + If set this to false, use `bytes()` to get content and `.reset()` to clear buffer. + :param bool use_bin_type: + Use bin type introduced in msgpack spec 2.0 for bytes. + It also enable str8 type for unicode. + """ + def __init__(self, default=None, encoding='utf-8', unicode_errors='strict', + use_single_float=False, autoreset=True, use_bin_type=False): + self._use_float = use_single_float + self._autoreset = autoreset + self._use_bin_type = use_bin_type + self._encoding = encoding + self._unicode_errors = unicode_errors + self._buffer = StringIO() + if default is not None: + if not callable(default): + raise TypeError("default must be callable") + self._default = default + + def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, isinstance=isinstance): + default_used = False + while True: + if nest_limit < 0: + raise PackValueError("recursion limit exceeded") + if obj is None: + return self._buffer.write(b"\xc0") + if isinstance(obj, bool): + if obj: + return self._buffer.write(b"\xc3") + return self._buffer.write(b"\xc2") + if isinstance(obj, int_types): + if 0 <= obj < 0x80: + return self._buffer.write(struct.pack("B", obj)) + if -0x20 <= obj < 0: + return self._buffer.write(struct.pack("b", obj)) + if 0x80 <= obj <= 0xff: + return self._buffer.write(struct.pack("BB", 0xcc, obj)) + if -0x80 <= obj < 0: + return self._buffer.write(struct.pack(">Bb", 0xd0, obj)) + if 0xff < obj <= 0xffff: + return self._buffer.write(struct.pack(">BH", 0xcd, obj)) + if -0x8000 <= obj < -0x80: + return self._buffer.write(struct.pack(">Bh", 0xd1, obj)) + if 0xffff < obj <= 0xffffffff: + return self._buffer.write(struct.pack(">BI", 0xce, obj)) + if -0x80000000 <= obj < -0x8000: + return self._buffer.write(struct.pack(">Bi", 0xd2, obj)) + if 0xffffffff < obj <= 0xffffffffffffffff: + return self._buffer.write(struct.pack(">BQ", 0xcf, obj)) + if -0x8000000000000000 <= obj < -0x80000000: + return self._buffer.write(struct.pack(">Bq", 0xd3, obj)) + raise PackValueError("Integer value out of range") + if self._use_bin_type and isinstance(obj, bytes): + n = len(obj) + if n <= 0xff: + self._buffer.write(struct.pack('>BB', 0xc4, n)) + elif n <= 0xffff: + self._buffer.write(struct.pack(">BH", 0xc5, n)) + elif n <= 0xffffffff: + self._buffer.write(struct.pack(">BI", 0xc6, n)) + else: + raise PackValueError("Bytes is too large") + return self._buffer.write(obj) + if isinstance(obj, (Unicode, bytes)): + if isinstance(obj, Unicode): + if self._encoding is None: + raise TypeError( + "Can't encode unicode string: " + "no encoding is specified") + obj = obj.encode(self._encoding, self._unicode_errors) + n = len(obj) + if n <= 0x1f: + self._buffer.write(struct.pack('B', 0xa0 + n)) + elif self._use_bin_type and n <= 0xff: + self._buffer.write(struct.pack('>BB', 0xd9, n)) + elif n <= 0xffff: + self._buffer.write(struct.pack(">BH", 0xda, n)) + elif n <= 0xffffffff: + self._buffer.write(struct.pack(">BI", 0xdb, n)) + else: + raise PackValueError("String is too large") + return self._buffer.write(obj) + if isinstance(obj, float): + if self._use_float: + return self._buffer.write(struct.pack(">Bf", 0xca, obj)) + return self._buffer.write(struct.pack(">Bd", 0xcb, obj)) + if isinstance(obj, ExtType): + code = obj.code + data = obj.data + assert isinstance(code, int) + assert isinstance(data, bytes) + L = len(data) + if L == 1: + self._buffer.write(b'\xd4') + elif L == 2: + self._buffer.write(b'\xd5') + elif L == 4: + self._buffer.write(b'\xd6') + elif L == 8: + self._buffer.write(b'\xd7') + elif L == 16: + self._buffer.write(b'\xd8') + elif L <= 0xff: + self._buffer.write(struct.pack(">BB", 0xc7, L)) + elif L <= 0xffff: + self._buffer.write(struct.pack(">BH", 0xc8, L)) + else: + self._buffer.write(struct.pack(">BI", 0xc9, L)) + self._buffer.write(struct.pack("b", code)) + self._buffer.write(data) + return + if isinstance(obj, (list, tuple)): + n = len(obj) + self._fb_pack_array_header(n) + for i in xrange(n): + self._pack(obj[i], nest_limit - 1) + return + if isinstance(obj, dict): + return self._fb_pack_map_pairs(len(obj), dict_iteritems(obj), + nest_limit - 1) + if not default_used and self._default is not None: + obj = self._default(obj) + default_used = 1 + continue + raise TypeError("Cannot serialize %r" % obj) + + def pack(self, obj): + self._pack(obj) + ret = self._buffer.getvalue() + if self._autoreset: + self._buffer = StringIO() + elif USING_STRINGBUILDER: + self._buffer = StringIO(ret) + return ret + + def pack_map_pairs(self, pairs): + self._fb_pack_map_pairs(len(pairs), pairs) + ret = self._buffer.getvalue() + if self._autoreset: + self._buffer = StringIO() + elif USING_STRINGBUILDER: + self._buffer = StringIO(ret) + return ret + + def pack_array_header(self, n): + if n >= 2**32: + raise ValueError + self._fb_pack_array_header(n) + ret = self._buffer.getvalue() + if self._autoreset: + self._buffer = StringIO() + elif USING_STRINGBUILDER: + self._buffer = StringIO(ret) + return ret + + def pack_map_header(self, n): + if n >= 2**32: + raise ValueError + self._fb_pack_map_header(n) + ret = self._buffer.getvalue() + if self._autoreset: + self._buffer = StringIO() + elif USING_STRINGBUILDER: + self._buffer = StringIO(ret) + return ret + + def pack_ext_type(self, typecode, data): + if not isinstance(typecode, int): + raise TypeError("typecode must have int type.") + if not 0 <= typecode <= 127: + raise ValueError("typecode should be 0-127") + if not isinstance(data, bytes): + raise TypeError("data must have bytes type") + L = len(data) + if L > 0xffffffff: + raise ValueError("Too large data") + if L == 1: + self._buffer.write(b'\xd4') + elif L == 2: + self._buffer.write(b'\xd5') + elif L == 4: + self._buffer.write(b'\xd6') + elif L == 8: + self._buffer.write(b'\xd7') + elif L == 16: + self._buffer.write(b'\xd8') + elif L <= 0xff: + self._buffer.write(b'\xc7' + struct.pack('B', L)) + elif L <= 0xffff: + self._buffer.write(b'\xc8' + struct.pack('>H', L)) + else: + self._buffer.write(b'\xc9' + struct.pack('>I', L)) + self._buffer.write(struct.pack('B', typecode)) + self._buffer.write(data) + + def _fb_pack_array_header(self, n): + if n <= 0x0f: + return self._buffer.write(struct.pack('B', 0x90 + n)) + if n <= 0xffff: + return self._buffer.write(struct.pack(">BH", 0xdc, n)) + if n <= 0xffffffff: + return self._buffer.write(struct.pack(">BI", 0xdd, n)) + raise PackValueError("Array is too large") + + def _fb_pack_map_header(self, n): + if n <= 0x0f: + return self._buffer.write(struct.pack('B', 0x80 + n)) + if n <= 0xffff: + return self._buffer.write(struct.pack(">BH", 0xde, n)) + if n <= 0xffffffff: + return self._buffer.write(struct.pack(">BI", 0xdf, n)) + raise PackValueError("Dict is too large") + + def _fb_pack_map_pairs(self, n, pairs, nest_limit=DEFAULT_RECURSE_LIMIT): + self._fb_pack_map_header(n) + for (k, v) in pairs: + self._pack(k, nest_limit - 1) + self._pack(v, nest_limit - 1) + + def bytes(self): + return self._buffer.getvalue() + + def reset(self): + self._buffer = StringIO() diff --git a/interactive-mining-3rdparty-madis/madis/src/pypylib/readme.txt b/interactive-mining-3rdparty-madis/madis/src/pypylib/readme.txt new file mode 100644 index 0000000..4089eea --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/pypylib/readme.txt @@ -0,0 +1 @@ +This directory contains "library" functions for PyPy diff --git a/interactive-mining-3rdparty-madis/madis/src/tests/readme.txt b/interactive-mining-3rdparty-madis/madis/src/tests/readme.txt new file mode 100644 index 0000000..354a23e --- /dev/null +++ b/interactive-mining-3rdparty-madis/madis/src/tests/readme.txt @@ -0,0 +1,2 @@ +This directory is for putting test files that are not needed to be versioned. Everything +here will be ignored by mercurial. \ No newline at end of file diff --git a/interactive-mining-madoap/madoap/.gitignore b/interactive-mining-madoap/madoap/.gitignore new file mode 100644 index 0000000..a9b0fc4 --- /dev/null +++ b/interactive-mining-madoap/madoap/.gitignore @@ -0,0 +1,25 @@ +^nbproject/.*$ +^.idea/.*$ +^src/docs/build/_static/.*$ +^/src/docs/build/_static/.*$ +^src/docs/build/_sources/.*$ +^/src/docs/build/_sources/.*$ +^src/docs/html/(?!readme.txt$).*$ +^/src/docs/html/(?!readme.txt$).*$ +^src/docs/build/.*$ +^/src/docs/build/.*$ +^src/docs/source/row\.txt$ +^/src/docs/source/row\.txt$ +^src/docs/source/aggregate\.txt$ +^/src/docs/source/aggregate\.txt$ +^src/docs/source/vtable\.txt$ +^/src/docs/source/vtable\.txt$ + +# use glob syntax. +syntax: glob +*.pyc +*.db3 +project.properties +project.xml +private.xml +private.properties diff --git a/interactive-mining-madoap/madoap/src/README b/interactive-mining-madoap/madoap/src/README new file mode 100644 index 0000000..f5e66ef --- /dev/null +++ b/interactive-mining-madoap/madoap/src/README @@ -0,0 +1,9 @@ +First edit settings.py to set the web server port and the paths of madis and DB. + +To start the stats server use: + +python madserver.py + +You'll find a service script (put it into /etc/init.d), for starting and stopping +the stats server. The script maps port 80->8080 (comment the iptables rules out if you don't +want the mapping), and starts the service without giving it root credentials. diff --git a/interactive-mining-madoap/madoap/src/etc/init.d/oapwebserver b/interactive-mining-madoap/madoap/src/etc/init.d/oapwebserver new file mode 100755 index 0000000..73a63b4 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/etc/init.d/oapwebserver @@ -0,0 +1,74 @@ +#! /bin/sh +# oastatwebserver: OpenAIRE statistics server. +# +# chkconfig: 2345 56 10 +# description: OpenAIRE statistics server. +# + +### BEGIN INIT INFO +# Provides: oawebserver +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Should-Start: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: OA web server +### END INIT INFO + +# Source function library. + +# RedHat +#. /etc/rc.d/init.d/functions + +# Debian +# to install: +# chmod 755 /etc/init.d/oawebserver +# update-rc.d oapwebserver defaults + +. /lib/lsb/init-functions + +DUSER="openaire" +SERVERNAME="oapwebserver" + +start() +{ +#iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080 +#iptables -t nat -A PREROUTING -p udp -m udp --dport 80 -j REDIRECT --to-ports 8080 +#iptables -t nat -A PREROUTING -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8443 +#iptables -t nat -A PREROUTING -p udp -m udp --dport 443 -j REDIRECT --to-ports 8443 + + echo -n $"Starting OpenAIRE stat server: " + su $DUSER -c 'screen -r '$SERVERNAME' -qX quit' > /dev/null 2>&1 + su $DUSER -c 'screen -q -d -m -S '$SERVERNAME' /usr/bin/python /home/'$DUSER'/programs/madoap/src/madserver.py' > /dev/null 2>&1 + echo +} + +stop() +{ + echo -n $"Shutting down web server: " + su $DUSER -c 'screen -r '$SERVERNAME' -qX quit' > /dev/null 2>&1 + + echo +} + + +# See how we were called. +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart|reload) + stop + sleep 1 + start + ;; + *) + echo $"Usage: $0 {start|stop|restart|reload}" + exit 1 +esac + +exit 0 + diff --git a/interactive-mining-madoap/madoap/src/madapps.py b/interactive-mining-madoap/madoap/src/madapps.py new file mode 100644 index 0000000..d6638d0 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/madapps.py @@ -0,0 +1,15 @@ +import json +#Query flows DO NOT SUPPORT COMMENTS!!!!!!!!!!!!!!!!!!! + +def getfromfile(filename): + import os + with open(os.path.join(settings.FLOW_PATH,filename)) as f: + return f.read() + +false=0 +true=1 + +apps=[ + + +] \ No newline at end of file diff --git a/interactive-mining-madoap/madoap/src/madserver.py b/interactive-mining-madoap/madoap/src/madserver.py new file mode 100755 index 0000000..f21ce61 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/madserver.py @@ -0,0 +1,726 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +import os +import re +import os.path +import re +import tornado.httpserver +import tornado.autoreload +import tornado.ioloop +import tornado.options +import tornado.web +import tornado.escape as escape +import settings as msettings +import madapps +import datetime +import random +import csv +import itertools +import email.utils +import json +import StringIO +from tornado.options import define, options, logging +from tornado_addons import ozhandler +import copy +from collections import OrderedDict + + +define("port", default=msettings.WEB_SERVER_PORT, help="run on the given port", type=int) + +filteredapps=None +filteredevals=None + +smallgif='GIF89a\1\0\1\0\x80\xff\0\xff\xff\xff\0\0\0,\0\0\0\0\1\0\1\0\0\2\2D\1\0;' + +viswidgetmap={ +'motionchart':'google.visualization.MotionChart', +'table':'google.visualization.Table', +'linechart':'google.visualization.LineChart', +'piechart':'google.visualization.PieChart', +'scatterchart':'google.visualization.ScatterChart', +'intensitymap':'google.visualization.IntensityMap', +'geomap':'google.visualization.GeoMap', +'columnchart':'google.visualization.ColumnChart', +'barchart':'google.visualization.BarChart', +'areachart':'google.visualization.AreaChart', +'annotatedtimeline':'google.visualization.AnnotatedTimeLine', +'termcloud':'TermCloud', +} + +queries = {} + +msettings.viswidgetmap=viswidgetmap + +class Application(tornado.web.Application): + def __init__(self): + handlers = [ + (r"/", madAppQueryGenerator), + (r"/importing-controller", importingControllerHandler), + (r"/importing-text-controller", importingTextsControllerHandler), + (r"/?$", madAppBarHandler), + (r"/[^/]+/?$", madAppHandler), + (r"/[^/]+/.+$", madAppDataHandler) + ] + + + settings = dict( + template_path=os.path.join(os.path.dirname(__file__), "templates"), + static_path=os.path.join(os.path.dirname(__file__), "static"), + xsrf_cookies=False, + cookie_secret=msettings.SECRET_KEY, + login_url="/auth/login", + debug=msettings.DEBUG + ) + + tornado.web.Application.__init__(self, handlers, **settings) + +def auth_callback(request, realm, username, password): + if username==msettings.USERNAME and password == msettings.PASSWORD: + request.user_id = 1 + return True + else: + return False + +def numberOfGrantsUploaded(user_id, cookie_set): + if cookie_set and user_id: + file_name = "/tmp/p%s.csv" % (user_id) + if os.path.isfile(file_name): + num_lines = sum(1 for line in open(file_name)) + if str(num_lines) == cookie_set: + return num_lines + return 0 + +def numberOfDocsUploaded(user_id): + if user_id: + file_name = "/tmp/docs%s.json" % (user_id) + if os.path.isfile(file_name): + num_lines = sum(1 for line in open(file_name)) + return num_lines + return 0 + +class BaseHandler(ozhandler.DjangoErrorMixin, ozhandler.BasicAuthMixin, tornado.web.RequestHandler): + def __init__(self, *args): + tornado.web.RequestHandler.__init__(self, *args) + if msettings.USERNAME!='': + self.hiddenauthget=self.get + self.get=self.authget + if msettings.RESTRICT_IPS: + self.hiddenget=self.get + self.get=self.checkwhitelistget + + def authget(self, *args): + try: + if self.passwordless: + self.hiddenauthget(*args) + return + except: + pass + + if not self.get_authenticated_user(auth_callback, 'stats'): + return False + self.hiddenauthget(*args) + + def checkwhitelistget(self, *args): + if self.request.remote_ip not in msettings.RESTRICT_IP_WHITELIST: + raise tornado.web.HTTPError(403) + return self.hiddenget(*args) + + def get_current_user(self): + return 'anonymous' + + def executequery(self, query, bindings=None): + def latinnum(x): + x=int(x) + lx="" + while x>25: + lx+=chr( ord('A')+int(x/25) ) + x%=25 + lx+=chr(ord('A')+x) + return lx + + query=query.rstrip(';\n\s ') + + try: + origvars=msettings.madis.functions.variables + c=msettings.Connection.cursor().execute(query, localbindings=bindings) + except Exception, e: + try: + c.close() + except: + pass + msettings.madis.functions.variables=origvars + self.finish(str(e)) + if msettings.DEBUG: + raise e + return + + # Schema from query's description + try: + schema=c.getdescription() + except: + c.close() + msettings.madis.functions.variables=origvars + self.finish() + return + + colnames=[] + coltypes=[] + + for cname, ctype in schema: + if ctype==None: + colnames+=[cname] + coltypes+=[ctype] + continue + ctypehead3=ctype.lower()[0:3] + if ctypehead3 in ('int', 'rea', 'flo', 'dou', 'num'): + ctype='number' + else: + ctype='string' + colnames+=[cname] + coltypes+=[ctype] + + try: + firstrow=c.next() + except StopIteration: + c.close() + msettings.madis.functions.variables=origvars + self.finish() + return + except Exception, e: + c.close() + msettings.madis.functions.variables=origvars + self.finish(str(e)) + return + + # Merge with guessed schema from query's first row + for cname, ctype, i in zip(colnames, coltypes, xrange(len(colnames))): + if ctype==None: + frtype=type(firstrow[i]) + if frtype in (int, float): + coltypes[i]='number' + else: + coltypes[i]='string' + + # Write responce's header + response={"cols":[]} + for name, ctype,num in zip(colnames, coltypes, xrange(len(colnames))): + id=latinnum(num) + response["cols"]+=[{"id":id, "label":name,"type":ctype}] + + # Write header + self.write(json.dumps(response, separators=(',', ':'), sort_keys=True, ensure_ascii=False)[0:-1] + ',"rows":[') + + # Write first line + response=json.dumps({"c":[{"v":x} for x in firstrow]}, separators=(',', ':'), sort_keys=True, ensure_ascii=False) + self.write(response) + + self.executequeryrow(c, msettings.madis.functions.variables) + msettings.madis.functions.variables=origvars + + def executequeryrow(self, cursor, vars): + try: + try: + origvars=msettings.madis.functions.variables + msettings.madis.functions.variables=vars + buffer=StringIO.StringIO() + while buffer.len<30000: + buffer.write(','+json.dumps({"c":[{"v":x} for x in cursor.next()]}, separators=(',', ':'), sort_keys=True, ensure_ascii=False)) + self.write(buffer.getvalue()) + self.flush(callback=lambda : self.executequeryrow(cursor, msettings.madis.functions.variables)) + except StopIteration: + cursor.close() + self.finish(buffer.getvalue()+']}') + finally: + msettings.madis.functions.variables=origvars + except IOError: + msettings.madis.functions.variables=origvars + cursor.close() + pass + + def serveimage(self, path, mime_type=None): + if os.path.sep != "/": + path = path.replace("/", os.path.sep) + abspath = os.path.abspath(os.path.join(self.settings['static_path'], path)) + + if mime_type==None: + mime_type='image/'+path[-3:] + self.set_header("Content-Type", mime_type) + + # Check the If-Modified-Since, and don't send the result if the + # content has not been modified + ims_value = self.request.headers.get("If-Modified-Since") + if ims_value is not None: + date_tuple = email.utils.parsedate(ims_value) + if_since = datetime.datetime.fromtimestamp(time.mktime(date_tuple)) + if if_since >= modified: + self.set_status(304) + return + + file = open(abspath, "rb") + try: + self.write(file.read()) + finally: + file.close() + +class HomeHandler(BaseHandler): + def get(self): + self.render("home.html", settings=msettings) + +class madAppBarHandler(BaseHandler): + def get(self): + self.render('madappbar.html', apps=filteredapps, evals=filteredevals, settings=msettings) + +trueset = set([1 , 'on', 'true', 'TRUE']) +URIdemultiplex = {r"/" + msettings.APPDIRNAME + "/analyze":'projects' + , r"/" + msettings.APPDIRNAME + "/datacitations":'datacitations' + , r"/" + msettings.APPDIRNAME + "/classifier":'classification' + , r"/" + msettings.APPDIRNAME + "/pdbs":'pdb' + , r"/" + msettings.APPDIRNAME + "/interactivemining":'interactivemining'} + + +class madAppQueryGenerator(BaseHandler): + passwordless=True + # When loading the page first time and evry refresh + def get(self): + if 'data' in self.request.arguments: + return + else: + # check if we already gave client a user_id + user_id = self.get_secure_cookie('madgikmining') + if not user_id: + # give him a unique user_id + user_id = 'user{0}'.format(datetime.datetime.now().microsecond + (random.randrange(1, 100+1) * 100000)) + self.set_secure_cookie('madgikmining', user_id) + # check if he already uploaded his grants ids and inform him via a message + numOfGrants = numberOfGrantsUploaded(user_id, self.get_secure_cookie('madgikmining_grantsuploaded')) + self.render('interactivemining.html', settings=msettings, numOfGrants=numOfGrants) + + + def post(self): + + if self.request.uri in URIdemultiplex: + self.request.arguments[ URIdemultiplex[self.request.uri] ] = ['on'] + + # Get the unique user id from the coookie set + user_id = self.get_secure_cookie('madgikmining') + # data to be sent + data = {} + try: + # he must upload his grant ids first + if numberOfGrantsUploaded(user_id, self.get_secure_cookie('madgikmining_grantsuploaded')) == 0: + self.write(json.dumps({'error': "A codes file must be uploaded first!"})) + return + + # 2 MODES of document upload: + # 1. he pasted some text in the document input + if 'document' in self.request.arguments: + doc = self.request.arguments['document'][0] + try: + doc = unicode(doc, 'utf_8', errors = 'ignore') + except: + doc = '' + if msettings.DEBUG: + raise + # 2. he already uploaded a txt of documents in json format + elif ('docsfileuploaded' not in self.request.arguments or ('docsfileuploaded' in self.request.arguments and self.request.arguments['docsfileuploaded'][0] not in trueset)) or numberOfDocsUploaded(user_id) == 0: + self.write(json.dumps({'error': "Documents must be uploaded!"})) + return + + # create positive and negative words weighted regex text + pos_set = neg_set = conf = whr_conf = '' + if 'poswords' in self.request.arguments and self.request.arguments['poswords'][0] != '{}': + # construct math string for positive words matching calculation with weights + pos_words = json.loads(self.request.arguments['poswords'][0]) + for key, value in pos_words.iteritems(): + pos_set += r'regexpcountuniquematches("(?:\b)%s(?:\b)",j2s(prev,middle,next))*%s + ' % (key,value) + pos_set += "0" + if 'negwords' in self.request.arguments and self.request.arguments['negwords'][0] != '{}': + # construct math string for negative words matching calculation with weights + neg_words = json.loads(self.request.arguments['negwords'][0]) + for key, value in neg_words.iteritems(): + neg_set += r'regexpcountuniquematches("(?:\b)%s(?:\b)",j2s(prev,middle,next))*%s - ' % (key,value) + neg_set += "0" + if pos_set != '' and neg_set != '': + conf = ", ({0} - {1})".format(pos_set, neg_set) + elif pos_set != '': + conf = ", {0}".format(pos_set) + elif neg_set != '': + conf = ", -{0}".format(neg_set) + if conf != '': + conf += ' as conf' + whr_conf = 'and conf>=0' + + # get the database cursor + cursor=msettings.Connection.cursor() + # create temp table with grants + list(cursor.execute("drop table if exists grants"+user_id, parse=False)) + query0 = "create temp table grants{0} as select stripchars(c1) as c3 from (file '/tmp/p{1}.csv')".format(user_id, user_id) + cursor.execute(query0) + if 'document' in self.request.arguments and self.request.arguments['document'][0] != '': + doc_filters = "regexpr('[\n|\r]',?,' ')" + if 'keywords' in self.request.arguments and self.request.arguments['keywords'][0] in trueset: + doc_filters = 'keywords('+doc_filters+')' + if 'lowercase' in self.request.arguments and self.request.arguments['lowercase'][0] in trueset: + doc_filters = 'lower('+doc_filters+')' + if 'stopwords' in self.request.arguments and self.request.arguments['stopwords'][0] in trueset: + doc_filters = 'filterstopwords('+doc_filters+')' + list(cursor.execute("select var('doc"+user_id+"', "+doc_filters+")", (doc,), parse=False)) + + #print 'query', [r for r in cursor.execute("select middle, j2s(prev,middle,next) %s from (select textwindow2s(var('doc%s'),10,1,5))" % (conf, user_id))] + query1 = "select c1 {0} from (select textwindow2s(var('doc{1}'),10,1,5)), (cache select stripchars(c1) as c1 from (file '/tmp/p{2}.csv')) T where middle = T.c1 {3}".format(conf, user_id, user_id, whr_conf) + data['funding_info'] = [{"code": r[0]} for r in cursor.execute(query1)] + elif numberOfDocsUploaded(user_id) != 0: + doc_filters = "regexpr('[\n|\r]',c2,' ')" + if 'keywords' in self.request.arguments and self.request.arguments['keywords'][0] in trueset: + doc_filters = 'keywords('+doc_filters+')' + if 'lowercase' in self.request.arguments and self.request.arguments['lowercase'][0] in trueset: + doc_filters = 'lower('+doc_filters+')' + if 'stopwords' in self.request.arguments and self.request.arguments['stopwords'][0] in trueset: + doc_filters = 'filterstopwords('+doc_filters+')' + list(cursor.execute("drop table if exists docs"+user_id, parse=False)) + query1 = "create temp table docs{0} as select c1, {1} as c2 from (setschema 'c1,c2' select jsonpath(c1, '$.id', '$.text') from (file '/tmp/docs{2}.json'))".format(user_id, doc_filters, user_id) + cursor.execute(query1) + + query2 = "select c1, c3 {0} from (select c1, textwindow2s(c2,10,1,5) from (select * from docs{1})), (select c3 from grants{2}) T where middle = T.c3 {3}".format(conf, user_id, user_id, whr_conf) + results = [r for r in cursor.execute(query2)] + data['funding_info'] = [{"code": r[1]} for r in results] + + except Exception as ints: + print ints + if msettings.DEBUG: + raise + + try: + cursor.close() + except: + pass + self.write(json.dumps(data)) + self.flush() + + +class saveProfileHandler(BaseHandler): + def post(self): + """Controls the importing job as follows: + *** load-raw-data (reading and saving them in the DB)""" + try: + user_id = self.get_secure_cookie('madgikmining') + if 'saveprofile' in self.request.arguments: + print "asda" + + except Exception as ints: + self.write(json.dumps({'respond': "SOomething went very wrong!"})) + print ints + return + + +class importingControllerHandler(BaseHandler): + def post(self): + """Controls the importing job as follows: + *** load-raw-data (reading and saving them in the DB)""" + + try: + + user_id = self.get_secure_cookie('madgikmining') + + csv_file_name = "/tmp/p{0}.csv".format(user_id) + csv_file = open(csv_file_name, 'w') + + body_split = [l.strip() for l in StringIO.StringIO(self.request.body).readlines()] + if body_split[3:5][0] == 'example': + #static/fp7grants.csv + + fp7_file = open("static/fp7grants.csv", 'r') + + while 1: + copy_buffer = fp7_file.read(1048576) + if not copy_buffer: + break + csv_file.write(copy_buffer) + + # cursor = msettings.Connection.cursor() + # cursor.execute('drop table if exists p%s' % (user_id)) + # cursor.execute('create temp table p%s(words)' % (user_id)) + # cursor.executemany("insert into p" + user_id + "(words) values(?)", + # ( + # ('246686',), ('283595',) + # ) + # ) + # try: + # cursor.close() + # except: + # pass + self.write(json.dumps({'respond': "25536 fp7 Codes loaded successfully!"})) + self.set_secure_cookie('madgikmining_grantsuploaded', "25536") + elif body_split[3:5][0] == 'normal': + importing_data = email.message_from_string('\n'.join(body_split[5:-1])) + + file_name = importing_data.get_filename() + csvfile = importing_data.get_payload() + dialect = csv.Sniffer().sniff(csvfile) + data = list(csvfile.splitlines()) + + for line in data: + csv_file.write(line+'\n') + + # cursor = msettings.Connection.cursor() + # cursor.execute('drop table if exists p%s' % (user_id)) + # cursor.execute('create temp table p%s(words)' % (user_id)) + # cursor.executemany("insert into p" + user_id + "(words) values(?)", + # ( + # (x,) for x in itertools.islice(data, None) + # ) + # ) + if len(data) == 1: + self.write(json.dumps({'respond': "File {0} uploaded.
1 Code loaded! Please make sure that you separate each code with newline!".format(file_name)})) + else: + self.write(json.dumps({'respond': "File {0} uploaded.
{1} Codes loaded successfully!".format(file_name, len(data))})) + self.set_secure_cookie('madgikmining_grantsuploaded', str(len(data))) + + csv_file.close() + + except Exception as ints: + self.write(json.dumps({'respond': "File Failed to Upload!"})) + print ints + return + + + +class importingTextsControllerHandler(BaseHandler): + def post(self): + """Controls the importing job as follows: + *** load-raw-data (reading and saving them in the DB)""" + + try: + # get user id from cookie. Must have + user_id = self.get_secure_cookie('madgikmining') + if user_id is None: + return + # get file info and body from post data + fileinfo = self.request.files['upload'][0] + fname = fileinfo['filename'] + extn = os.path.splitext(fname)[1] + # must be .pdf or .json + if extn != ".txt" and extn != ".pdf": + self.write(json.dumps({'respond': "File must be .pdf or .txt"})) + return + # write data to physical file + cname = "/tmp/docs{0}{1}".format(user_id, extn) + fh = open(cname, 'w') + fh.write(fileinfo['body']) + fh.close() + + # Convert pdf to txt and then to json format + if extn == ".pdf": + import subprocess as sub + p = sub.Popen(['pdftotext', '-enc', 'UTF-8', cname],stdout=sub.PIPE,stderr=sub.PIPE) + output, errors = p.communicate() + if errors: + self.write(json.dumps({'respond': "Cannot convert .pdf to .txt"})) + return + os.remove(cname) + cname = "/tmp/docs{0}.txt".format(user_id) + with open(cname, 'r') as fin: + data=fin.read().replace('\n', ' ') + if len(data)==0: + self.write(json.dumps({'respond': "Cannot convert .pdf to .txt"})) + return + with open("/tmp/docs{0}.json".format(user_id), "wb") as fout: + json.dump({"text":data,"id":os.path.splitext(fname)[0]}, fout) + os.remove(cname) + # else check if txt is in correct json format + elif extn == ".txt": + try: + jsonlist = [] + for line in open(cname, 'r'): + jsonlist.append(json.loads(line)) + os.rename(cname, "/tmp/docs{0}.json".format(user_id)) + except ValueError, e: + self.write(json.dumps({'respond': "File is not in a valid json format"})) + os.remove(cname) + print e + return + self.write(json.dumps({'respond': "File {0} uploaded successfully!
".format(fname)})) + + except Exception as ints: + self.write(json.dumps({'respond': "File Failed to Upload!"})) + print ints + return + + + +class madAppHandler(BaseHandler): + def get(self): + try: + appname=re.match(r'.+/([^/]+)/?$', self.request.uri).groups()[0].lower() + except AttributeError: + raise tornado.web.HTTPError(404) + + appobj=None + for ap in madapps.apps: + if ap['link']==appname: + appobj=ap + break + + if appobj==None: + raise tornado.web.HTTPError(404) + + self.render('madappview.html', app=appobj, apps=filteredapps, evals=filteredevals, settings=msettings) + +class madAppDataHandler(BaseHandler): + + @tornado.web.asynchronous + def post(self): + try: + appname, queryname=[x.lower() for x in re.match(r'.+/([^/]+)/(.+)$', self.request.uri).groups()] + except AttributeError: + raise tornado.web.HTTPError(404) + + appobj=None + query='' + for ap in madapps.apps: + if ap['link']==appname: + if queryname in ap: + appobj=ap + if queryname=='query': + query=appobj['query'] + else: + query=appobj[queryname]['query'] + break + + if appobj==None: + raise tornado.web.HTTPError(404) + + params=dict(((x.replace(' ','_'),y[0].replace('\n','')) for x,y in self.request.arguments.iteritems()) ) + self.executequery(query, params) + + + + + +def main(): + global filteredapps, filteredevals + + def getqtext(query,params): + query=query.strip('\n \s') + query=escape.xhtml_escape(query) + for i in params: + i=i.replace(' ','_') + query=re.sub(':'+i, ''+escape.xhtml_escape(i)+'', query) + query=re.sub('$'+i, ''+escape.xhtml_escape(i)+'', query) + query=re.sub('@'+i, ''+escape.xhtml_escape(i)+'', query) + return query.replace("\n","
") + + def getparams(app): + qparams=re.findall('%{(.*?)}',app['query'], re.UNICODE ) + return set(qparams) + + def getqueries(): + query_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),'queries')) + for dir, _, files in os.walk(query_dir): + for file in files: + if file.endswith('.sql'): + queries[os.path.splitext(file)[0]] = open(os.path.join(dir,file), 'r').read() + if msettings.DEBUG: + tornado.autoreload.watch(os.path.join(dir,file)) + + def getexamples(app): + if "examples" not in app: + return [] + fullexamples=[] + if type(app["examples"])==list: + i=0 + for el in app["examples"]: + i+=1 + d={} + d["name"]='ex'+str(i) + d["paramstring"]=str(el).replace('{','').replace('}','').replace("'",'') + d["paramarray"]=json.dumps(el) + fullexamples.append(d) + else: + for el in app["examples"]: + d={} + d["name"]=el + d["paramstring"]=str(app["examples"][el]).replace('{','').replace('}','').replace("'",'') + d["paramarray"]=json.dumps(app["examples"][el]) + fullexamples.append(d) + fullexamples.sort(key=lambda x:x["name"]) + return fullexamples + + def processtemplate(app): + if 'template' not in app: + return + + getqueries() + + if 'initial_queries' in queries: + try: + list(msettings.Connection.cursor().execute(queries['initial_queries'])) + except Exception, e: + raise Exception("Error when executing DB_INITIAL_EXECUTE:\n"+queries['initial_queries']+"\nThe error was:\n"+ str(e)) + + tornado.options.parse_command_line() + + # Restructure applications + logging.info('Running madApp startup scripts') + + for app in madapps.apps: + + app['link']=app['link'].lower() + if "title" not in app: + app["title"]=app['link'] + if "linktitle" not in app: + app["linktitle"]=app["title"] + + if 'startup' in app: + c=msettings.Connection.cursor() + logging.info('Running startup queries for app'+app['linktitle']+' :\n'+app['startup']) + c.execute(app['startup']) + c.close() + + app["qtext"]=getqtext(app["query"], [p['name'] for p in app['params']]) + app["examples"]=getexamples(app) + app['datavisualizations']=dict([(x,[y['visualizations']] if type(y['visualizations'])==dict else y['visualizations']) for x,y in app.iteritems() if type(y)==dict and 'query' in y]) + if 'query' in app: + app['datavisualizations']['query']=copy.deepcopy(app['visualisations']) + for vis in app['visualisations']: + vis['viswidgetmap']=viswidgetmap[vis['name'].lower()] + + logging.info('Completed madApp startup scripts') + + filteredapps=filter(lambda x:("eval" not in x),madapps.apps) + filteredevals=filter(lambda x:("eval" in x),madapps.apps) + + if not msettings.DEBUG: + sockets = tornado.netutil.bind_sockets(options.port) + tornado.process.fork_processes(0) + server = tornado.httpserver.HTTPServer(Application()) + # ssl_options = { + #"certfile": os.path.join("/home/openaire/ssl/certificate.crt"), + #"keyfile": os.path.join("/home/openaire/ssl/privateKey.key"), +#}) + server.add_sockets(sockets) + tornado.ioloop.IOLoop.instance().start() + else: +# debug case + http_server = tornado.httpserver.HTTPServer(Application()) + http_server.bind(options.port) + http_server.start(1) + tornado.ioloop.IOLoop.instance().start() + + + +if __name__ == "__main__": + main() diff --git a/interactive-mining-madoap/madoap/src/madserverssl.py b/interactive-mining-madoap/madoap/src/madserverssl.py new file mode 100755 index 0000000..1a5b05d --- /dev/null +++ b/interactive-mining-madoap/madoap/src/madserverssl.py @@ -0,0 +1,745 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +import os +import re +import os.path +import re +import tornado.httpserver +import tornado.autoreload +import tornado.ioloop +import tornado.options +import tornado.web +import tornado.escape as escape +import settings as msettings +import madapps +import datetime +import random +import csv +import itertools +import email.utils +import json +import StringIO +from tornado.options import define, options, logging +from tornado_addons import ozhandler +import copy +from collections import OrderedDict + + +define("port", default=msettings.WEB_SERVER_PORT, help="run on the given port", type=int) + +filteredapps=None +filteredevals=None + +smallgif='GIF89a\1\0\1\0\x80\xff\0\xff\xff\xff\0\0\0,\0\0\0\0\1\0\1\0\0\2\2D\1\0;' + +viswidgetmap={ +'motionchart':'google.visualization.MotionChart', +'table':'google.visualization.Table', +'linechart':'google.visualization.LineChart', +'piechart':'google.visualization.PieChart', +'scatterchart':'google.visualization.ScatterChart', +'intensitymap':'google.visualization.IntensityMap', +'geomap':'google.visualization.GeoMap', +'columnchart':'google.visualization.ColumnChart', +'barchart':'google.visualization.BarChart', +'areachart':'google.visualization.AreaChart', +'annotatedtimeline':'google.visualization.AnnotatedTimeLine', +'termcloud':'TermCloud', +} + +queries = {} + +msettings.viswidgetmap=viswidgetmap + +class Application(tornado.web.Application): + def __init__(self): + handlers = [ + (r"/", HomeHandler), + (r"/(?i)"+msettings.APPDIRNAME+"/analyze", madAppMiningServices), + (r"/(?i)"+msettings.APPDIRNAME+"/classifier", madAppMiningServices), + (r"/(?i)"+msettings.APPDIRNAME+"/datacitations", madAppMiningServices), + (r"/(?i)"+msettings.APPDIRNAME+"/citations", madAppMiningServices), + (r"/(?i)"+msettings.APPDIRNAME+"/docsim", madAppMiningServices), + (r"/(?i)"+msettings.APPDIRNAME+"/software", madAppMiningServices), + (r"/(?i)"+msettings.APPDIRNAME+"/pdbs", madAppMiningServices), + (r"/(?i)"+msettings.APPDIRNAME+"/images", madAppMiningServices), + (r"/(?i)"+msettings.APPDIRNAME+"/interactivemining", madAppQueryGenerator), + (r"/(?i)"+msettings.APPDIRNAME+"/interactivemining/importing-controller", importingControllerHandler), + (r"/(?i)"+msettings.APPDIRNAME+"/?$", madAppBarHandler), + (r"/(?i)"+msettings.APPDIRNAME+"/[^/]+/?$", madAppHandler), + (r"/(?i)"+msettings.APPDIRNAME+"/[^/]+/.+$", madAppDataHandler) + ] + + + settings = dict( + template_path=os.path.join(os.path.dirname(__file__), "templates"), + static_path=os.path.join(os.path.dirname(__file__), "static"), + xsrf_cookies=False, + cookie_secret=msettings.SECRET_KEY, + login_url="/auth/login", + debug=msettings.DEBUG + ) + + tornado.web.Application.__init__(self, handlers, **settings) + +def auth_callback(request, realm, username, password): + if username==msettings.USERNAME and password == msettings.PASSWORD: + request.user_id = 1 + return True + else: + return False + +class BaseHandler(ozhandler.DjangoErrorMixin, ozhandler.BasicAuthMixin, tornado.web.RequestHandler): + def __init__(self, *args): + tornado.web.RequestHandler.__init__(self, *args) + if msettings.USERNAME!='': + self.hiddenauthget=self.get + self.get=self.authget + if msettings.RESTRICT_IPS: + self.hiddenget=self.get + self.get=self.checkwhitelistget + + def authget(self, *args): + try: + if self.passwordless: + self.hiddenauthget(*args) + return + except: + pass + + if not self.get_authenticated_user(auth_callback, 'stats'): + return False + self.hiddenauthget(*args) + + def checkwhitelistget(self, *args): + if self.request.remote_ip not in msettings.RESTRICT_IP_WHITELIST: + raise tornado.web.HTTPError(403) + return self.hiddenget(*args) + + def get_current_user(self): + return 'anonymous' + + def executequery(self, query, bindings=None): + def latinnum(x): + x=int(x) + lx="" + while x>25: + lx+=chr( ord('A')+int(x/25) ) + x%=25 + lx+=chr(ord('A')+x) + return lx + + query=query.rstrip(';\n\s ') + + try: + origvars=msettings.madis.functions.variables + c=msettings.Connection.cursor().execute(query, localbindings=bindings) + except Exception, e: + try: + c.close() + except: + pass + msettings.madis.functions.variables=origvars + self.finish(str(e)) + if msettings.DEBUG: + raise e + return + + # Schema from query's description + try: + schema=c.getdescription() + except: + c.close() + msettings.madis.functions.variables=origvars + self.finish() + return + + colnames=[] + coltypes=[] + + for cname, ctype in schema: + if ctype==None: + colnames+=[cname] + coltypes+=[ctype] + continue + ctypehead3=ctype.lower()[0:3] + if ctypehead3 in ('int', 'rea', 'flo', 'dou', 'num'): + ctype='number' + else: + ctype='string' + colnames+=[cname] + coltypes+=[ctype] + + try: + firstrow=c.next() + except StopIteration: + c.close() + msettings.madis.functions.variables=origvars + self.finish() + return + except Exception, e: + c.close() + msettings.madis.functions.variables=origvars + self.finish(str(e)) + return + + # Merge with guessed schema from query's first row + for cname, ctype, i in zip(colnames, coltypes, xrange(len(colnames))): + if ctype==None: + frtype=type(firstrow[i]) + if frtype in (int, float): + coltypes[i]='number' + else: + coltypes[i]='string' + + # Write responce's header + response={"cols":[]} + for name, ctype,num in zip(colnames, coltypes, xrange(len(colnames))): + id=latinnum(num) + response["cols"]+=[{"id":id, "label":name,"type":ctype}] + + # Write header + self.write(json.dumps(response, separators=(',', ':'), sort_keys=True, ensure_ascii=False)[0:-1] + ',"rows":[') + + # Write first line + response=json.dumps({"c":[{"v":x} for x in firstrow]}, separators=(',', ':'), sort_keys=True, ensure_ascii=False) + self.write(response) + + self.executequeryrow(c, msettings.madis.functions.variables) + msettings.madis.functions.variables=origvars + + def executequeryrow(self, cursor, vars): + try: + try: + origvars=msettings.madis.functions.variables + msettings.madis.functions.variables=vars + buffer=StringIO.StringIO() + while buffer.len<30000: + buffer.write(','+json.dumps({"c":[{"v":x} for x in cursor.next()]}, separators=(',', ':'), sort_keys=True, ensure_ascii=False)) + self.write(buffer.getvalue()) + self.flush(callback=lambda : self.executequeryrow(cursor, msettings.madis.functions.variables)) + except StopIteration: + cursor.close() + self.finish(buffer.getvalue()+']}') + finally: + msettings.madis.functions.variables=origvars + except IOError: + msettings.madis.functions.variables=origvars + cursor.close() + pass + + def serveimage(self, path, mime_type=None): + if os.path.sep != "/": + path = path.replace("/", os.path.sep) + abspath = os.path.abspath(os.path.join(self.settings['static_path'], path)) + + if mime_type==None: + mime_type='image/'+path[-3:] + self.set_header("Content-Type", mime_type) + + # Check the If-Modified-Since, and don't send the result if the + # content has not been modified + ims_value = self.request.headers.get("If-Modified-Since") + if ims_value is not None: + date_tuple = email.utils.parsedate(ims_value) + if_since = datetime.datetime.fromtimestamp(time.mktime(date_tuple)) + if if_since >= modified: + self.set_status(304) + return + + file = open(abspath, "rb") + try: + self.write(file.read()) + finally: + file.close() + +class HomeHandler(BaseHandler): + def get(self): + self.render("home.html", settings=msettings) + +class madAppBarHandler(BaseHandler): + def get(self): + self.render('madappbar.html', apps=filteredapps, evals=filteredevals, settings=msettings) + +trueset = set([1 , 'on', 'true', 'TRUE']) +URIdemultiplex = {r"/" + msettings.APPDIRNAME + "/analyze":'projects' + , r"/" + msettings.APPDIRNAME + "/datacitations":'datacitations' + , r"/" + msettings.APPDIRNAME + "/classifier":'classification' + , r"/" + msettings.APPDIRNAME + "/pdbs":'pdb' + , r"/" + msettings.APPDIRNAME + "/interactivemining":'interactivemining'} + +class madAppMiningServices(BaseHandler): + passwordless=True + def get(self): + if 'data' in self.request.arguments: + return + else: + if self.request.uri == r"/" + msettings.APPDIRNAME + "/analyze": + self.render('analyze.html',settings=msettings) + elif self.request.uri == r"/" + msettings.APPDIRNAME + "/classifier": + self.render('classifier.html',settings=msettings) + elif self.request.uri == r"/" + msettings.APPDIRNAME + "/datacitations": + self.render('datacitations.html',settings=msettings) + elif self.request.uri == r"/" + msettings.APPDIRNAME + "/citations": + self.render('citations.html',settings=msettings) + elif self.request.uri == r"/" + msettings.APPDIRNAME + "/docsim": + self.render('similarity.html',settings=msettings) + elif self.request.uri == r"/" + msettings.APPDIRNAME + "/software": + self.render('software.html',settings=msettings) + elif self.request.uri == r"/" + msettings.APPDIRNAME + "/pdbs": + self.render('pdbs.html',settings=msettings) + elif self.request.uri == r"/" + msettings.APPDIRNAME + "/images": + self.render('images.html',settings=msettings) + + def post(self): + + if self.request.uri in URIdemultiplex: + self.request.arguments[ URIdemultiplex[self.request.uri] ] = ['on'] + + data = {} + try: + if 'document' in self.request.arguments: + doc = self.request.arguments['document'][0] + else: + if 'image' in self.request.files: + fileinfo = self.request.files['image'][0] + fname = fileinfo['filename'] + else: + return + if 'document' in self.request.arguments: + try: + doc = unicode(doc, 'utf_8', errors = 'ignore') + except: + doc = '' + if msettings.DEBUG: + raise + + cursor=msettings.Connection.cursor() + if 'projects' in self.request.arguments and self.request.arguments['projects'][0] in trueset: + list(cursor.execute(r"select var('doc', regexpr('(\b\S*?[^0-9\s_]\S*?\s_?)(\d{3})(\s)(\d{3})(_?\s\S*?[^0-9\s_]\S*?\b)',filterstopwords(normalizetext(lower(?))),'\1\2\4\5'))", (doc,), parse=False)) + list(cursor.execute(r"select var('doc_unprocessed', ?)", (doc,), parse=False)) + list(cursor.execute(r"select var('doc2', regexpr('\n',comprspaces(?),' '))", (doc,), parse=False)) + query = queries['fundingminequery'] + data['funding_info'] = [OrderedDict([('fund', r[0]),('acronym', r[1]),('grantid', r[2]),('confidence', r[3]),('EGI-related',True if r[4]==1 else False)]) for r in cursor.execute(query)] + + + if 'datacitations' in self.request.arguments and self.request.arguments['datacitations'][0] in trueset: + if doc.count('\n')>10: + list(cursor.execute(r"select var('doc', normalizetext(textreferences(?)))", (doc,), parse=False)) + else: + list(cursor.execute(r"select var('doc', normalizetext(?))", (doc,), parse=False)) + list(cursor.execute(r"select var('doc2', comprspaces(filterstopwords(regexpr('(/|:)(\n)',?,'\1'))))", (doc,), parse=False)) + query = queries['datacitationsquery'] + data['datacitation_info'] = [OrderedDict([('organization', r[0]),('related_doi', r[1]),('confidence', r[2]),('resource_type', r[3])]) for r in cursor.execute(query)] + + + if 'classification' in self.request.arguments and self.request.arguments['classification'][0] in trueset: + print list(cursor.execute(r"select var('doc', (stem(filterstopwords(keywords(?)))))", (doc,), parse=False)) + + query = queries['classifierquery'] + data['classification_info'] = [OrderedDict([('taxonomy', r[0]),('class', r[1]),('confidence', r[2])]) for r in cursor.execute(query)] + + if 'pdb' in self.request.arguments and self.request.arguments['pdb'][0] in trueset: + list(cursor.execute(r"select var('doc', comprspaces(lower(filterstopwords(regexpr('[^\w-]',?,' ')))) )", (doc,), parse=False)) + query = queries['pdbquery'] + data['pdb_info'] = [OrderedDict([('pdbid', r[0])]) for r in cursor.execute(query)] + if 'software' in self.request.arguments: + list(cursor.execute(r"select var('doc6', ?)", (doc,), parse=False)) + query = queries['software'] + data['software_info'] = [OrderedDict([('softwareURL', r[0])]) for r in cursor.execute(query)] + if 'image' in self.request.files: + pass + except: + if msettings.DEBUG: + raise + + try: + cursor.close() + except: + pass + if not self.request.files: + self.write(json.dumps(data)) + self.flush() + else : + #Query image:
') + self.write('

') + self.write('
Returned images:
') + for i in lala: + self.write('

') + except IOError: + self.write('Not an image file') + os.unlink('static/uploads/'+fname) + + self.flush() + + + +class madAppQueryGenerator(BaseHandler): + passwordless=True + def get(self): + if 'data' in self.request.arguments: + return + else: + user_id = self.get_secure_cookie('madgikmining') + #print "old", user_id + if not user_id: + user_id = 'user%s' % (datetime.datetime.now().microsecond + (random.randrange(1, 100+1) * 100000)) + #print "new", user_id + self.set_secure_cookie('madgikmining', user_id) + #encoded = jwt.encode({'user': user_id}, 'secret', algorithm='HS256') + self.render('interactivemining.html', settings=msettings) + + + def post(self): + + if self.request.uri in URIdemultiplex: + self.request.arguments[ URIdemultiplex[self.request.uri] ] = ['on'] + + user_id = self.get_secure_cookie('madgikmining') + + data = {} + try: + if 'fileuploaded' not in self.request.arguments or ('fileuploaded' in self.request.arguments and self.request.arguments['fileuploaded'][0] not in trueset): + self.write(json.dumps({'error': "A file must be uploaded first!"})) + return + if 'document' in self.request.arguments: + doc = self.request.arguments['document'][0] + try: + doc = unicode(doc, 'utf_8', errors = 'ignore') + except: + doc = '' + if msettings.DEBUG: + raise + + cursor=msettings.Connection.cursor() + + pos_set = neg_set = '' + + if 'poswords' in self.request.arguments: + cursor.execute("drop table if exists pos%s" % (user_id)) + cursor.execute("create temp table pos%s(words)" % (user_id)) + + # cursor.executemany("insert into pos" + user_id + "(words) values(?)", + # ( + # ('(?:\b)'+x+'(?:\b)',) for x in self.request.arguments['poswords'][0][:-1].split('|') + # ) + # ) + cursor.executemany("insert into pos" + user_id + "(words) values(?)", + ( + (r"(?:\b)%s(?:\b)" % (x),) for x in self.request.arguments['poswords'][0][:-1].split('|') + ) + ) + cursor.execute("hidden var 'varpos%s' from select jmergeregexp(jgroup(words)) from (select * from pos%s order by length(words) desc)" % (user_id, user_id)) + #data['poswords'] = [r for r in cursor.execute('select * from pos%s' % (user_id))] + cursor.execute("drop table if exists pos%s" % (user_id)) + pos_set = "regexpcountuniquematches(var('varpos%s'),j2s(prev,middle,next))" % (user_id) + if 'negwords' in self.request.arguments: + cursor.execute("drop table if exists neg%s" % (user_id)) + cursor.execute("create temp table neg%s(words)" % (user_id)) + cursor.executemany("insert into neg" + user_id + "(words) values(?)", + ( + (r"(?:\b)%s(?:\b)" % (x),) for x in unicode(self.request.arguments['negwords'][0][:-1], 'utf_8', errors = 'ignore').split('|') + ) + ) + cursor.execute("hidden var 'varneg%s' from select jmergeregexp(jgroup(words)) from (select * from neg%s order by length(words) desc)" % (user_id, user_id)) + #data['negwords'] = [r for r in cursor.execute("select var('varneg%s')" % (user_id))] + cursor.execute('drop table if exists neg%s' % (user_id)) + neg_set = "regexpcountuniquematches(var('varneg%s'),j2s(prev,middle,next))" % (user_id) + + doc_filters = "regexpr('[\n|\r]',?,' ')" + if 'keywords' in self.request.arguments and self.request.arguments['keywords'][0] in trueset: + doc_filters = 'keywords('+doc_filters+')' + if 'lowercase' in self.request.arguments and self.request.arguments['lowercase'][0] in trueset: + doc_filters = 'lower('+doc_filters+')' + if 'stopwords' in self.request.arguments and self.request.arguments['stopwords'][0] in trueset: + doc_filters = 'filterstopwords('+doc_filters+')' + + cursor=msettings.Connection.cursor() + if 'document' in self.request.arguments and self.request.arguments['document'][0] != '': + list(cursor.execute("select var('doc"+user_id+"', "+doc_filters+")", (doc,), parse=False)) + conf = '' + if pos_set != '' and neg_set != '': + conf = ", (%s - %s)" % (pos_set, neg_set) + elif pos_set != '': + conf = ", %s" % (pos_set) + elif neg_set != '': + conf = ", %s" % (neg_set) + if conf != '': + conf += ' as conf' + query = "select c1 %s from (select textwindow2s(var('doc%s'),10,1,5)), (cache select stripchars(c1) as c1 from (file '/tmp/p%s.csv')) T where middle = T.c1" % ('', user_id, user_id) + data['funding_info'] = [{"code": r[0]} for r in cursor.execute(query)] + except: + if msettings.DEBUG: + raise + + try: + cursor.close() + except: + pass + self.write(json.dumps(data)) + self.flush() + + +class importingControllerHandler(BaseHandler): + def post(self): + """Controls the importing job as follows: + *** load-raw-data (reading and saving them in the DB)""" + + try: + + user_id = self.get_secure_cookie('madgikmining') + + csv_file_name = "/tmp/p%s.csv" % (user_id) + csv_file = open(csv_file_name, 'w') + + body_split = [l.strip() for l in StringIO.StringIO(self.request.body).readlines()] + if body_split[3:5][0] == 'example': + #static/fp7grants.csv + + fp7_file = open("fp7grants.csv", 'r') + + while 1: + copy_buffer = fp7_file.read(1048576) + if not copy_buffer: + break + csv_file.write(copy_buffer) + + # cursor = msettings.Connection.cursor() + # cursor.execute('drop table if exists p%s' % (user_id)) + # cursor.execute('create temp table p%s(words)' % (user_id)) + # cursor.executemany("insert into p" + user_id + "(words) values(?)", + # ( + # ('246686',), ('283595',) + # ) + # ) + # try: + # cursor.close() + # except: + # pass + self.write(json.dumps({'respond': "25536 fp7 Codes loaded successfully!"})) + elif body_split[3:5][0] == 'normal': + importing_data = email.message_from_string('\n'.join(body_split[5:-1])) + + file_name = importing_data.get_filename() + csvfile = importing_data.get_payload() + dialect = csv.Sniffer().sniff(csvfile) + data = list(csvfile.splitlines()) + + for line in data: + csv_file.write(line+'\n') + + # cursor = msettings.Connection.cursor() + # cursor.execute('drop table if exists p%s' % (user_id)) + # cursor.execute('create temp table p%s(words)' % (user_id)) + # cursor.executemany("insert into p" + user_id + "(words) values(?)", + # ( + # (x,) for x in itertools.islice(data, None) + # ) + # ) + if len(data) == 1: + self.write(json.dumps({'respond': "File "+file_name+" uploaded.
1 Code loaded! Please make sure that you separate each code with newline!"})) + else: + self.write(json.dumps({'respond': "File "+file_name+" uploaded.
%s Codes loaded successfully!" % (len(data))})) + + csv_file.close() + + except Exception as ints: + self.write(json.dumps({'respond': "File Failed to Upload!"})) + print ints + return + + # try: + # cursor.close() + # except: + # pass + + + +class madAppHandler(BaseHandler): + def get(self): + try: + appname=re.match(r'.+/([^/]+)/?$', self.request.uri).groups()[0].lower() + except AttributeError: + raise tornado.web.HTTPError(404) + + appobj=None + for ap in madapps.apps: + if ap['link']==appname: + appobj=ap + break + + if appobj==None: + raise tornado.web.HTTPError(404) + + self.render('madappview.html', app=appobj, apps=filteredapps, evals=filteredevals, settings=msettings) + +class madAppDataHandler(BaseHandler): + + @tornado.web.asynchronous + def post(self): + try: + appname, queryname=[x.lower() for x in re.match(r'.+/([^/]+)/(.+)$', self.request.uri).groups()] + except AttributeError: + raise tornado.web.HTTPError(404) + + appobj=None + query='' + for ap in madapps.apps: + if ap['link']==appname: + if queryname in ap: + appobj=ap + if queryname=='query': + query=appobj['query'] + else: + query=appobj[queryname]['query'] + break + + if appobj==None: + raise tornado.web.HTTPError(404) + + params=dict(((x.replace(' ','_'),y[0].replace('\n','')) for x,y in self.request.arguments.iteritems()) ) + self.executequery(query, params) + + + + + +def main(): + global filteredapps, filteredevals + + def getqtext(query,params): + query=query.strip('\n \s') + query=escape.xhtml_escape(query) + for i in params: + i=i.replace(' ','_') + query=re.sub(':'+i, ''+escape.xhtml_escape(i)+'', query) + query=re.sub('$'+i, ''+escape.xhtml_escape(i)+'', query) + query=re.sub('@'+i, ''+escape.xhtml_escape(i)+'', query) + return query.replace("\n","
") + + def getparams(app): + qparams=re.findall('%{(.*?)}',app['query'], re.UNICODE ) + return set(qparams) + + def getqueries(): + query_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),'queries')) + for dir, _, files in os.walk(query_dir): + for file in files: + if file.endswith('.sql'): + queries[os.path.splitext(file)[0]] = open(os.path.join(dir,file), 'r').read() + if msettings.DEBUG: + tornado.autoreload.watch(os.path.join(dir,file)) + + def getexamples(app): + if "examples" not in app: + return [] + fullexamples=[] + if type(app["examples"])==list: + i=0 + for el in app["examples"]: + i+=1 + d={} + d["name"]='ex'+str(i) + d["paramstring"]=str(el).replace('{','').replace('}','').replace("'",'') + d["paramarray"]=json.dumps(el) + fullexamples.append(d) + else: + for el in app["examples"]: + d={} + d["name"]=el + d["paramstring"]=str(app["examples"][el]).replace('{','').replace('}','').replace("'",'') + d["paramarray"]=json.dumps(app["examples"][el]) + fullexamples.append(d) + fullexamples.sort(key=lambda x:x["name"]) + return fullexamples + + def processtemplate(app): + if 'template' not in app: + return + + getqueries() + + if 'initial_queries' in queries: + try: + list(msettings.Connection.cursor().execute(queries['initial_queries'])) + except Exception, e: + raise Exception("Error when executing DB_INITIAL_EXECUTE:\n"+queries['initial_queries']+"\nThe error was:\n"+ str(e)) + + tornado.options.parse_command_line() + + # Restructure applications + logging.info('Running madApp startup scripts') + + for app in madapps.apps: + + app['link']=app['link'].lower() + if "title" not in app: + app["title"]=app['link'] + if "linktitle" not in app: + app["linktitle"]=app["title"] + + if 'startup' in app: + c=msettings.Connection.cursor() + logging.info('Running startup queries for app'+app['linktitle']+' :\n'+app['startup']) + c.execute(app['startup']) + c.close() + + app["qtext"]=getqtext(app["query"], [p['name'] for p in app['params']]) + app["examples"]=getexamples(app) + app['datavisualizations']=dict([(x,[y['visualizations']] if type(y['visualizations'])==dict else y['visualizations']) for x,y in app.iteritems() if type(y)==dict and 'query' in y]) + if 'query' in app: + app['datavisualizations']['query']=copy.deepcopy(app['visualisations']) + for vis in app['visualisations']: + vis['viswidgetmap']=viswidgetmap[vis['name'].lower()] + + logging.info('Completed madApp startup scripts') + + filteredapps=filter(lambda x:("eval" not in x),madapps.apps) + filteredevals=filter(lambda x:("eval" in x),madapps.apps) + + if not msettings.DEBUG: + sockets = tornado.netutil.bind_sockets(options.port) + tornado.process.fork_processes(0) + server = tornado.httpserver.HTTPServer(Application(), + ssl_options = { + "certfile": os.path.join("/home/openaire/ssl/certificate.crt"), + "keyfile": os.path.join("/home/openaire/ssl/privateKey.key"), +}) + server.add_sockets(sockets) + tornado.ioloop.IOLoop.instance().start() + else: +# debug case + http_server = tornado.httpserver.HTTPServer(Application()) + http_server.bind(options.port) + http_server.start(1) + tornado.ioloop.IOLoop.instance().start() + + + +if __name__ == "__main__": + main() diff --git a/interactive-mining-madoap/madoap/src/settings.py b/interactive-mining-madoap/madoap/src/settings.py new file mode 100644 index 0000000..3b01a88 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/settings.py @@ -0,0 +1,45 @@ +DEBUG = False +RESTRICT_IPS=False +#DAEMONIZE=False +#DEBUG = True +#RESTRICT_IPS=True +USERNAME='openaire' +PASSWORD='openaire' +WEB_SERVER_PORT=8080 +APPDIRNAME='openaireplus' +MADIS_PATH='../../../interactive-mining-3rdparty-madis/madis/src' +DB='static/database.db' + +FLOW_PATH='' + +# Change this. Make this unique, and don't share it with anybody. +SECRET_KEY = 's2b8!44p$0ycp!&p6)bhfoliuhdfvsieuppk5wl!@z=$#xj7yoc23fvr' + +# Check to see if some of the variables are defined +try: DB +except NameError: DB='' + +try: DAEMONIZE +except NameError: DAEMONIZE=False + +try: USERNAME +except NameError: USERNAME='' + +# Set madIS connection +import sys +sys.path.append(MADIS_PATH) + +import madis + +Connection=madis.functions.Connection(DB) + +def curip(): + import socket + ips = [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")] + if ips == []: + return '127.0.1.1' + else: + return [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][0] + +cclass='.'.join(curip().split('.')[0:3]) +RESTRICT_IP_WHITELIST= ['127.0.0.1']+[cclass+"."+str(i) for i in range(1,255)] diff --git a/interactive-mining-madoap/madoap/src/static/BG_Footer_2.jpg b/interactive-mining-madoap/madoap/src/static/BG_Footer_2.jpg new file mode 100644 index 0000000..1231ddd Binary files /dev/null and b/interactive-mining-madoap/madoap/src/static/BG_Footer_2.jpg differ diff --git a/interactive-mining-madoap/madoap/src/static/OpenAIREplus_logo.png b/interactive-mining-madoap/madoap/src/static/OpenAIREplus_logo.png new file mode 100644 index 0000000..bcdcc7c Binary files /dev/null and b/interactive-mining-madoap/madoap/src/static/OpenAIREplus_logo.png differ diff --git a/interactive-mining-madoap/madoap/src/static/OpenAIREplus_logo1.png b/interactive-mining-madoap/madoap/src/static/OpenAIREplus_logo1.png new file mode 100644 index 0000000..ab896ef Binary files /dev/null and b/interactive-mining-madoap/madoap/src/static/OpenAIREplus_logo1.png differ diff --git a/interactive-mining-madoap/madoap/src/static/OpenAIREplus_logo2.png b/interactive-mining-madoap/madoap/src/static/OpenAIREplus_logo2.png new file mode 100644 index 0000000..ac3dac5 Binary files /dev/null and b/interactive-mining-madoap/madoap/src/static/OpenAIREplus_logo2.png differ diff --git a/interactive-mining-madoap/madoap/src/static/accessURL.js b/interactive-mining-madoap/madoap/src/static/accessURL.js new file mode 100644 index 0000000..2244af5 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/static/accessURL.js @@ -0,0 +1,62 @@ +function accessURL(url, params, method, postCompletionCallback, visname) { + + var xhr=null; + + if (typeof XMLHttpRequest == "undefined") + XMLHttpRequest = function () { + try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } + catch (e) {} + try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } + catch (e) {} + try { return new ActiveXObject("Microsoft.XMLHTTP"); } + catch (e) {} + throw new Error("This browser does not support XMLHttpRequest."); + }; + + xhr = new XMLHttpRequest(); + + xhr.onreadystatechange = function() + { + try{ + // if((xhr.readyState == 3) || (xhr.readyState == 4)){ +// alert("Resp text: "+xhr.responseText + "

Resp XML: "+xhr.responseXML +"

Status: "+ xhr.status +"

status Text: "+ xhr.statusText); + + // } + if(xhr.readyState == 4) + { + + if(xhr.status == 200) { + + // document.ajax.dyn="Received:" + xhr.responseText; + var outcome=xhr.responseText; +// alert(xhr.responseText); + postCompletionCallback(outcome, visname); + } + else { + //alert("Error code " + xhr.status); + outcome="Error: "+xhr.responseText; + postCompletionCallback(outcome, visname); + } + } else { + // alert("state is:"+xhr.readyState+" status is"+xhr.status+ "response text is: "+xhr.responseText); + // alert("ready False"); + } + + }catch(e) { + } + }; + if (method=="POST"){ + xhr.open("POST", url, true); + xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + xhr.setRequestHeader("Content-length", params.length); + xhr.send(params); + } + else { + + if (params.length>0){ + url+='?'+params; + } + xhr.open("GET", url, true); + xhr.send(null); + } +} diff --git a/interactive-mining-madoap/madoap/src/static/ajax-loader.gif b/interactive-mining-madoap/madoap/src/static/ajax-loader.gif new file mode 100644 index 0000000..86f6b81 Binary files /dev/null and b/interactive-mining-madoap/madoap/src/static/ajax-loader.gif differ diff --git a/interactive-mining-madoap/madoap/src/static/comments.css b/interactive-mining-madoap/madoap/src/static/comments.css new file mode 100644 index 0000000..84ba49f --- /dev/null +++ b/interactive-mining-madoap/madoap/src/static/comments.css @@ -0,0 +1,37 @@ + +.extra { + + text-decoration:none; +} + + a span.extra {display: none; + text-decoration:none; + +} + + + a:hover span.extra { + text-decoration:none; + display: block; + width:130px; + position: absolute; + padding: 5px; + /*margin: 5px; */ + z-index: 10000; + color: #000000; + background: white; + font: 10px Verdana, sans-serif; + left:10px; + top:15px + } + + + + #term-vis { + padding:50px; +margin-left:auto; +margin-right:auto; +width:70%; +border:1px solid rgb(204, 204, 204); +text-align:center; + } \ No newline at end of file diff --git a/interactive-mining-madoap/madoap/src/static/database.db b/interactive-mining-madoap/madoap/src/static/database.db new file mode 100644 index 0000000..57780be Binary files /dev/null and b/interactive-mining-madoap/madoap/src/static/database.db differ diff --git a/interactive-mining-madoap/madoap/src/static/favicon.ico b/interactive-mining-madoap/madoap/src/static/favicon.ico new file mode 100644 index 0000000..7789bf7 Binary files /dev/null and b/interactive-mining-madoap/madoap/src/static/favicon.ico differ diff --git a/interactive-mining-madoap/madoap/src/static/fp7grants.csv b/interactive-mining-madoap/madoap/src/static/fp7grants.csv new file mode 100644 index 0000000..c4f85bf --- /dev/null +++ b/interactive-mining-madoap/madoap/src/static/fp7grants.csv @@ -0,0 +1,25536 @@ +275032 +322699 +268543 +263147 +227065 +600402 +263651 +306484 +334552 +322541 +244821 +293741 +624538 +288008 +314501 +291783 +227087 +631489 +244909 +331032 +321031 +609778 +208801 +201413 +272048 +611596 +276595 +200754 +267697 +284879 +221978 +247349 +253937 +322133 +609359 +308299 +259620 +329466 +255875 +255515 +268523 +296379 +606105 +245917 +237868 +230865 +340735 +239164 +610418 +277993 +222965 +315360 +280202 +233147 +311910 +216214 +316690 +282703 +304108 +247273 +318633 +252356 +310191 +246874 +266103 +261349 +317526 +242099 +606073 +244356 +611233 +326551 +604057 +624151 +298665 +293565 +623995 +630988 +283015 +220112 +316310 +268255 +339108 +611396 +299341 +218589 +239294 +325912 +253065 +225077 +618522 +268309 +220278 +222331 +328828 +339031 +277156 +215881 +232640 +254202 +327845 +336305 +246776 +625537 +288801 +231181 +625116 +231032 +205693 +234973 +338991 +213501 +336808 +200728 +213744 +221230 +605180 +254796 +611688 +632447 +272340 +269202 +604134 +216120 +232645 +305312 +261104 +201119 +218813 +201914 +275755 +259515 +609419 +291733 +220800 +325262 +278418 +224941 +331710 +632269 +248138 +252531 +602825 +288082 +269036 +337574 +261669 +302640 +303755 +289754 +218966 +224611 +237290 +323173 +242535 +291543 +222916 +200561 +234321 +253797 +278040 +287815 +211329 +266959 +909423 +293921 +267341 +288318 +627936 +326619 +618465 +244172 +330237 +217624 +270396 +276985 +230778 +279804 +321746 +327197 +319208 +252373 +623163 +219552 +611016 +220270 +239748 +615089 +268349 +235596 +286709 +249084 +606171 +216382 +236583 +317445 +231730 +264394 +230368 +254009 +269143 +330156 +265211 +236807 +221361 +208535 +315746 +625466 +604416 +274093 +265499 +237175 +247546 +247384 +327701 +272996 +279288 +285014 +200251 +320964 +265994 +276811 +316773 +242934 +296081 +330849 +303172 +298176 +211801 +266157 +290683 +321979 +264526 +245031 +258138 +318101 +606668 +270687 +244236 +214459 +210355 +331615 +203441 +283857 +226103 +624885 +625740 +306983 +233524 +275544 +307624 +624022 +222111 +255605 +224892 +316553 +300185 +219665 +340113 +280025 +252473 +304005 +333916 +229292 +279599 +323042 +214810 +302444 +226549 +298785 +268370 +309802 +267637 +223300 +245928 +267230 +298254 +266124 +327540 +220396 +301269 +293894 +341320 +237582 +290455 +263512 +310068 +243653 +282526 +290137 +288912 +231000 +614944 +219340 +282490 +207330 +618351 +315238 +279943 +258666 +253103 +609617 +284198 +212894 +325386 +284871 +295707 +305388 +326919 +615274 +220642 +253129 +602856 +260862 +268147 +317884 +268268 +280855 +284905 +254833 +295261 +627593 +226740 +304218 +305422 +334512 +605758 +612789 +622388 +304154 +288102 +293574 +609386 +627441 +269505 +263794 +226558 +219785 +602125 +247659 +310436 +609226 +315351 +600181 +619448 +200297 +230947 +265942 +911202 +216173 +334762 +259152 +261685 +309329 +626184 +327905 +268325 +277673 +213360 +230937 +610829 +609844 +337284 +283679 +293664 +299408 +335624 +627265 +265267 +258581 +619788 +286762 +611988 +334956 +220016 +324336 +298569 +609809 +262892 +257103 +283955 +247739 +251442 +215148 +214864 +213637 +278845 +627520 +314157 +301193 +295179 +256587 +221053 +294557 +309337 +331612 +626598 +212966 +220899 +237411 +269752 +233816 +311865 +610449 +296391 +305632 +329677 +610428 +298093 +256461 +628790 +252440 +319192 +232522 +227844 +620091 +247321 +217925 +316832 +245199 +234833 +293665 +282333 +230253 +266018 +602757 +228980 +285856 +213161 +213546 +215350 +227321 +290766 +341206 +274308 +255185 +624424 +291144 +284443 +265985 +268191 +299919 +233077 +201577 +221218 +247650 +246083 +224918 +218621 +278862 +328282 +294168 +201230 +226365 +321952 +623739 +618143 +326129 +229723 +218493 +307778 +331421 +236955 +253117 +220266 +251720 +312084 +265724 +235978 +262453 +272385 +331476 +238191 +319277 +231367 +274396 +224547 +244237 +625185 +620070 +275726 +609550 +285229 +909487 +212643 +291141 +262549 +230669 +603196 +631048 +244188 +612261 +233994 +258191 +623648 +277060 +301166 +299202 +228634 +607627 +268804 +330316 +267443 +260991 +298647 +315550 +622444 +291433 +602050 +244779 +336665 +306277 +295378 +618107 +241526 +298932 +326917 +218390 +233486 +336408 +334844 +244541 +615381 +303007 +259297 +318622 +621275 +341038 +211905 +330813 +220368 +307498 +336043 +237270 +254676 +316533 +247219 +286556 +339367 +279277 +316788 +618680 +256714 +322034 +604853 +269661 +288786 +239496 +232099 +299250 +605001 +252258 +324591 +285549 +251887 +242491 +630199 +204513 +264330 +257782 +261331 +231845 +226873 +327168 +609026 +256514 +616213 +201608 +294933 +291372 +618961 +622296 +241919 +212304 +290583 +320375 +326020 +276205 +631482 +268893 +270889 +223120 +323404 +228724 +250157 +320478 +252343 +236809 +248390 +256673 +212019 +329044 +600572 +309314 +254413 +300455 +238434 +274386 +263897 +270483 +304985 +600207 +215839 +328144 +214660 +617329 +262584 +260744 +247138 +240433 +338187 +614264 +257005 +256319 +227159 +626397 +331496 +250026 +329249 +311575 +211714 +236798 +607049 +283741 +618969 +248767 +238186 +602604 +314630 +335006 +243212 +211359 +255762 +287464 +235914 +608109 +213780 +243128 +241598 +267690 +257422 +631609 +232917 +626843 +213371 +223996 +341137 +222292 +247411 +215475 +615585 +330521 +266367 +229885 +235413 +337161 +231888 +615650 +254957 +303871 +623230 +249267 +618422 +312397 +285223 +287099 +236932 +613912 +261550 +252503 +631413 +9864 +311963 +628569 +311820 +288542 +221908 +296423 +608078 +302010 +624583 +273462 +286676 +276529 +256575 +315551 +611324 +223450 +261911 +331131 +302103 +605265 +605007 +307074 +244552 +249377 +222946 +287829 +339490 +262468 +293578 +318067 +605545 +278346 +603389 +619819 +268665 +619609 +307357 +314867 +300855 +600177 +269973 +607904 +604143 +278560 +223989 +338523 +631404 +297433 +272227 +623855 +629114 +625809 +241127 +291038 +295868 +622811 +311957 +220988 +215584 +266581 +608152 +338904 +280804 +318786 +287101 +268276 +276130 +909122 +312514 +606199 +335277 +276574 +212154 +629981 +232131 +618250 +248296 +219918 +322586 +204853 +300072 +290463 +100017 +285884 +305801 +240054 +330735 +328798 +247680 +283283 +600380 +279893 +270324 +302617 +245123 +235295 +231138 +288349 +263699 +322814 +272438 +310747 +611076 +300814 +322907 +321691 +231109 +230652 +304007 +330649 +608739 +320042 +229333 +257495 +282012 +250363 +276664 +269317 +235120 +626376 +602536 +287407 +276046 +308502 +627391 +201627 +317146 +297557 +256526 +233710 +279753 +235114 +627457 +616393 +227577 +619437 +225369 +329812 +254361 +244967 +302215 +279518 +629649 +273824 +257829 +322752 +243594 +222087 +271877 +605893 +306279 +245124 +257872 +610005 +618454 +261495 +334377 +220890 +259842 +327127 +332285 +335593 +237219 +316528 +218038 +318921 +300532 +630955 +205027 +252888 +293402 +619198 +282656 +303228 +632278 +616744 +234009 +223951 +269586 +326865 +220407 +265987 +310187 +317707 +312453 +295675 +235732 +302834 +219782 +268281 +243322 +251506 +285030 +240984 +268446 +253047 +326494 +627027 +241904 +275610 +307964 +620233 +214566 +233083 +254495 +290974 +230698 +294627 +606331 +235226 +328985 +253929 +323439 +600397 +305033 +320499 +268413 +271895 +611964 +236411 +249225 +219200 +313202 +224557 +217141 +321773 +311490 +336659 +230980 +327684 +286830 +311025 +629341 +213321 +312454 +285410 +276921 +912100 +244067 +253545 +234299 +329601 +200247 +601616 +308961 +269484 +322424 +248867 +275313 +222097 +213569 +256810 +249302 +224761 +327046 +302303 +244959 +248676 +331824 +214089 +320917 +200820 +615709 +613971 +275261 +224356 +264737 +274339 +331255 +288980 +243923 +229335 +229611 +326604 +266976 +336054 +303293 +612714 +605236 +290023 +242112 +617351 +293753 +329570 +223615 +272242 +285912 +608571 +622645 +612704 +612774 +607691 +265471 +232337 +629076 +249310 +330284 +220199 +310700 +228449 +235129 +328862 +316010 +613609 +288445 +303343 +310584 +307544 +248107 +293978 +239540 +301002 +630852 +256964 +305374 +315025 +249931 +231830 +618892 +232812 +248458 +298352 +609750 +295189 +279548 +600788 +282945 +627475 +281749 +317110 +610018 +317761 +274533 +299818 +257051 +227457 +333948 +268460 +295486 +248997 +236950 +315065 +234182 +608849 +605889 +604500 +291592 +252994 +281245 +265128 +606644 +252091 +262266 +244092 +331680 +288021 +204514 +273984 +277815 +300544 +218744 +285635 +285683 +265582 +622974 +268843 +287896 +282767 +270686 +258178 +279237 +309349 +335288 +256376 +243583 +314299 +626808 +615456 +260515 +262348 +260600 +332028 +316125 +315208 +9764 +240299 +265898 +289760 +303620 +216287 +317762 +607093 +336019 +246124 +324304 +211528 +267523 +628720 +235411 +215747 +276860 +239201 +267213 +276416 +298182 +294240 +274827 +304209 +247536 +602699 +230805 +284842 +241277 +220596 +216338 +328529 +301782 +322942 +336468 +299048 +610650 +610902 +330064 +253911 +622280 +315262 +322603 +204028 +228430 +227138 +230847 +306247 +321716 +304025 +228339 +630654 +328959 +312184 +273872 +267356 +241622 +222219 +239430 +281640 +330424 +338510 +236045 +288356 +251646 +321639 +265874 +236454 +607178 +257184 +299848 +311725 +297550 +295203 +214832 +247978 +603518 +244383 +286489 +294012 +307937 +248687 +215244 +252906 +627682 +610484 +291094 +247504 +606416 +284236 +280064 +302931 +270192 +270561 +241132 +603705 +221073 +328713 +629218 +224776 +327906 +261177 +609783 +626272 +275571 +603959 +262355 +268906 +239421 +334336 +243118 +330422 +337077 +253368 +257511 +327630 +221068 +262009 +293461 +286060 +9948 +336130 +334090 +269150 +247178 +619462 +280141 +614839 +281720 +300901 +308429 +247365 +320733 +248858 +612385 +287463 +228273 +322842 +221149 +246858 +341380 +230355 +336839 +257372 +303096 +217967 +200267 +221571 +273711 +228825 +617129 +629229 +217237 +220024 +605658 +251600 +607911 +236511 +274987 +329239 +318985 +203929 +281719 +629625 +274794 +606734 +217931 +301463 +240111 +216165 +272129 +247820 +316751 +294517 +282700 +293601 +248873 +615613 +230788 +321992 +257513 +274342 +303526 +252389 +259370 +282507 +305279 +287728 +275286 +613996 +221054 +324607 +641577 +244250 +294166 +227003 +609118 +242446 +605286 +282430 +293562 +230846 +328680 +226995 +626904 +316614 +248032 +221618 +251798 +606348 +321622 +249008 +315285 +632807 +257284 +609666 +307856 +285688 +615596 +317888 +232662 +265171 +287351 +335928 +244093 +234041 +339019 +339208 +305868 +622415 +328530 +631466 +200288 +224348 +623386 +214902 +289157 +294051 +277936 +250076 +318928 +330385 +211284 +269151 +267614 +235545 +213250 +282910 +267251 +224756 +221464 +304104 +618157 +276107 +231855 +338846 +201525 +286038 +236227 +244371 +294152 +314255 +235122 +312025 +284100 +278231 +328518 +268352 +227639 +322986 +325358 +291147 +322365 +293886 +295137 +262444 +233772 +323395 +631585 +260884 +605605 +215607 +262612 +291414 +247170 +282750 +256355 +205175 +243695 +612675 +216405 +226470 +274350 +201640 +214787 +282992 +232127 +219872 +246749 +263441 +265881 +200269 +258238 +606169 +339953 +248326 +281605 +219890 +250244 +335086 +216480 +287458 +326681 +308467 +259640 +254512 +265702 +271843 +611005 +281335 +211796 +223388 +338205 +318216 +627769 +254174 +233366 +291132 +269921 +286013 +315146 +327987 +632480 +323412 +276037 +309831 +607686 +282748 +327207 +909289 +625297 +623281 +224044 +9912 +220732 +242093 +312057 +618930 +221545 +609127 +200911 +251211 +211863 +8488 +218764 +236299 +623713 +266519 +302127 +272517 +232250 +303714 +318873 +606865 +203194 +309453 +222400 +625727 +236664 +323458 +230347 +336718 +305555 +607394 +271574 +260564 +265661 +280535 +273608 +255782 +236618 +220299 +274566 +224942 +282047 +293719 +228304 +334000 +211597 +210223 +616333 +611693 +326705 +243768 +218340 +247097 +266531 +602442 +311460 +208589 +243273 +607373 +306928 +317451 +241865 +625356 +606879 +202059 +295458 +223534 +251464 +254649 +238148 +244060 +284927 +230871 +277729 +274612 +623630 +616449 +320079 +294076 +912487 +607131 +321334 +229802 +303931 +217061 +282621 +246543 +318671 +608231 +251385 +248262 +322493 +622187 +317959 +249835 +230605 +276704 +267142 +620120 +339941 +632035 +310023 +320506 +226310 +268168 +289032 +305428 +268399 +314971 +267160 +223868 +266249 +618140 +233859 +276951 +212830 +607433 +264879 +299648 +329084 +273304 +240928 +261468 +249394 +225165 +284663 +621403 +221623 +299346 +606363 +334525 +321649 +233655 +237599 +269418 +201587 +201169 +325268 +303534 +301599 +230714 +295513 +327017 +302657 +235429 +298594 +260316 +631716 +249681 +608142 +629378 +316722 +224848 +230830 +626740 +224565 +283871 +266465 +208132 +331419 +236845 +262155 +230775 +257868 +255128 +268395 +625521 +607044 +220084 +252980 +602771 +244944 +321921 +213424 +230313 +248119 +329316 +234989 +266946 +203675 +601456 +300034 +287787 +269020 +235744 +236653 +270589 +285842 +621176 +302997 +913590 +250605 +234338 +218225 +334347 +269135 +322210 +286030 +9763 +281891 +272999 +908507 +628019 +311839 +310763 +286052 +310627 +623168 +631783 +258084 +220798 +298303 +249210 +203288 +269064 +251534 +244384 +237391 +248809 +235229 +297524 +294757 +288309 +290336 +340561 +283626 +323656 +276084 +608682 +619556 +280387 +328485 +216259 +298405 +614154 +206201 +230287 +246924 +206726 +628338 +293762 +314363 +320130 +217206 +320004 +283496 +298210 +8625 +266107 +617891 +223410 +221146 +221709 +210362 +605254 +237884 +249388 +216089 +605788 +236606 +278872 +328215 +622117 +312602 +610637 +218789 +286576 +223681 +316391 +300002 +337797 +281739 +618788 +229266 +202859 +627854 +211868 +262874 +302600 +262428 +614879 +624864 +215157 +212367 +605506 +294646 +330282 +910715 +206947 +298957 +340733 +302060 +276889 +272874 +225167 +303799 +630662 +239527 +295555 +304980 +245034 +250098 +309636 +252926 +293900 +294325 +211407 +611695 +278011 +299677 +223034 +294068 +619435 +298186 +267055 +223487 +230388 +232391 +278798 +286560 +264125 +224521 +602051 +282534 +333727 +299860 +251978 +231042 +254449 +244365 +605019 +289150 +221595 +213628 +221100 +275781 +334564 +319092 +605616 +321788 +295354 +335891 +329100 +284801 +624798 +317578 +288828 +260393 +316906 +627788 +260124 +613520 +287450 +205289 +295293 +223610 +913478 +243689 +254607 +309558 +205896 +229761 +283950 +617336 +624160 +255413 +617670 +289610 +311704 +240980 +321381 +261224 +619241 +314861 +284595 +215884 +220006 +212073 +609698 +291497 +331373 +326442 +605779 +295180 +335373 +298420 +286174 +290647 +211307 +212334 +269256 +621975 +237089 +624339 +219821 +612640 +256326 +294212 +602273 +281803 +318132 +298298 +218960 +235147 +623338 +241098 +221332 +256554 +246203 +316205 +240335 +304202 +331190 +328112 +303907 +321319 +201766 +245461 +339786 +234400 +624877 +235649 +273006 +602170 +274448 +294851 +316300 +248116 +294932 +288692 +285671 +269853 +235702 +274151 +232151 +256360 +300077 +242167 +233169 +220146 +300137 +336948 +261351 +303946 +305123 +235457 +298470 +256363 +318804 +261520 +323977 +339993 +217077 +277140 +261387 +238201 +284419 +231200 +268244 +274737 +310649 +603043 +323323 +204979 +611337 +265346 +311751 +251226 +298741 +224769 +330886 +279363 +255604 +313623 +332138 +233843 +221026 +626267 +328085 +270577 +229700 +608604 +309706 +246932 +232257 +249274 +230224 +629202 +262156 +303024 +275524 +297640 +293438 +277741 +610582 +242295 +322377 +264089 +605838 +217266 +306754 +305259 +261682 +243791 +609542 +274569 +273527 +247500 +330797 +280632 +324214 +287595 +120016 +293663 +201601 +208948 +261411 +335023 +272633 +301897 +613745 +331291 +200526 +606096 +222680 +228673 +242204 +628405 +224866 +236064 +285578 +260477 +340889 +617233 +288833 +283336 +312792 +202844 +260885 +233024 +605980 +311231 +299571 +220866 +247506 +248240 +254371 +314580 +617970 +218691 +333801 +625581 +257263 +228933 +319024 +224142 +321302 +220754 +609850 +618697 +609784 +614424 +224286 +286408 +312842 +251477 +319114 +632814 +257230 +253905 +627639 +221840 +332422 +285181 +340442 +241176 +253507 +221428 +294428 +616268 +208237 +324564 +285854 +605465 +612614 +624803 +331366 +274769 +303166 +255152 +213457 +299653 +241336 +622874 +611068 +221713 +626495 +320708 +252417 +280516 +301077 +613411 +262873 +281287 +274379 +201333 +260747 +608417 +336189 +235380 +234961 +323924 +262312 +241479 +217911 +231161 +335120 +257623 +243603 +253332 +340896 +230932 +246550 +282816 +300984 +612345 +294790 +256769 +327538 +298295 +278025 +265459 +311318 +305697 +249305 +214909 +331428 +247492 +305178 +235176 +303180 +615640 +230943 +263215 +307836 +258406 +277461 +319456 +284437 +297436 +229694 +329018 +261213 +232908 +239422 +275325 +266770 +234303 +267634 +312827 +600663 +629168 +277015 +627253 +328935 +318082 +338954 +333939 +220799 +328500 +625471 +222824 +627767 +260499 +618763 +257528 +283145 +287106 +302388 +279977 +308830 +295825 +912054 +627784 +272831 +205927 +290975 +275095 +272280 +237417 +229294 +607290 +224067 +286370 +609190 +336536 +616861 +330771 +291214 +211911 +608082 +255881 +308087 +253694 +263406 +300302 +236501 +202652 +308793 +303452 +235860 +286955 +206300 +611795 +288274 +268264 +606716 +331883 +331350 +295562 +313200 +318980 +284306 +323872 +210806 +319970 +230796 +230268 +610411 +262448 +628197 +301729 +316338 +210356 +316608 +253541 +310067 +300686 +239019 +623527 +212196 +259627 +339678 +220135 +241711 +631633 +240076 +231082 +628604 +340081 +318602 +286145 +615638 +606795 +271141 +260797 +616797 +286858 +339233 +286487 +240864 +312511 +263416 +236059 +341360 +243312 +605389 +246589 +322206 +257626 +230043 +241481 +259110 +219781 +606844 +313978 +323727 +282460 +330150 +230146 +252937 +300245 +249933 +624886 +311673 +265992 +254183 +631044 +329960 +317746 +217031 +603498 +334577 +330444 +247708 +299441 +224498 +620262 +321097 +230903 +605338 +221989 +259303 +211055 +327423 +608030 +323147 +327075 +625710 +608332 +251833 +618774 +276778 +333922 +236663 +339390 +291602 +268384 +315404 +246738 +309070 +323970 +609380 +287576 +289829 +212246 +286464 +326202 +273420 +612759 +303565 +266054 +330915 +340200 +260887 +285541 +210037 +618807 +303088 +272648 +231993 +212545 +612639 +316929 +331610 +281096 +320493 +309701 +200835 +214006 +266804 +235625 +321372 +278807 +622182 +321742 +224366 +328466 +290732 +302819 +624619 +209243 +220253 +619992 +323105 +244104 +223994 +214560 +287583 +334404 +324443 +626708 +336493 +301419 +222989 +298698 +242286 +274574 +255000 +295970 +217725 +630059 +217889 +278407 +230220 +294094 +612652 +248351 +222540 +232190 +247547 +217787 +295272 +270219 +304062 +213708 +219811 +251494 +622289 +256798 +201032 +216006 +602906 +254575 +233715 +335400 +212921 +211605 +608746 +281722 +238292 +329845 +296701 +334069 +249704 +263751 +334566 +249018 +274223 +215761 +220386 +329969 +239172 +294823 +295311 +311825 +8507 +300826 +303912 +240970 +628303 +316082 +622134 +251832 +606496 +327225 +232637 +327608 +208516 +317669 +285052 +286093 +246784 +245026 +285069 +285203 +302504 +329416 +279611 +256599 +236346 +274497 +339555 +290080 +245262 +287820 +283214 +276401 +224831 +286693 +274729 +626214 +336633 +290077 +335491 +612583 +300235 +300184 +220209 +288267 +631793 +290038 +325993 +226536 +322656 +274999 +298637 +211778 +259639 +242630 +269907 +610713 +277033 +324627 +315633 +293855 +625795 +296257 +232082 +617266 +310890 +260372 +265325 +338251 +220243 +287818 +309916 +216100 +216949 +609817 +611832 +257129 +303990 +908448 +330183 +254835 +265505 +302546 +335473 +325368 +613303 +220252 +232176 +280827 +253004 +299789 +234201 +239469 +627761 +217862 +262937 +309555 +274766 +297876 +248835 +337333 +248505 +259204 +259092 +223498 +320300 +235499 +216563 +630833 +280153 +259352 +299137 +321710 +239126 +307727 +243950 +328233 +622786 +254380 +260964 +295213 +298546 +248894 +608770 +323113 +249956 +311943 +258501 +269565 +238639 +641553 +237280 +251515 +309993 +257178 +281641 +285526 +281265 +621233 +309767 +269169 +324391 +291429 +301029 +317614 +286200 +333843 +215605 +293800 +236567 +8487 +226943 +327060 +267188 +231323 +256872 +289723 +262207 +328351 +243045 +321696 +300990 +220731 +304160 +281047 +249483 +616675 +256295 +232612 +626205 +8434 +235487 +201889 +315967 +606998 +272335 +323453 +253629 +627124 +294144 +251186 +283077 +309041 +615984 +247060 +218817 +200632 +218783 +238562 +290563 +206653 +235988 +282310 +260336 +624997 +269304 +233481 +318981 +339198 +301693 +336467 +274177 +611715 +621193 +248421 +265727 +323841 +260101 +321602 +265856 +314958 +230958 +228730 +910861 +294709 +322073 +318123 +602714 +239174 +248749 +231997 +278054 +908423 +232397 +284123 +247878 +631982 +295373 +285399 +211982 +269362 +626734 +316531 +316120 +321849 +604647 +610359 +219218 +218453 +334261 +619234 +336792 +290399 +203685 +267567 +328796 +211484 +230684 +312746 +256471 +268327 +263916 +611391 +217297 +236347 +290966 +221182 +260087 +625137 +321268 +273467 +600471 +316512 +221272 +299738 +252784 +233683 +247683 +236887 +314201 +628803 +287074 +281063 +231807 +239330 +240167 +285443 +615922 +240989 +228585 +308473 +220532 +250316 +221254 +233910 +224619 +268156 +228953 +291864 +286161 +226167 +236681 +322038 +238821 +295302 +295362 +610675 +229336 +328454 +310973 +311536 +319964 +258114 +622830 +217014 +285164 +277984 +248189 +316097 +309944 +314352 +273104 +327940 +295025 +278310 +265308 +290981 +321554 +262693 +606806 +239212 +266268 +312906 +215479 +303409 +607611 +283754 +205425 +256506 +608491 +222883 +206711 +280860 +311552 +236073 +265740 +219376 +290770 +303484 +317859 +314407 +603519 +236670 +609780 +318911 +217877 +220566 +334300 +201681 +627227 +606084 +269908 +286603 +273068 +234990 +317562 +632458 +221097 +249119 +623638 +326002 +241566 +297881 +314441 +268721 +257039 +340915 +248693 +300083 +306240 +329540 +325974 +235142 +617377 +253708 +227299 +258613 +214706 +306292 +265910 +237297 +625238 +316356 +264103 +318787 +241839 +312806 +258782 +254559 +226880 +279578 +632468 +314024 +273884 +256488 +245572 +201762 +256305 +315565 +213903 +265138 +255363 +316422 +311682 +327990 +302123 +275747 +286854 +277080 +282687 +618503 +627240 +247868 +305629 +258697 +300109 +251930 +256885 +215923 +618105 +303772 +236168 +270644 +609704 +328611 +217920 +303344 +602243 +238679 +318909 +305444 +249809 +605203 +612425 +338763 +229907 +224775 +294311 +294302 +293781 +329837 +270749 +324594 +242209 +267216 +270535 +221158 +604036 +211429 +266970 +297499 +607051 +611967 +229034 +213558 +269297 +120224 +236426 +328822 +285059 +909960 +285954 +247462 +223979 +293860 +331450 +618104 +261554 +629661 +306661 +338528 +604325 +280991 +221066 +303052 +255559 +309729 +328370 +623876 +617376 +281760 +228855 +252374 +326794 +229553 +312582 +311926 +256834 +630069 +262101 +256527 +303262 +296347 +203247 +200198 +603906 +249431 +239288 +247706 +262907 +306708 +909375 +236068 +284433 +214340 +226874 +274571 +268132 +255129 +207057 +618399 +631827 +233376 +224888 +281225 +294191 +298361 +291300 +618907 +235979 +221366 +252139 +330004 +609024 +607720 +261123 +282891 +257431 +623691 +316861 +250278 +269266 +258616 +321726 +224594 +609082 +227030 +629740 +267107 +289842 +220874 +217514 +265663 +336331 +238409 +335672 +329121 +264509 +221827 +267522 +217226 +263318 +286386 +339495 +252239 +228506 +244954 +240809 +609528 +328008 +251763 +306201 +607380 +604279 +226967 +226655 +221081 +324370 +285266 +329903 +339140 +224350 +221482 +612453 +251685 +211888 +287581 +247450 +222145 +338602 +257580 +258658 +298595 +295550 +252475 +610472 +234787 +241073 +304978 +606711 +302609 +271814 +606395 +606090 +282330 +276977 +218742 +252260 +236758 +302077 +263782 +249512 +618708 +339072 +326083 +235955 +330519 +203123 +626341 +317671 +215483 +628428 +611819 +274184 +282915 +327293 +338179 +288442 +273377 +609251 +219301 +275790 +318625 +259435 +266529 +255149 +266182 +235454 +611737 +602919 +247999 +602139 +265831 +328673 +263273 +284743 +606983 +218068 +613776 +237569 +312458 +266592 +317127 +252075 +626501 +247596 +225374 +627645 +257448 +295214 +322328 +276776 +232971 +282952 +602121 +237267 +328867 +265850 +248772 +618407 +278722 +307934 +626728 +217810 +617849 +220044 +209480 +9728 +224390 +295262 +322288 +255394 +608728 +236111 +236290 +293683 +224882 +334417 +261517 +237090 +626129 +274181 +213219 +328961 +265309 +302606 +299405 +336564 +318665 +632156 +297854 +267651 +618149 +260162 +219818 +235205 +245565 +249295 +304912 +235167 +233925 +211971 +206198 +237222 +329652 +305061 +253912 +610692 +248629 +284989 +339312 +335646 +616186 +314461 +245030 +266647 +249147 +334948 +251864 +288273 +256449 +322851 +314596 +257909 +629435 +309497 +600700 +300971 +217838 +235130 +267149 +303849 +257856 +251598 +325613 +268296 +303927 +291531 +279867 +204554 +605405 +327585 +608702 +285176 +606817 +327151 +266039 +270332 +256721 +618363 +291522 +257019 +331004 +604063 +259133 +622630 +285571 +256522 +632263 +294142 +237203 +618122 +281851 +285166 +328525 +321951 +604884 +290456 +318693 +241446 +268245 +333628 +606052 +276301 +323526 +213411 +295167 +217227 +292281 +230936 +230995 +329071 +288827 +278720 +624362 +322229 +245238 +318398 +298150 +246981 +332317 +287551 +317297 +316339 +269207 +245550 +222125 +237673 +275561 +295190 +313397 +299756 +242058 +243529 +290050 +606575 +303415 +605302 +323464 +606950 +255003 +326802 +609806 +244088 +627743 +303784 +329776 +239533 +243857 +241577 +275135 +624461 +246310 +323035 +228144 +232562 +308496 +246761 +234236 +234845 +234088 +266722 +332395 +254779 +276837 +304086 +241918 +305626 +257385 +277183 +284487 +335814 +605485 +288147 +236723 +212399 +220983 +238132 +630714 +278864 +605298 +237296 +340177 +254658 +286545 +632554 +326003 +224428 +224621 +227764 +222518 +322100 +223711 +333737 +288878 +265397 +258934 +218761 +244772 +261063 +244703 +256551 +241070 +253524 +265733 +632828 +276961 +242993 +308376 +276807 +227571 +328605 +256959 +322645 +281598 +605181 +291877 +607493 +239959 +231964 +313502 +303699 +217878 +227522 +232458 +280043 +280070 +261565 +201350 +260070 +260414 +613308 +298969 +323470 +331436 +269073 +296001 +235241 +212326 +255089 +306622 +237266 +253043 +338804 +614922 +233473 +611281 +224779 +303972 +230863 +258378 +318556 +258053 +609304 +323520 +611125 +629517 +276958 +626190 +228726 +306783 +215756 +221701 +315637 +223713 +221205 +223888 +332081 +281296 +228046 +262212 +337581 +607480 +243607 +631431 +221236 +266603 +209394 +222286 +214653 +286334 +322406 +641453 +606962 +253594 +281348 +274057 +307111 +222303 +240113 +228595 +281043 +610476 +276759 +255670 +316555 +223277 +222487 +9687 +332297 +224226 +627114 +231204 +253783 +618847 +605067 +219273 +337573 +235010 +303029 +221072 +326939 +302221 +238700 +302939 +624888 +331463 +268357 +280909 +247283 +247787 +334437 +268049 +605132 +604003 +299852 +604764 +324510 +239850 +623747 +303742 +304179 +287421 +617627 +302297 +303891 +290901 +285624 +603722 +310208 +331232 +230817 +223238 +334496 +610874 +285820 +219611 +322692 +284461 +225663 +296687 +226373 +229861 +622362 +627200 +235907 +244310 +322151 +330055 +289240 +321700 +316564 +200179 +218026 +611383 +628892 +302489 +328397 +913076 +280566 +279931 +340931 +623536 +261623 +239252 +334323 +298839 +631569 +210934 +224402 +212132 +607930 +217397 +203143 +325343 +220150 +216339 +313290 +213153 +274541 +600927 +611570 +230515 +631280 +330240 +295355 +606901 +238607 +235422 +262673 +216886 +271788 +317534 +252407 +333937 +624981 +253403 +299217 +280424 +211804 +233469 +228394 +249640 +209214 +623932 +261512 +286697 +280145 +215327 +323040 +297391 +287062 +306337 +629459 +257790 +283501 +299356 +323209 +254694 +215036 +214371 +262943 +305343 +613697 +623456 +252985 +331812 +238111 +321149 +332226 +244314 +306478 +294397 +302295 +224631 +248577 +258212 +211338 +229183 +335431 +327463 +213436 +256552 +318932 +298060 +257894 +314190 +308378 +295053 +612659 +266044 +314671 +286354 +258023 +311858 +286583 +272186 +299320 +331158 +251837 +211590 +329968 +246102 +276241 +222267 +339899 +313180 +267696 +611165 +299027 +236417 +274381 +260432 +329183 +268800 +224864 +282510 +299195 +230267 +284152 +311532 +238802 +229597 +273631 +339647 +278705 +603029 +224327 +312567 +277172 +224784 +220002 +222204 +245438 +621627 +604920 +306933 +209267 +204999 +256499 +327977 +256571 +628818 +296448 +246881 +308991 +266992 +277927 +238646 +226285 +222503 +253995 +268328 +334563 +274389 +227716 +218065 +289461 +911689 +278106 +280565 +318109 +237309 +257784 +294809 +257414 +254577 +611019 +330840 +288409 +255378 +313146 +246535 +306845 +609188 +288705 +612615 +295092 +221656 +631775 +323514 +230331 +625276 +601040 +236470 +234306 +232554 +229660 +268670 +303814 +265286 +260290 +912652 +252711 +220913 +334829 +252568 +312147 +329870 +301336 +606119 +255109 +214025 +227010 +331555 +312885 +617142 +217783 +311815 +622087 +227224 +251132 +620180 +622744 +256328 +311965 +609223 +267146 +266271 +255082 +9833 +222424 +310177 +291442 +294249 +328763 +263165 +317879 +219528 +325978 +310970 +255806 +217384 +286175 +290914 +265280 +218575 +610990 +218565 +608985 +220608 +613420 +254402 +243211 +268263 +329024 +317871 +209842 +283484 +624974 +617888 +289782 +322050 +268537 +268381 +232478 +304225 +290694 +230920 +323687 +267104 +252957 +334502 +282775 +306595 +230318 +316882 +310857 +220292 +241900 +294570 +239834 +301155 +269140 +277844 +249519 +334028 +331813 +334840 +311819 +234104 +270683 +212533 +215560 +604656 +327778 +223488 +295176 +201461 +607626 +289347 +302344 +284395 +231101 +222881 +265368 +248410 +211753 +294278 +233919 +270601 +339691 +244963 +223126 +211048 +626504 +328772 +315282 +298401 +235563 +316289 +630735 +622815 +209789 +239412 +273575 +285839 +322820 +312883 +275336 +252665 +218000 +300983 +221689 +211757 +330446 +284486 +294016 +273108 +277087 +611948 +266530 +294264 +323384 +329465 +253883 +281691 +206480 +609693 +312687 +261330 +256452 +254238 +253085 +295803 +225327 +281600 +262286 +251686 +253678 +259033 +273235 +621282 +221980 +224832 +316758 +293707 +316518 +219996 +287444 +623725 +269276 +335724 +329091 +214705 +290428 +233815 +228587 +299936 +266296 +200481 +631578 +614020 +605454 +280756 +232974 +629425 +273572 +256821 +316959 +616563 +339754 +279632 +331095 +321140 +254128 +251426 +230786 +302428 +246252 +309301 +616047 +297511 +216634 +242319 +259061 +220390 +607087 +280676 +614623 +221916 +632604 +257262 +328319 +265578 +256647 +211345 +210949 +299687 +232603 +282122 +608422 +263042 +254503 +625258 +323052 +313188 +305694 +242061 +288698 +293482 +625364 +281910 +261095 +214227 +629015 +276077 +260102 +223532 +627651 +260661 +298543 +287069 +268433 +266632 +613551 +316191 +614087 +340534 +602167 +214668 +215010 +258348 +224205 +236322 +318926 +606662 +226482 +627489 +308336 +213178 +216134 +253096 +271765 +258463 +316975 +268536 +247265 +265439 +239256 +240672 +242729 +617198 +626659 +254671 +267426 +312297 +322947 +235375 +214814 +600716 +224287 +294160 +248290 +609305 +275577 +249293 +307707 +611366 +297849 +275396 +909658 +236738 +619463 +224014 +313454 +211534 +216668 +224855 +242084 +613937 +287481 +306719 +298562 +222257 +235322 +253978 +301806 +227551 +308074 +613532 +624890 +306810 +211940 +243261 +609710 +274433 +234239 +623135 +218164 +631269 +285120 +9894 +294037 +327533 +243639 +263747 +261873 +252862 +218237 +336679 +605207 +268388 +273735 +256511 +605436 +254339 +255669 +230959 +244485 +223832 +613368 +236093 +329622 +288219 +235123 +302157 +302251 +321217 +262623 +242257 +247010 +611458 +275683 +264633 +254533 +235157 +286284 +282794 +235623 +624854 +258749 +285948 +287423 +227127 +608931 +225383 +294299 +909106 +273381 +236208 +289007 +274748 +613170 +273994 +221734 +277071 +309832 +626320 +220424 +329169 +224582 +277801 +224757 +245044 +269037 +251357 +330249 +302854 +318388 +235419 +249306 +623806 +628912 +265572 +278348 +246513 +303750 +320812 +253483 +287954 +246969 +228743 +329298 +328977 +244510 +258837 +204486 +229025 +216312 +629706 +327376 +331675 +261693 +293818 +327367 +201714 +311788 +287509 +619177 +307793 +607000 +288150 +330621 +219860 +252592 +301884 +247549 +625058 +305385 +326293 +219398 +227906 +238366 +300723 +249205 +303674 +301793 +621194 +300071 +237454 +275298 +256694 +220147 +211250 +211723 +257154 +268058 +235886 +218433 +330069 +289316 +227525 +233992 +283963 +295917 +284996 +606869 +295138 +614966 +308392 +254106 +627049 +213442 +316354 +256398 +330003 +314061 +280915 +284877 +223935 +283707 +287652 +623380 +230913 +253055 +600725 +616072 +248919 +226927 +333918 +246603 +247078 +230836 +313987 +249169 +214602 +200613 +341096 +265610 +224335 +312249 +303727 +223932 +320971 +264759 +201102 +289081 +611433 +289346 +268596 +333749 +216446 +619137 +248765 +613581 +272914 +627575 +230328 +624879 +327263 +316732 +629413 +298697 +615414 +618223 +219483 +240210 +303820 +314068 +269267 +248804 +327934 +256390 +909605 +285275 +331734 +301433 +616510 +296676 +316223 +609488 +234782 +218953 +284941 +215820 +238382 +252856 +328913 +269142 +229673 +260623 +318521 +235328 +268294 +298927 +284456 +226713 +300969 +600847 +255009 +289196 +296549 +264738 +278483 +612230 +244102 +641539 +268397 +608133 +622414 +330657 +240743 +280773 +228839 +244468 +221451 +268671 +240983 +240453 +337221 +618183 +201214 +246655 +606847 +271784 +241879 +300536 +331197 +260988 +601958 +294556 +627862 +617840 +221317 +230740 +299864 +237549 +247299 +240895 +235394 +304936 +265754 +232116 +340260 +250297 +322280 +229685 +218245 +252478 +239270 +256716 +289016 +230561 +222288 +9758 +214599 +604521 +286864 +290246 +274060 +626229 +306157 +269134 +246772 +202283 +262254 +229100 +317826 +291870 +276155 +628812 +607567 +627846 +606878 +264362 +293832 +603662 +209044 +307447 +216176 +224353 +248920 +302989 +265957 +268235 +214898 +318202 +287320 +320975 +341340 +244493 +294443 +247049 +293579 +271813 +259267 +247732 +252355 +254143 +317674 +295276 +602889 +246545 +311310 +303525 +329134 +628300 +274730 +311736 +256299 +611073 +255503 +267128 +618541 +621245 +324491 +606061 +246565 +258647 +217993 +271886 +225314 +294333 +252786 +219577 +311000 +315029 +628003 +299063 +631163 +616050 +230143 +221217 +210908 +335529 +612689 +299504 +275867 +300162 +277115 +224383 +253980 +248175 +262837 +207632 +213320 +221507 +306513 +908108 +268690 +607150 +317681 +295660 +217148 +340077 +239272 +285050 +313980 +287929 +260392 +279962 +205641 +255019 +283867 +295241 +310948 +606488 +319969 +604999 +236478 +280140 +228662 +627113 +213514 +298905 +301460 +220336 +239393 +259183 +629874 +224812 +233718 +242564 +261633 +612069 +327681 +317742 +334828 +312330 +218280 +618294 +247757 +301564 +255071 +263523 +244273 +608892 +224272 +120218 +320723 +260853 +268851 +257743 +248464 +316657 +340172 +251834 +211684 +282896 +242361 +216256 +340602 +229585 +617951 +326693 +608363 +600415 +320596 +293557 +324219 +262176 +627187 +247870 +909880 +605583 +286798 +262411 +287455 +229208 +248128 +266538 +314307 +626429 +303716 +260242 +326499 +603942 +238710 +230126 +275848 +610576 +239868 +239490 +337011 +324518 +623872 +230833 +294004 +618368 +272920 +641489 +316087 +310325 +336167 +8536 +328404 +310809 +619267 +223797 +280127 +268225 +321331 +312778 +306772 +220813 +246686 +324386 +265576 +310748 +618769 +261098 +622662 +609864 +340430 +288235 +330215 +302562 +247373 +230976 +252792 +276922 +333990 +273391 +283974 +211604 +223877 +242458 +282948 +315664 +291389 +339571 +265154 +304994 +631693 +236526 +299401 +275851 +334039 +249872 +330674 +256265 +259972 +296322 +622730 +611153 +212919 +625119 +285952 +605734 +241506 +323454 +602299 +631541 +329718 +277849 +622632 +216372 +276868 +618003 +303605 +302520 +254442 +316604 +248514 +332445 +281996 +211738 +213910 +334068 +222948 +911767 +261389 +331893 +249204 +243283 +318452 +618114 +616434 +338680 +618731 +909453 +278998 +310659 +267853 +224748 +321983 +615075 +212885 +224213 +230596 +313347 +324617 +226246 +341009 +632167 +329083 +307940 +632456 +237483 +295484 +251650 +331647 +265780 +281847 +334312 +247772 +278389 +315305 +287460 +213107 +289374 +309788 +632237 +233764 +626291 +315271 +226694 +234000 +269051 +268338 +294079 +313172 +278248 +300281 +321066 +238356 +327995 +263962 +285045 +625996 +627787 +328962 +619795 +284216 +218940 +603557 +224432 +268858 +260358 +322261 +222582 +618534 +321888 +340506 +231108 +316210 +605748 +605987 +305937 +610058 +624904 +249894 +631304 +208111 +203077 +322070 +217296 +275891 +618375 +318874 +204986 +298285 +211700 +277883 +243827 +200732 +228604 +625738 +218693 +275480 +218935 +274384 +611188 +307334 +277098 +236264 +217818 +239303 +251982 +227781 +286995 +230554 +246839 +249830 +253370 +332265 +622905 +286213 +622320 +299300 +234418 +629867 +271815 +301027 +301796 +259385 +269279 +304214 +285782 +609707 +223692 +329131 +302782 +244828 +316618 +631128 +294298 +610454 +610927 +227628 +306733 +608087 +610797 +254965 +293456 +289521 +217872 +316216 +263277 +286362 +245856 +328563 +231396 +264506 +225134 +247893 +318247 +303864 +610640 +260676 +299400 +600377 +277963 +232349 +302236 +234861 +260383 +293975 +909457 +330806 +207350 +236430 +238678 +333959 +237955 +313271 +247033 +283012 +602262 +341400 +303722 +230946 +260065 +259272 +224847 +605809 +625870 +206080 +316094 +286220 +314454 +270692 +239408 +221637 +277749 +281748 +260043 +608512 +218609 +261952 +302208 +328776 +312375 +236197 +628360 +232717 +330574 +327440 +606567 +219582 +619228 +257106 +238556 +272194 +253914 +206994 +279802 +272259 +255795 +290568 +325954 +625378 +303568 +274677 +252240 +227711 +253701 +323413 +616623 +268273 +252079 +600877 +298644 +629434 +221868 +276998 +257843 +322705 +313308 +311024 +324115 +221635 +253305 +340890 +288422 +315506 +224625 +293429 +630677 +286943 +629995 +298220 +626421 +230659 +242763 +281885 +204264 +211988 +602587 +330623 +321135 +276243 +223101 +609400 +230902 +243149 +296014 +200141 +268541 +617676 +207441 +298618 +295440 +291151 +303650 +613055 +330418 +267635 +285128 +9841 +324426 +607775 +246557 +260137 +628809 +320559 +329001 +253243 +221206 +260159 +233599 +288533 +322001 +313110 +617185 +308571 +302206 +254386 +308265 +335536 +277169 +626334 +252934 +279281 +233457 +612578 +249488 +314735 +245228 +618768 +327899 +203846 +233033 +288209 +614331 +608684 +315743 +263107 +278090 +317756 +320388 +247593 +228495 +212749 +327901 +294233 +285989 +271858 +624011 +627852 +267643 +318925 +281356 +312148 +238423 +260961 +211316 +334966 +275823 +208007 +278801 +244706 +339541 +220833 +317704 +227878 +286007 +328902 +238393 +309384 +331925 +256693 +264735 +288869 +301032 +237876 +308246 +285158 +282834 +327419 +620298 +268440 +220287 +295854 +259949 +614552 +276694 +268788 +266767 +260598 +235317 +627922 +263086 +9933 +219891 +600958 +284772 +275759 +327675 +641476 +314125 +236477 +336092 +216267 +203298 +619488 +337328 +295769 +329762 +221554 +218324 +295217 +238285 +331323 +303854 +318272 +297895 +318524 +289976 +224760 +243964 +310337 +334581 +337191 +249529 +600623 +625328 +256594 +270382 +322138 +258521 +321488 +256862 +254103 +308267 +313220 +221486 +244956 +249745 +320116 +215462 +273312 +298107 +249399 +606569 +323417 +255749 +276491 +306965 +619560 +237036 +263954 +333799 +618623 +306655 +272404 +219978 +627088 +209241 +627696 +256416 +293535 +305282 +609377 +612484 +608031 +249171 +339123 +270531 +609593 +268278 +255424 +291239 +219662 +254887 +605096 +301742 +266757 +336084 +334383 +300491 +120005 +262418 +278212 +620227 +283236 +266391 +252125 +614504 +265416 +315313 +602420 +284108 +259505 +213462 +287708 +312139 +333053 +224943 +262138 +298280 +265848 +278537 +244061 +200265 +295168 +299665 +604434 +304280 +607663 +297148 +263307 +267166 +238597 +315718 +330697 +200850 +242834 +246763 +222008 +217122 +624496 +609546 +327643 +231115 +293422 +328625 +622339 +313037 +322368 +311674 +335696 +217523 +326974 +627320 +220500 +230985 +298340 +328806 +215190 +609391 +301401 +285136 +318908 +219384 +247544 +227378 +286807 +306029 +314981 +290123 +629050 +259368 +224945 +242006 +219588 +275871 +301472 +254569 +288166 +285195 +291184 +300586 +321266 +255164 +623908 +304148 +278603 +298278 +606942 +294745 +235904 +223115 +287127 +322466 +224929 +242173 +216721 +299258 +202231 +318201 +314350 +327581 +318306 +279227 +628961 +324198 +317858 +276790 +265419 +331962 +208245 +609788 +620173 +318490 +600378 +236337 +308923 +625653 +339659 +299681 +285248 +323196 +313357 +253119 +252518 +303386 +279549 +268897 +615132 +226528 +300828 +246939 +268246 +224886 +308339 +236676 +283778 +617585 +287506 +614002 +616907 +234032 +231038 +287600 +295202 +228224 +217068 +224752 +310612 +622533 +627688 +631145 +202994 +296698 +307519 +288917 +246974 +605411 +301756 +609756 +305018 +624421 +234860 +281297 +300639 +264470 +233407 +253965 +216031 +609234 +300011 +312651 +211517 +211486 +248866 +239457 +287596 +223355 +298811 +616918 +293843 +239207 +309191 +612673 +240898 +286605 +299264 +335079 +214095 +291474 +253628 +308427 +212525 +216593 +230745 +293774 +608295 +333955 +611070 +622311 +318319 +207745 +237821 +261506 +621919 +203099 +322016 +303161 +241377 +267991 +623055 +268608 +291222 +319901 +235548 +249800 +230178 +214281 +248443 +201099 +623443 +219337 +300945 +222440 +625184 +334452 +603264 +295000 +252330 +608518 +307032 +293619 +204575 +604169 +221696 +265896 +227118 +270404 +263672 +244251 +217247 +261105 +214567 +236120 +8495 +275180 +236793 +608729 +201648 +252015 +331003 +264817 +334861 +230747 +278472 +607865 +331159 +252067 +318372 +626098 +626577 +283487 +265716 +219740 +241267 +618556 +251542 +218547 +217792 +248493 +254046 +329694 +331724 +215030 +629451 +294576 +214478 +255770 +277986 +311083 +276795 +288566 +246829 +209938 +276754 +278416 +201662 +230517 +229526 +318793 +201600 +333588 +249222 +271982 +310240 +626682 +614711 +268335 +321988 +322386 +278675 +241321 +238128 +307104 +286344 +236735 +328159 +251592 +301662 +279647 +275574 +295552 +240750 +312368 +318969 +302635 +300176 +236639 +260908 +291439 +294229 +236311 +232159 +241231 +247220 +291332 +246243 +251368 +328757 +610490 +321565 +240795 +302274 +294533 +290110 +270089 +273207 +257543 +326268 +238648 +623513 +308850 +221243 +231125 +243093 +211843 +256508 +236688 +284802 +248160 +268400 +303541 +249177 +248552 +220688 +326647 +307612 +271498 +617516 +293594 +263382 +275150 +252701 +266718 +253014 +609531 +619211 +316361 +257616 +302670 +324285 +262514 +268164 +254166 +625351 +247827 +260116 +317533 +612870 +262591 +628043 +293621 +310531 +243908 +219457 +235705 +232937 +298436 +209130 +333806 +627766 +260601 +237106 +613194 +262308 +211932 +324414 +223858 +224896 +319015 +326048 +269335 +277152 +327244 +607417 +286244 +235791 +275477 +222116 +230967 +234813 +259294 +621207 +328546 +313820 +605634 +268386 +266129 +200184 +309271 +330655 +227258 +323030 +204246 +201663 +300753 +301546 +224675 +263735 +312972 +220485 +607727 +326108 +631427 +262216 +248694 +330946 +282845 +302804 +247793 +334318 +256493 +274367 +226477 +266575 +319278 +618885 +608891 +239183 +217784 +272763 +314410 +227135 +216041 +624502 +293897 +632446 +623275 +241796 +233502 +273969 +258237 +224538 +248776 +268243 +241992 +247368 +249883 +275863 +618327 +341102 +223767 +272768 +286418 +296128 +268815 +241400 +251234 +219222 +235140 +624197 +264388 +618918 +251877 +215524 +601165 +295232 +290705 +266813 +280587 +610764 +290998 +211693 +219808 +272400 +227893 +623082 +263501 +623804 +329609 +311546 +264663 +221929 +224409 +221921 +289033 +255907 +601012 +209064 +631350 +277800 +221104 +245691 +228301 +318912 +295004 +223372 +266543 +298147 +331385 +299747 +303610 +232580 +609167 +329813 +260604 +277179 +602398 +223189 +210042 +226556 +605853 +258169 +909407 +263255 +209636 +269841 +620238 +260627 +204756 +314265 +609094 +318922 +236737 +270599 +274074 +275778 +233253 +608899 +624125 +205129 +610947 +244978 +631798 +266609 +289282 +215847 +246049 +613879 +613547 +293871 +620185 +272659 +215840 +338252 +299890 +264635 +294056 +228539 +311974 +333663 +283938 +337135 +312987 +317947 +287382 +255173 +287932 +303242 +205030 +226338 +219433 +306614 +230123 +251349 +615564 +215193 +212696 +251017 +231033 +254388 +256758 +261369 +258236 +339703 +247918 +247031 +238514 +275946 +298683 +314090 +277017 +248898 +623051 +247543 +310420 +334444 +311836 +631712 +242029 +278486 +254068 +614715 +269985 +247681 +616920 +321741 +230858 +614725 +324385 +265297 +247039 +318115 +234870 +239739 +282759 +236423 +277036 +323094 +333996 +294952 +303411 +631233 +235177 +626947 +609989 +606738 +238511 +254807 +298918 +279113 +609837 +322112 +618251 +230672 +221017 +291874 +294260 +619116 +281764 +218987 +219169 +318999 +213180 +237834 +288971 +203312 +240816 +294777 +294262 +306311 +606378 +239528 +284621 +287800 +227691 +628136 +332623 +288975 +259234 +299725 +274395 +228043 +202996 +221061 +216946 +265970 +605140 +223431 +277624 +277038 +216552 +626590 +316359 +255034 +239290 +301410 +302475 +300936 +237305 +278004 +272772 +299168 +254736 +247658 +247992 +288121 +271935 +226299 +215533 +228424 +225404 +627325 +255024 +303426 +243256 +608765 +272722 +254919 +618124 +628355 +263773 +226592 +327413 +255211 +330757 +312321 +300763 +230557 +223468 +241302 +231335 +230644 +300285 +203291 +262572 +268732 +273041 +223895 +279248 +249910 +201549 +338508 +612273 +253863 +214491 +321711 +331667 +615443 +286935 +279954 +322219 +321570 +329336 +315711 +314128 +614791 +630671 +318489 +291508 +330028 +609819 +234372 +279582 +223026 +609100 +251285 +203952 +315425 +285623 +624894 +232738 +624441 +249020 +235244 +247143 +233828 +232324 +298821 +239807 +232073 +312185 +215536 +268363 +215417 +259562 +632630 +330732 +277085 +266074 +261286 +340535 +290852 +248252 +289578 +253897 +313195 +216462 +299616 +247532 +211785 +220679 +251859 +253607 +278122 +258846 +294724 +623652 +208344 +620300 +265114 +283393 +227985 +270624 +605318 +306349 +257793 +300171 +306465 +254334 +287445 +601851 +251413 +628384 +623364 +337635 +336560 +628178 +283481 +299610 +228117 +295225 +609427 +217922 +224913 +623673 +233926 +627096 +320403 +263549 +307286 +910877 +269460 +307800 +268646 +257617 +622853 +289795 +281986 +605817 +626116 +229935 +275400 +309434 +225354 +338895 +213292 +617451 +251684 +252781 +255176 +273522 +305831 +222705 +262972 +604849 +278234 +282558 +335530 +214788 +334430 +295089 +287242 +276917 +340050 +604000 +313590 +631370 +285104 +266633 +249433 +229600 +234854 +265522 +302720 +627288 +268409 +207810 +266762 +276812 +285727 +252586 +274091 +237161 +305983 +212887 +274627 +289192 +272725 +255987 +603773 +338110 +233799 +221496 +608979 +609306 +285305 +269328 +209718 +235363 +220395 +269477 +234995 +275171 +317880 +8728 +631364 +245339 +249598 +251415 +329920 +338229 +303571 +260132 +302445 +318940 +220041 +309249 +254125 +218792 +252635 +268311 +216732 +323567 +223188 +322737 +283580 +244970 +298635 +247586 +607508 +612213 +318408 +332409 +316296 +303443 +295446 +253782 +282881 +229792 +232087 +306658 +262161 +294923 +611490 +336319 +335332 +277099 +298246 +230118 +294974 +313671 +296451 +266411 +279505 +309984 +630755 +253272 +234849 +608001 +295045 +262925 +222982 +235532 +323028 +222633 +262412 +239335 +626386 +291175 +268265 +218570 +259612 +612816 +211549 +618909 +602999 +249292 +334472 +281622 +237092 +336581 +317169 +321603 +324362 +255522 +607183 +306113 +207634 +247657 +212300 +273514 +296631 +260079 +316021 +254516 +248545 +226136 +269387 +211713 +253548 +218923 +266073 +283493 +237765 +235746 +314936 +237439 +314229 +234340 +253626 +276906 +282557 +260309 +248502 +632738 +273191 +262516 +219698 +248485 +303644 +248512 +274522 +276840 +269185 +242377 +9835 +270563 +301287 +311244 +242390 +304128 +226526 +236689 +324620 +262930 +215805 +273978 +211594 +287484 +221008 +301583 +265799 +309475 +309517 +255848 +220808 +278366 +608016 +296012 +317040 +214015 +327546 +332210 +304066 +611560 +610879 +318930 +294121 +333602 +264226 +227179 +221727 +301125 +252538 +628515 +257315 +278415 +329366 +611889 +212337 +230330 +205660 +340321 +221700 +240705 +255054 +619942 +265394 +908496 +266801 +267139 +224919 +236794 +301638 +295145 +250021 +331336 +609416 +266192 +201433 +226488 +266155 +288777 +229714 +300862 +617050 +223037 +607081 +246987 +615759 +625991 +258087 +214853 +274837 +612326 +276071 +268506 +603887 +325661 +251492 +312787 +248347 +605821 +243471 +278779 +908690 +237198 +207583 +265387 +317999 +312993 +267631 +218447 +310856 +262256 +246669 +297401 +256222 +236753 +274335 +300035 +275542 +302756 +323460 +628629 +321721 +220226 +253289 +317542 +232070 +242276 +271086 +222716 +252058 +625318 +305169 +280559 +219062 +9823 +323476 +256725 +618777 +600408 +313609 +246037 +9721 +281784 +299506 +252477 +227632 +299613 +253346 +248737 +248333 +318381 +316748 +237163 +286262 +300837 +285286 +276888 +277101 +212109 +262242 +611963 +612252 +255578 +312643 +225382 +315563 +230602 +220929 +329826 +607814 +220151 +211383 +623712 +220661 +230193 +291085 +287746 +600601 +632258 +218242 +314252 +287363 +613906 +268310 +258301 +278438 +337066 +299734 +227761 +251475 +230861 +315688 +233160 +607957 +228869 +621560 +298274 +912563 +236901 +315192 +243421 +272955 +234079 +911934 +220752 +303989 +318876 +273412 +308975 +245986 +219691 +249251 +267833 +310962 +274972 +268094 +282856 +321428 +236867 +285833 +286264 +212226 +205199 +261715 +302957 +622732 +605815 +624080 +223844 +310927 +622889 +298447 +301953 +252369 +266717 +221680 +272369 +327626 +237039 +278397 +243752 +252611 +607325 +604204 +287252 +202499 +255646 +322180 +224559 +293499 +340440 +209481 +275812 +235636 +249865 +621268 +608621 +286067 +251194 +207901 +605335 +329424 +201970 +294582 +274337 +275270 +241779 +341117 +278249 +237128 +604506 +242497 +629825 +231026 +284931 +320691 +286714 +227772 +304927 +293406 +250176 +283286 +242482 +329515 +625810 +309143 +600825 +339407 +615588 +268717 +242153 +632291 +326906 +236345 +298831 +212002 +236667 +628359 +257217 +284520 +304712 +246759 +608385 +284533 +280611 +239182 +296092 +304810 +9777 +246371 +285121 +299887 +282593 +307322 +300402 +320203 +236136 +259772 +301182 +220557 +339128 +340764 +256730 +252362 +221576 +268232 +245162 +336267 +233886 +317624 +608062 +617472 +624918 +272389 +618647 +627243 +338077 +334130 +307395 +631344 +245404 +276556 +331140 +266809 +224151 +268145 +618110 +277039 +220085 +332363 +223211 +305467 +255193 +266046 +243638 +278557 +333781 +209321 +268457 +211810 +321890 +221948 +317259 +273616 +234866 +306387 +281500 +262587 +257661 +253281 +247486 +601139 +302038 +283163 +249677 +643330 +298975 +230400 +320815 +315717 +261472 +284422 +323282 +623702 +255624 +262898 +328257 +236766 +274110 +641542 +622322 +276814 +249869 +610402 +254139 +338546 +288369 +335033 +628734 +277014 +265686 +269627 +257438 +208994 +284875 +615096 +321133 +314719 +318968 +266622 +202054 +294438 +338999 +284549 +238438 +217991 +304077 +329202 +205493 +256762 +333835 +231975 +279729 +257375 +304262 +254444 +214226 +612263 +300070 +258865 +289647 +224894 +298090 +612776 +235005 +295392 +256915 +285220 +328446 +233161 +221331 +628997 +270666 +220839 +329039 +285929 +289837 +293981 +230589 +231085 +237550 +312029 +200971 +294354 +277110 +311953 +238877 +267266 +626220 +223575 +323304 +244748 +208858 +224201 +300410 +252608 +319142 +308645 +314739 +623231 +249668 +306652 +331795 +228296 +327340 +274665 +301567 +310472 +301294 +623271 +621439 +622643 +265178 +240039 +262127 +631390 +254930 +231526 +294678 +269019 +248037 +620087 +275886 +284986 +302078 +255525 +224024 +293462 +218149 +277091 +289313 +262486 +334991 +265781 +235861 +285385 +324148 +327985 +289562 +249587 +290589 +619532 +625034 +236153 +201483 +910243 +286465 +273734 +328261 +316560 +323047 +331905 +248976 +619635 +8593 +200257 +237633 +289305 +271874 +327229 +221233 +220092 +229507 +268970 +263305 +258030 +632852 +223850 +299703 +268486 +279024 +215219 +306880 +212737 +303492 +260725 +247950 +253979 +244434 +213845 +239241 +221140 +623978 +623041 +242190 +244242 +265550 +283562 +241381 +246760 +265651 +239247 +306242 +602936 +280759 +612210 +222625 +318902 +282004 +252228 +276838 +219934 +274373 +241913 +314139 +618557 +235974 +604517 +617739 +276890 +312030 +242922 +220912 +333654 +253555 +216269 +230766 +232518 +235018 +272485 +335561 +326023 +305863 +255300 +249397 +615929 +618146 +301436 +260424 +619732 +212034 +625556 +607694 +269115 +272653 +280020 +227845 +261513 +233306 +253899 +285405 +203364 +606071 +250254 +229571 +246942 +268239 +252659 +320774 +213757 +303184 +611878 +290836 +320553 +624577 +269118 +301787 +256408 +618751 +300096 +276158 +632565 +273295 +230972 +244090 +913876 +297463 +318916 +625149 +330713 +242389 +287844 +221363 +296501 +236113 +285093 +262225 +331097 +605998 +318362 +240002 +285406 +249286 +335266 +329765 +267222 +265588 +300802 +293901 +297964 +632254 +340331 +263289 +248033 +306274 +256772 +613692 +233417 +617605 +306045 +295286 +276336 +269914 +334104 +297855 +315417 +252839 +265401 +260105 +328289 +612681 +278514 +219350 +217028 +242427 +254858 +205239 +269963 +613611 +312140 +254216 +329918 +219675 +618131 +310343 +273896 +334366 +625547 +284959 +231824 +629237 +280575 +338410 +337969 +264840 +331964 +324246 +284316 +329902 +294231 +279278 +321426 +277150 +252858 +248289 +212029 +339743 +293568 +608847 +265722 +609611 +335739 +261258 +335573 +268201 +210118 +254150 +325342 +235064 +608627 +324070 +337638 +330152 +325990 +329520 +304264 +221850 +239518 +219873 +336935 +339179 +294519 +632874 +289853 +604857 +327673 +256537 +284891 +331370 +215078 +263577 +602269 +625551 +268138 +309223 +225511 +273361 +220440 +254634 +213126 +247991 +628938 +318784 +613694 +211468 +267499 +297728 +235309 +260139 +313642 +240524 +284101 +265096 +252936 +238363 +219870 +202893 +320839 +276805 +293788 +340140 +328551 +326763 +606425 +256369 +222747 +301414 +254123 +281967 +247404 +616474 +294603 +302881 +317550 +909869 +270538 +236306 +248419 +600918 +316366 +602366 +226898 +312690 +251151 +606967 +630764 +269354 +224168 +224867 +315507 +220465 +251947 +258547 +250420 +287534 +302737 +600653 +220697 +264710 +254628 +241832 +208068 +631983 +313474 +604398 +274669 +294653 +228663 +269459 +294234 +617313 +232447 +255731 +601728 +296371 +220939 +305128 +286409 +215216 +306284 +253301 +206809 +242379 +326676 +237397 +275302 +328049 +258418 +615045 +255789 +208488 +275765 +234252 +308908 +251984 +320021 +328931 +242131 +607517 +615458 +220048 +308552 +330908 +606571 +210346 +9934 +247705 +266753 +243182 +207015 +310175 +224482 +318294 +249159 +318177 +619626 +321477 +600545 +258567 +624609 +222260 +200202 +273487 +621796 +318962 +212903 +231875 +610730 +328259 +626934 +311517 +340152 +213740 +221478 +263924 +249546 +619186 +243888 +626571 +284053 +626208 +235136 +318987 +619912 +624475 +623183 +300815 +300974 +211548 +220892 +248678 +253380 +604514 +336480 +260895 +627202 +249415 +317246 +628441 +201431 +251605 +244519 +327714 +215289 +226791 +268471 +626398 +241125 +618325 +215225 +234255 +286825 +295826 +237546 +285152 +267683 +203418 +211471 +204429 +234501 +628128 +262243 +217766 +304775 +220394 +604013 +222289 +220360 +606525 +609071 +318068 +623609 +250358 +608957 +262280 +628509 +232479 +219674 +234374 +269255 +262257 +258537 +223473 +624794 +236871 +321905 +288574 +287415 +621974 +313077 +250013 +632438 +232274 +275253 +241572 +218567 +326032 +609222 +236827 +320951 +339958 +237699 +605193 +283223 +268312 +224854 +318209 +255931 +303435 +334201 +251562 +218552 +293757 +312807 +226653 +612360 +312377 +294691 +275632 +216503 +217457 +226846 +237641 +237059 +272268 +253331 +628789 +311336 +318392 +282862 +324329 +285843 +603447 +618543 +217504 +626430 +250128 +264600 +304186 +261788 +293783 +273837 +261699 +221262 +622899 +237922 +313373 +625402 +235356 +322189 +628069 +330017 +307342 +278186 +200254 +618439 +322602 +249994 +610994 +618794 +242553 +332946 +256475 +334052 +235286 +239175 +313673 +631389 +605081 +252836 +254552 +273066 +242719 +234811 +296229 +202984 +295722 +230525 +253182 +618152 +624575 +320570 +283349 +320750 +305739 +254623 +632299 +256498 +605092 +212683 +282335 +316382 +607062 +306819 +601939 +216541 +330101 +202914 +321697 +222159 +236243 +246937 +612739 +281904 +601102 +256653 +256568 +224019 +288175 +232745 +629277 +233756 +255656 +8631 +211423 +243188 +618136 +251957 +218812 +269849 +910403 +224212 +268733 +272043 +273810 +603629 +623227 +255634 +219212 +300073 +331703 +232826 +622127 +293602 +301465 +310901 +237435 +611145 +620263 +247258 +257566 +211089 +277078 +288342 +604068 +296006 +224330 +211436 +617721 +223816 +615699 +210508 +617727 +324588 +329966 +211333 +618016 +247914 +260746 +314578 +283617 +234784 +324554 +303466 +624161 +200978 +295364 +304040 +253674 +279950 +294158 +251953 +227758 +266624 +221111 +244159 +278453 +641455 +303860 +335367 +201739 +218656 +264940 +248620 +291071 +616063 +245144 +235460 +249262 +236271 +242360 +626235 +220105 +614787 +614975 +252713 +338549 +300395 +241393 +328352 +268365 +120221 +259749 +251033 +321838 +294186 +248609 +285285 +219962 +625735 +294775 +267915 +273819 +273680 +607905 +335284 +287760 +330955 +314744 +255752 +288145 +214032 +280433 +279702 +603696 +226502 +612713 +219431 +614141 +285985 +236321 +224924 +255837 +337344 +625217 +323180 +222720 +260934 +611810 +339116 +206978 +249220 +253556 +287485 +334341 +275949 +305934 +220456 +630166 +307260 +300298 +287120 +299781 +296722 +221740 +618861 +204188 +608959 +203043 +320639 +227816 +610391 +250429 +615708 +8753 +302145 +610658 +296369 +247765 +308733 +221543 +271656 +245054 +622847 +228624 +602783 +268231 +618460 +604069 +610440 +300246 +617256 +284715 +285681 +280135 +277885 +257439 +285295 +255573 +271738 +278659 +234810 +294498 +274117 +234384 +279344 +220251 +626601 +604935 +624765 +226132 +287078 +339694 +247514 +235835 +271861 +330466 +254956 +912701 +335948 +609084 +239216 +223545 +610462 +324292 +223004 +249143 +301663 +328124 +630783 +248603 +609042 +235196 +262116 +264474 +233399 +610633 +220152 +249889 +618400 +631159 +328205 +283158 +337974 +257111 +245159 +287589 +203523 +220317 +600405 +251710 +232302 +235223 +260534 +305746 +236678 +234796 +236581 +624717 +280410 +261151 +611612 +329197 +302422 +624474 +616938 +631770 +234147 +252267 +230246 +276943 +282163 +253801 +218251 +286889 +295712 +211473 +247029 +264564 +276987 +603667 +278205 +257930 +231722 +290591 +256402 +236799 +322249 +233862 +257862 +323418 +276791 +221565 +217194 +607941 +246657 +265586 +264828 +261810 +610477 +618657 +609019 +233730 +604277 +611183 +237847 +338133 +327811 +308983 +230629 +624380 +274885 +274081 +339256 +231048 +613344 +265294 +610878 +324522 +281930 +230726 +296104 +332019 +627418 +220247 +604129 +604802 +313184 +300648 +260338 +217157 +641593 +307629 +222115 +235868 +311754 +625032 +290490 +221083 +608698 +268066 +268595 +609211 +246737 +255866 +327384 +261901 +607799 +234324 +293567 +329313 +235775 +624440 +239259 +602144 +243631 +240830 +257474 +262664 +287593 +224145 +223083 +274919 +263167 +221002 +221208 +277005 +236562 +281072 +611230 +245017 +312503 +290520 +265854 +603488 +219977 +624646 +279097 +303809 +249185 +236579 +243359 +341455 +288928 +228929 +254270 +618448 +303618 +230470 +253106 +260715 +624137 +622846 +239258 +307144 +307163 +611242 +275103 +331219 +307636 +298414 +312603 +288989 +338538 +212502 +239434 +225722 +255718 +237658 +328641 +604766 +333906 +287034 +284471 +305968 +261710 +237265 +216378 +265307 +301220 +627487 +211078 +257360 +626891 +318991 +262560 +281781 +303719 +621375 +219492 +299044 +9761 +319286 +257335 +237022 +623543 +211638 +242003 +277043 +218599 +224928 +230924 +215493 +286539 +244470 +247508 +215072 +620294 +239865 +247648 +231196 +265624 +266084 +242098 +274649 +317269 +219339 +202881 +252057 +316275 +625248 +628012 +290585 +248705 +250319 +303320 +253994 +317472 +604965 +624467 +604987 +247837 +269265 +237543 +623324 +200431 +256584 +625792 +216342 +234808 +249807 +291348 +328866 +216807 +253940 +245749 +610753 +230799 +288028 +265496 +632179 +226364 +330876 +600406 +220670 +325277 +278921 +236069 +268382 +328197 +278636 +229135 +222927 +213154 +603534 +221050 +271610 +291152 +300895 +308377 +334361 +289066 +219586 +217782 +219294 +276751 +612921 +260455 +281306 +618111 +266126 +247076 +228044 +619509 +273528 +608532 +215291 +248544 +618591 +280518 +255425 +311777 +249235 +214040 +619563 +207203 +214610 +223062 +340863 +319054 +212482 +237751 +335568 +230881 +265682 +291814 +265593 +337440 +247768 +605960 +213372 +622417 +613034 +623255 +322349 +260576 +261157 +630811 +268316 +628921 +308864 +607492 +291659 +213311 +298920 +262761 +304668 +614102 +316593 +280106 +261352 +242955 +251307 +212394 +311403 +622478 +236662 +254019 +239409 +300062 +253290 +328684 +287602 +215362 +286083 +633107 +249142 +302009 +267202 +254521 +268359 +217899 +212257 +276928 +605050 +243914 +266660 +325995 +213389 +327282 +290605 +291826 +221392 +237725 +212529 +626696 +224156 +262580 +221562 +299185 +261894 +232410 +329451 +224874 +233690 +605116 +219561 +252961 +288428 +286828 +237622 +298890 +629256 +225924 +249642 +294001 +202224 +269213 +306757 +295132 +298326 +238017 +333797 +283465 +252594 +613177 +228286 +269257 +216676 +239539 +623199 +275252 +608069 +281699 +306471 +222628 +233573 +322284 +232501 +235569 +306186 +266689 +231009 +291211 +320221 +611358 +617509 +908362 +317105 +249183 +608913 +256387 +909030 +262947 +241905 +241615 +601215 +223077 +273017 +211606 +278674 +237608 +600414 +285602 +256422 +249203 +254724 +323478 +263440 +307502 +612086 +229627 +294227 +279361 +211448 +250207 +607310 +217207 +308036 +607722 +289437 +612329 +252367 +330489 +271850 +615233 +326597 +229518 +254849 +315239 +229464 +304961 +600555 +286632 +254407 +241559 +623394 +322167 +260041 +305152 +249782 +604237 +285969 +627695 +8696 +287921 +255042 +219570 +306385 +250350 +276945 +285800 +307309 +221088 +289163 +267760 +620189 +289646 +614088 +321963 +340748 +303688 +221173 +230251 +279391 +244096 +261507 +239248 +610859 +284238 +221613 +321740 +245588 +269067 +280713 +334954 +312483 +309419 +255035 +323041 +266055 +329978 +218862 +257078 +220711 +201868 +619424 +250210 +234217 +241721 +617107 +282562 +226532 +631801 +245140 +213717 +318907 +226818 +211457 +251813 +257992 +601043 +229220 +220782 +218596 +302942 +627590 +302448 +226870 +303413 +611439 +303476 +325275 +215175 +340698 +263281 +315464 +253063 +288670 +244161 +224524 +228389 +210012 +618854 +602461 +614705 +244362 +218305 +299227 +612480 +340243 +213876 +330461 +261530 +330487 +630070 +228755 +223566 +230824 +202680 +329876 +295960 +228802 +248986 +295218 +209382 +600948 +250043 +214042 +631706 +224780 +609822 +327695 +306493 +608881 +234106 +214993 +248424 +616732 +313217 +602363 +280813 +252731 +629134 +216465 +248942 +290542 +218062 +322256 +215399 +265933 +245419 +626526 +323988 +245412 +266408 +220318 +237202 +251821 +265502 +230879 +313626 +249466 +267209 +247928 +620078 +624939 +612347 +201804 +626852 +247333 +249120 +311363 +200165 +220108 +631665 +330103 +252843 +629892 +605641 +284529 +286572 +287770 +311358 +329953 +919487 +262075 +302395 +201792 +221502 +606172 +242689 +237224 +621244 +261304 +300830 +336376 +273215 +236555 +617985 +252252 +330880 +217322 +276703 +605480 +250465 +335078 +287842 +330442 +298297 +307483 +320276 +319013 +200342 +272511 +200186 +260097 +299288 +328471 +264774 +245940 +253751 +320541 +333831 +310445 +326993 +216691 +227915 +608897 +226548 +201619 +272107 +618350 +261060 +232854 +611971 +252840 +609949 +265782 +261392 +631111 +219661 +335395 +314836 +332222 +283870 +227579 +280304 +245751 +260678 +235862 +246977 +315286 +290486 +313613 +257450 +208528 +226042 +236099 +255689 +266559 +304979 +235969 +255619 +248218 +314680 +243401 +258142 +602525 +283783 +297420 +273531 +257099 +600854 +619205 +243019 +251514 +908275 +623212 +238007 +315665 +218207 +303831 +234559 +268797 +291198 +318905 +612361 +245336 +612701 +312815 +335220 +271554 +301100 +236711 +234052 +229893 +216008 +200264 +221143 +269404 +617391 +305421 +246777 +279770 +240142 +338290 +632072 +323300 +259173 +321973 +316549 +270082 +274668 +224833 +601722 +231608 +623396 +281964 +317089 +294176 +627232 +301307 +219786 +288553 +261460 +202798 +321111 +239384 +278203 +629478 +606179 +328245 +307364 +286859 +215366 +298843 +237177 +211335 +247153 +275779 +297861 +602270 +329851 +625024 +233744 +244026 +238593 +326054 +248606 +316012 +331756 +263502 +208146 +281422 +605305 +311880 +230099 +298455 +288883 +338539 +334368 +202047 +605414 +620316 +231025 +621228 +227407 +333607 +275319 +239497 +257351 +265731 +235300 +626471 +296489 +262902 +610704 +606632 +616441 +256790 +256474 +321614 +237011 +247789 +313234 +312283 +244047 +200307 +219026 +244123 +339905 +263227 +211894 +299525 +230688 +218606 +606713 +213477 +279039 +244547 +286658 +230790 +204953 +216027 +254419 +289404 +608381 +224098 +247872 +329538 +604602 +201673 +211092 +231288 +314122 +262949 +233476 +245746 +266806 +247051 +220185 +615655 +329574 +219155 +328724 +623704 +247472 +230851 +616986 +337383 +261728 +201057 +308809 +603019 +293861 +214158 +260176 +621237 +315207 +306357 +311422 +618080 +228796 +610802 +299133 +314893 +235618 +209540 +308800 +336608 +258292 +299986 +326701 +273433 +222950 +626666 +257800 +631416 +200426 +311719 +241077 +340510 +606023 +242210 +320278 +327083 +321999 +631616 +631064 +242714 +341509 +312186 +310489 +909364 +235199 +625655 +220790 +609828 +314181 +280183 +289011 +330327 +336528 +269242 +322140 +270693 +239519 +231507 +609789 +255039 +326983 +278568 +278373 +262494 +255396 +620193 +628224 +284792 +251649 +306031 +265310 +618599 +299552 +273936 +258360 +218417 +214431 +270180 +618496 +282605 +290793 +305373 +314540 +269851 +337397 +301528 +601738 +609763 +629254 +287663 +267816 +609787 +238475 +279022 +285489 +216863 +256348 +606057 +262449 +282740 +606548 +270350 +256477 +212912 +626441 +623964 +314005 +249241 +286426 +221524 +290823 +258842 +606508 +331969 +230814 +285117 +293409 +332345 +604739 +307955 +289051 +318484 +604397 +212402 +215282 +317126 +277095 +282079 +263339 +276523 +209797 +312931 +328758 +630210 +282308 +284951 +253013 +285194 +253677 +288667 +9809 +604049 +235512 +337595 +256438 +253415 +228862 +248896 +274723 +320131 +235967 +248027 +313461 +326641 +609206 +246576 +265192 +337108 +214627 +293846 +267114 +223598 +256941 +205426 +201444 +211743 +233229 +281234 +612292 +265695 +300669 +336860 +291294 +229968 +243557 +268385 +286963 +249154 +276995 +339380 +304223 +230816 +241955 +255115 +201724 +229286 +261555 +221121 +252915 +216284 +307000 +624811 +324387 +234867 +268405 +300616 +276702 +609078 +339341 +268206 +297409 +212348 +228310 +241535 +318996 +239317 +279369 +275037 +604981 +259391 +283570 +288079 +224306 +312004 +240486 +265614 +281168 +271640 +252616 +623253 +606453 +262026 +233466 +305823 +303614 +331454 +324508 +252323 +221462 +222787 +607798 +249347 +340673 +617471 +621217 +273854 +255249 +265660 +237227 +611736 +268880 +612441 +630064 +254126 +264994 +620264 +273547 +908582 +330972 +295735 +626638 +307496 +268389 +600852 +269336 +239479 +247651 +329189 +619520 +273664 +307149 +312725 +332318 +248134 +340712 +260888 +311993 +229927 +605125 +221592 +290575 +254337 +627274 +274586 +612796 +249968 +256403 +332320 +325939 +278403 +624145 +287611 +279342 +263600 +294255 +261936 +262787 +276869 +207279 +249684 +630211 +320992 +333185 +203438 +623864 +308291 +272271 +302801 +249516 +340248 +231727 +247841 +294856 +232080 +220880 +612707 +291827 +247653 +309530 +265113 +248907 +246809 +228637 +266834 +619591 +219485 +312261 +311919 +312031 +215639 +245224 +315161 +241304 +601969 +223876 +606242 +276762 +298531 +221662 +243632 +254548 +609838 +294485 +319974 +315683 +236861 +620163 +257063 +228639 +217039 +609102 +232947 +326395 +601116 +334206 +286610 +602904 +120008 +630996 +226524 +334041 +293569 +619197 +306826 +256432 +253636 +241196 +256431 +305608 +246541 +281623 +322228 +275596 +219361 +267254 +321833 +282900 +202132 +204995 +220784 +620276 +295003 +621219 +287395 +604048 +606088 +611823 +284860 +248703 +246176 +320816 +280831 +308524 +602470 +214137 +602289 +310105 +237531 +214901 +617102 +255554 +314913 +272571 +606645 +215874 +247621 +253110 +287439 +232628 +309495 +315677 +340540 +312715 +618187 +329578 +216184 +265600 +613513 +239260 +311723 +314965 +309848 +220365 +287688 +624035 +253633 +251874 +241724 +249309 +257565 +328497 +627450 +284277 +314347 +270843 +222233 +247014 +284745 +284578 +221889 +273807 +315497 +253516 +244578 +612566 +230357 +276217 +260590 +203703 +202706 +248307 +610467 +289964 +256468 +620327 +322154 +622308 +274817 +263302 +609345 +287426 +231034 +213267 +245478 +611034 +608678 +302963 +614010 +628519 +265946 +601426 +252331 +337238 +271775 +258775 +276960 +252874 +608533 +626191 +293720 +604448 +266184 +305011 +217346 +627982 +328110 +328369 +205557 +628373 +244065 +220982 +222718 +229703 +607350 +235366 +248397 +235049 +337327 +259354 +213233 +606740 +333786 +618492 +631224 +211464 +230868 +266941 +220793 +293968 +332141 +239485 +239462 +248284 +234229 +333938 +262269 +623992 +302898 +288551 +281785 +623409 +627740 +316546 +254260 +262749 +318803 +200605 +332043 +608554 +205494 +241426 +250322 +239257 +297700 +328078 +625636 +228596 +220341 +303781 +236263 +622531 +607085 +320684 +268614 +227058 +319179 +245721 +268165 +287911 +207047 +248984 +632462 +616846 +330904 +219537 +291472 +302032 +312745 +604530 +618158 +316149 +235231 +280829 +289974 +302807 +308440 +290464 +606851 +303680 +301674 +616082 +212774 +245156 +238577 +323456 +304774 +280492 +310320 +248960 +908524 +241909 +217466 +264301 +625057 +300515 +261247 +302442 +219332 +615574 +269081 +631871 +628179 +254389 +605299 +230261 +223123 +602552 +290976 +614562 +606862 +246373 +300121 +212494 +295196 +337425 +228421 +312088 +604241 +237962 +613044 +602272 +602278 +269173 +625121 +315988 +624431 +309794 +318938 +300854 +282949 +240544 +303314 +608649 +328645 +322989 +605173 +220555 +608860 +265817 +627195 +261557 +605396 +323034 +605716 +313481 +300501 +288596 +310873 +610535 +210922 +225546 +224877 +242965 +230376 +615584 +253593 +237781 +254925 +625487 +238671 +295009 +277124 +269389 +252491 +221570 +301062 +331858 +277606 +268062 +286208 +239169 +626530 +600071 +316427 +218878 +218309 +617711 +615159 +337128 +249024 +324433 +294045 +252714 +213143 +600209 +627539 +625639 +232952 +234313 +602485 +100204 +618127 +280604 +339270 +302228 +317981 +293907 +253329 +265616 +620068 +218285 +328781 +248582 +288094 +329128 +279705 +615539 +201975 +238702 +200500 +268216 +304941 +227822 +279439 +239444 +622848 +204828 +616830 +283002 +219622 +226354 +286598 +231068 +284387 +287739 +203449 +218893 +248052 +256284 +304886 +269156 +252821 +258885 +226520 +295729 +310039 +309048 +259510 +249951 +630076 +220730 +631752 +303269 +247623 +289352 +312492 +302429 +235722 +641496 +299939 +615220 +220970 +269132 +311705 +249135 +312702 +239546 +283435 +265873 +217817 +256391 +265558 +631387 +306731 +321464 +247750 +215269 +289042 +318718 +259112 +327903 +270186 +234834 +615988 +268462 +223572 +631741 +219762 +218045 +307806 +272243 +246703 +268377 +230017 +268351 +317697 +291803 +201142 +224249 +608886 +251958 +232459 +231126 +307582 +301697 +226915 +247908 +330268 +296703 +275176 +241003 +603860 +270669 +306706 +283883 +237762 +304085 +228664 +329690 +265861 +314329 +227422 +626518 +334302 +229284 +247523 +224895 +625054 +223806 +265101 +318943 +281765 +260169 +265275 +629558 +325967 +268298 +237314 +287848 +269205 +224161 +220055 +267376 +209700 +618007 +202112 +336703 +321858 +279738 +606935 +293681 +252122 +268340 +314413 +257118 +618098 +275873 +618478 +216199 +610050 +211601 +247241 +235753 +294987 +274356 +290100 +329116 +285411 +272869 +223001 +315546 +631420 +241184 +223236 +303462 +605115 +331728 +216122 +268332 +619456 +206829 +250047 +203340 +611404 +631814 +624245 +909258 +286887 +277591 +612599 +221346 +263036 +253098 +624345 +247422 +322576 +268181 +308023 +641594 +262255 +254598 +298652 +272923 +244459 +216415 +251680 +252652 +216444 +300061 +283644 +255657 +220876 +239285 +339129 +249256 +295889 +611012 +329485 +232665 +624770 +215477 +334065 +202483 +293767 +238291 +285552 +245119 +618371 +257267 +316137 +296282 +606528 +253036 +233776 +231112 +300553 +312484 +205872 +294110 +268214 +241285 +229747 +610510 +224778 +272463 +332233 +632506 +202272 +630706 +256405 +260632 +309756 +228538 +201159 +311794 +338041 +264115 +301108 +306644 +248855 +618451 +200276 +314233 +911303 +306638 +237669 +234359 +261344 +302649 +256341 +260558 +610686 +247821 +261653 +616777 +620205 +615879 +612717 +223378 +294307 +631003 +223340 +299949 +612589 +291834 +610509 +219592 +608299 +220200 +257115 +254825 +305121 +210890 +9637 +269994 +327941 +214751 +296536 +289355 +622142 +289897 +265063 +200232 +614221 +253724 +615651 +286269 +334463 +289045 +245583 +908724 +631556 +285380 +217559 +8545 +334237 +303880 +276934 +268115 +336041 +611312 +609535 +265448 +311952 +257418 +270584 +302011 +245807 +329386 +310344 +261561 +613024 +223614 +221403 +256910 +291652 +269227 +221874 +221099 +600198 +606350 +261727 +8653 +615906 +232608 +629430 +623974 +274878 +238819 +231954 +272556 +219394 +269658 +608910 +314949 +218528 +249186 +230966 +631709 +278350 +319962 +218993 +229196 +340469 +328377 +265769 +632184 +211567 +316151 +248972 +265119 +304725 +205442 +275767 +600773 +300408 +291002 +611327 +310220 +212668 +219415 +311766 +300623 +332016 +625555 +269874 +307432 +270198 +221766 +295264 +207908 +328364 +256291 +280281 +315226 +335989 +608667 +320169 +288702 +239322 +237675 +323301 +257433 +231738 +315145 +300569 +223102 +630763 +230637 +260460 +242387 +228021 +223341 +263079 +309962 +332045 +605402 +310021 +617337 +239312 +630843 +296514 +320620 +261474 +631396 +252237 +282655 +267165 +331737 +320898 +268729 +281443 +264697 +614281 +283881 +302596 +625082 +294761 +622745 +307609 +265483 +295271 +298424 +245294 +306494 +321703 +228814 +321909 +240473 +284364 +219573 +306990 +256986 +600924 +607022 +310483 +233984 +285910 +276991 +643510 +252446 +252598 +227391 +602407 +263312 +224930 +313719 +607328 +303703 +220202 +212085 +255076 +289361 +266248 +208779 +608800 +222425 +216759 +273586 +301333 +628761 +200876 +248036 +264084 +327300 +317471 +260421 +275853 +277916 +218290 +263248 +223373 +9667 +312573 +238975 +304786 +236088 +612985 +214766 +329423 +600849 +285268 +268252 +605095 +313320 +312235 +210772 +273635 +294253 +213968 +268628 +323273 +267248 +321378 +326465 +298030 +323462 +307986 +257980 +605221 +256270 +312311 +256671 +301049 +270259 +276209 +324624 +312747 +609405 +201676 +609453 +216861 +911070 +334881 +283304 +235164 +283008 +312804 +316790 +623126 +236714 +334086 +218355 +337508 +275074 +236989 +258642 +613688 +220498 +236961 +246912 +237429 +252966 +247758 +325239 +607346 +289170 +311152 +233838 +222011 +277713 +322637 +254328 +248008 +226224 +219939 +327391 +260774 +215754 +213322 +313085 +294955 +282078 +912545 +229750 +608022 +335359 +257574 +214579 +618095 +334256 +328554 +322150 +603807 +613370 +222992 +256530 +618197 +307687 +321400 +627271 +212057 +220139 +223137 +227122 +236924 +285287 +263443 +631800 +628055 +619172 +605698 +223298 +317916 +257649 +314286 +229743 +238296 +269718 +219614 +339991 +222712 +269321 +260468 +336983 +8695 +263529 +308874 +318542 +340345 +290467 +237677 +239443 +249199 +239605 +321717 +622255 +200859 +257550 +620143 +239362 +235538 +288598 +605412 +276145 +609720 +223984 +304178 +630741 +291406 +271855 +336978 +256703 +268236 +247561 +239429 +301028 +303640 +247081 +610524 +232585 +223576 +306972 +317894 +618744 +287091 +293902 +609637 +278917 +265647 +235447 +284313 +338809 +240853 +284209 +318480 +243634 +315592 +322823 +299009 +278981 +268911 +8480 +227161 +334228 +608027 +314145 +204832 +312711 +271712 +304788 +277998 +260927 +294340 +250056 +271545 +260481 +300444 +324614 +283068 +253942 +287103 +237018 +273112 +321124 +275422 +9759 +318137 +221212 +230854 +611527 +222745 +232109 +209871 +258941 +606517 +312737 +331281 +312050 +268870 +323405 +628982 +283802 +265943 +204792 +236885 +272962 +261357 +600698 +628377 +299915 +222913 +241281 +322865 +314632 +284636 +619551 +244966 +271816 +322160 +239885 +330133 +628159 +291377 +214911 +252752 +226203 +311931 +238381 +244516 +254977 +237738 +310080 +333784 +317846 +219881 +333848 +220301 +249208 +623930 +258603 +321769 +252757 +262484 +258608 +213303 +301990 +269323 +293953 +330847 +232881 +631740 +216461 +613979 +334489 +309373 +289377 +322564 +260787 +629675 +606486 +290158 +218688 +202013 +204816 +240940 +247013 +286840 +287401 +218938 +237558 +274660 +303208 +257123 +277061 +271485 +613968 +201960 +228051 +295719 +272165 +257158 +266082 +609180 +339842 +212236 +327702 +235297 +257379 +230679 +247476 +218374 +329264 +206584 +631984 +202781 +287888 +320796 +309633 +263689 +227597 +615945 +268271 +323392 +321556 +314338 +320680 +289428 +319893 +625188 +335326 +257787 +228795 +632542 +630925 +910078 +220641 +237085 +304556 +236110 +276989 +212372 +603246 +241878 +627480 +312912 +320389 +248527 +320459 +306659 +287713 +334077 +605934 +337560 +279590 +328487 +295971 +262039 +294975 +269916 +335063 +303485 +227448 +239276 +605086 +612686 +293952 +279541 +609147 +622028 +283024 +265700 +247726 +201524 +280061 +630729 +606390 +337023 +624067 +318343 +628104 +269616 +316355 +293845 +307616 +266202 +624428 +218747 +300485 +606037 +294416 +201002 +265170 +255674 +252452 +313692 +329603 +236441 +246297 +245497 +222362 +248236 +321525 +314864 +220815 +283093 +299969 +627228 +293589 +600925 +285939 +611682 +274224 +213417 +325975 +307930 +302583 +605215 +298380 +280712 +619633 +287759 +268696 +239898 +299473 +242338 +329795 +303810 +240132 +269442 +217098 +200549 +239287 +618321 +317705 +282793 +285582 +306312 +276083 +268836 +280987 +300998 +238345 +623737 +323288 +283760 +607729 +218508 +251330 +214905 +908880 +294313 +608855 +247073 +302433 +232242 +237149 +274749 +621945 +251399 +217762 +226716 +310892 +303818 +235794 +301594 +221515 +215669 +261915 +288408 +299501 +261202 +629703 +285103 +324146 +236220 +231036 +605162 +334622 +340588 +239308 +609200 +218639 +287720 +228542 +329047 +219318 +253671 +274509 +298752 +291590 +228736 +607418 +295197 +243452 +285082 +607072 +323596 +235510 +248496 +285222 +218477 +328689 +247024 +605051 +312661 +331460 +270590 +214856 +250643 +910787 +288192 +256297 +219932 +204871 +219621 +213600 +258659 +232375 +613793 +628877 +607279 +605339 +322467 +230896 +606742 +244417 +249780 +278611 +611140 +619568 +216065 +262646 +230791 +272362 +244995 +265392 +211441 +218741 +261814 +232944 +333713 +301103 +240263 +299636 +296587 +212435 +255215 +286838 +252750 +284081 +223925 +237294 +300596 +605864 +273567 +329442 +605264 +233553 +281301 +298300 +618067 +310939 +237271 +257291 +258345 +624711 +246540 +285091 +285490 +317554 +279499 +222895 +276770 +612570 +237791 +236381 +301493 +281198 +219953 +337579 +241346 +267087 +222954 +298137 +261817 +626889 +254127 +263733 +620134 +243484 +219940 +326482 +274881 +254235 +610691 +337689 +213345 +604360 +323336 +626533 +244118 +273515 +621408 +219307 +334359 +277056 +289903 +615680 +216672 +259550 +305578 +252489 +260156 +295170 +327259 +339244 +600388 +627478 +258729 +296131 +328177 +256367 +273822 +323761 +252196 +279171 +217154 +277023 +299993 +215446 +274167 +201194 +242710 +236780 +218795 +239433 +276015 +621447 +267285 +317692 +316730 +237426 +334053 +275832 +236376 +618163 +267867 +296700 +318488 +307087 +603036 +314563 +229155 +298305 +619101 +630188 +294276 +628331 +230597 +324334 +250334 +289217 +228464 +249360 +335421 +303824 +268648 +261670 +220946 +339169 +260146 +268401 +257073 +250356 +610150 +327711 +241440 +255333 +214975 +313421 +602602 +340918 +290693 +332399 +612237 +245542 +340906 +219540 +279202 +287207 +268757 +277069 +320330 +204522 +235848 +612642 +632871 +236941 +278867 +626519 +219682 +302109 +224788 +266514 +247524 +289364 +302320 +213461 +289566 +264872 +265269 +323528 +265814 +285326 +272297 +337272 +8425 +269251 +308337 +299946 +268888 +330699 +911319 +215412 +228701 +278204 +260688 +260587 +312542 +330740 +221108 +303556 +625506 +253090 +334473 +255461 +259268 +283334 +614620 +328024 +266929 +331894 +247631 +246180 +318924 +286301 +284708 +302235 +283601 +217738 +618301 +252663 +225353 +219223 +293576 +253719 +619237 +304164 +606803 +298098 +235175 +253635 +231148 +630827 +203103 +315335 +608354 +235721 +317488 +242394 +278156 +298619 +235386 +612139 +277149 +310645 +251698 +330728 +286969 +326744 +235938 +316442 +621223 +247847 +299200 +325320 +201550 +264864 +211909 +318144 +625746 +212281 +258742 +247034 +223791 +214889 +305930 +316551 +249158 +269295 +309102 +283646 +607602 +312558 +318982 +325331 +320832 +280786 +625907 +261433 +227975 +244031 +329695 +239331 +290308 +631297 +632227 +208792 +216240 +239494 +253945 +282051 +294053 +336045 +612670 +241791 +333988 +611272 +244895 +218423 +224338 +319855 +311166 +600407 +207189 +611040 +283837 +293945 +256300 +239482 +240765 +216064 +208561 +320590 +257531 +269940 +243491 +321174 +320764 +229458 +260368 +288594 +312768 +269250 +609521 +335497 +212535 +223427 +218163 +208796 +316889 +264780 +340923 +326933 +631945 +302226 +624158 +211499 +324180 +300149 +222142 +294502 +301541 +313382 +623027 +120003 +239858 +281149 +288815 +312090 +339025 +246923 +273180 +609140 +282551 +212186 +272940 +320473 +275197 +301355 +289966 +236309 +309545 +251809 +219820 +312919 +625939 +311933 +273423 +227428 +204374 +278419 +244635 +624295 +311238 +287505 +231024 +331977 +601170 +203135 +258803 +245082 +219687 +243725 +238952 +327919 +219560 +336012 +619643 +314701 +607274 +318397 +291260 +278576 +626195 +265758 +611973 +612641 +296170 +265717 +312721 +631432 +224835 +219258 +289021 +324515 +247777 +326089 +605075 +254797 +220449 +247627 +260914 +316633 +244024 +624639 +204135 +605246 +295999 +256521 +330061 +8592 +256752 +275928 +254773 +908419 +302589 +608090 +641559 +242703 +268417 +270707 +259043 +275512 +231620 +307732 +616891 +317839 +631035 +309449 +276680 +291561 +617588 +337488 +302561 +218662 +321990 +236509 +222904 +312703 +274841 +213339 +603877 +271866 +219356 +223601 +251904 +266327 +223834 +330024 +221553 +293797 +296150 +222690 +230254 +327425 +307605 +306326 +291339 +248630 +214505 +211800 +262786 +299340 +281403 +295375 +222458 +221560 +251951 +243481 +320028 +604187 +226752 +235319 +219681 +601167 +262019 +273765 +262272 +256315 +233765 +288981 +299283 +221051 +615789 +255853 +614168 +294027 +618550 +259076 +251456 +295759 +274035 +253950 +301551 +231654 +218584 +302034 +319968 +316654 +605639 +243140 +611875 +235066 +283182 +611452 +215535 +290586 +233005 +265860 +261381 +229977 +294312 +609681 +224628 +261580 +303429 +624893 +251467 +314237 +257454 +253373 +286885 +331285 +252745 +249996 +314366 +267228 +232946 +225646 +294088 +228867 +287076 +226517 +282996 +314887 +315416 +220714 +260026 +267229 +328167 +618654 +214090 +631479 +237216 +620121 +256569 +212105 +216011 +268387 +329360 +340625 +628506 +283284 +240332 +268928 +319012 +616103 +262519 +210078 +266334 +234325 +210030 +283359 +288841 +262567 +272569 +265644 +212095 +323444 +214714 +618994 +239415 +911932 +322326 +616080 +249438 +268078 +287637 +253207 +613802 +253300 +287634 +307356 +220189 +256668 +301898 +625388 +267764 +338545 +322434 +250325 +609475 +302357 +617508 +212625 +275885 +216224 +249919 +618430 +267079 +607590 +230804 +255951 +613179 +620291 +321993 +9928 +9681 +326869 +235755 +333748 +248531 +310377 +213696 +240923 +205419 +247967 +288985 +339478 +294022 +234258 +600375 +279600 +261492 +224810 +222426 +258734 +252120 +201485 +253803 +258593 +267454 +221016 +269299 +270239 +244584 +614290 +239199 +237230 +236792 +227265 +236852 +203239 +203413 +333034 +253780 +239191 +285819 +295156 +302724 +211737 +233227 +308136 +215075 +909381 +234818 +248639 +262118 +608085 +609515 +213506 +321178 +275107 +218954 +329875 +274163 +230641 +268162 +282690 +606624 +327846 +200973 +241818 +334533 +274932 +317132 +218148 +266097 +612506 +315166 +249939 +243737 +297424 +251528 +270428 +294010 +217745 +283676 +288205 +264476 +228916 +317893 +235759 +257059 +298386 +325630 +274206 +335925 +619606 +213106 +324401 +289958 +247303 +614278 +621541 +220104 +221222 +273223 +300606 +9741 +256444 +609043 +270489 +255574 +317715 +231720 +216529 +624849 +211285 +254456 +267117 +617747 +300565 +272021 +305690 +230719 +253127 +612724 +327647 +323059 +286577 +224853 +209161 +328288 +299190 +285420 +252574 +266920 +303900 +248652 +211404 +630926 +260901 +253737 +265669 +607787 +305653 +225368 +227943 +255466 +274920 +630734 +339446 +247959 +338953 +618429 +607400 +224644 +306000 +244264 +310842 +245133 +308974 +622549 +228650 +260791 +331494 +263293 +321485 +328052 +621571 +322817 +612572 +256580 +336716 +315720 +300192 +262305 +251862 +335514 +266208 +286333 +266222 +299861 +268238 +340511 +297486 +270197 +305380 +605550 +270005 +251791 +332913 +274519 +232064 +246067 +206269 +619166 +612451 +273844 +234151 +221753 +622716 +613941 +325981 +230662 +284500 +231007 +246074 +612339 +253654 +225594 +258769 +217805 +298138 +256593 +266640 +260034 +226567 +208643 +223401 +214018 +614794 +611099 +243851 +226604 +338580 +621940 +200580 +254944 +263731 +275846 +220172 +273621 +328361 +627755 +324609 +242114 +286989 +620084 +318415 +8413 +326496 +267638 +304153 +257635 +244335 +230964 +273868 +213319 +273469 +245020 +253603 +225407 +609734 +269322 +210103 +632226 +299659 +244443 +215167 +235728 +247685 +631787 +618661 +215006 +215910 +300774 +295273 +230473 +257521 +259374 +314473 +287353 +235879 +240487 +240324 +610905 +304761 +622863 +632524 +600204 +303059 +269784 +263162 +290923 +603394 +605353 +627008 +322217 +318927 +301895 +317232 +609534 +627723 +268119 +623085 +328847 +625720 +294250 +328993 +235415 +303467 +301807 +263942 +220928 +276565 +273466 +313797 +247482 +223477 +318970 +242345 +220832 +268199 +618343 +252457 +287122 +229760 +302868 +216715 +252296 +257539 +305760 +312081 +324519 +276916 +608049 +205302 +280421 +241262 +627684 +303564 +263335 +329753 +294294 +230811 +608934 +608096 +601806 +612587 +338821 +224868 +313114 +224849 +247798 +272737 +273805 +308481 +201651 +286400 +617279 +624968 +615126 +274012 +267273 +231029 +340258 +324449 +312848 +252857 +265810 +207844 +222889 +236334 +609448 +239455 +628150 +285153 +229871 +278570 +259559 +626732 +291080 +309548 +237833 +285205 +317883 +245347 +616695 +309516 +326582 +224297 +269110 +276861 +248120 +200121 +255266 +628138 +618234 +289481 +629370 +254261 +328030 +246903 +336126 +218499 +622934 +289053 +286337 +613647 +313014 +240387 +318632 +238690 +318048 +300721 +279170 +624562 +626025 +208162 +234175 +221404 +316494 +210967 +200274 +282329 +608013 +276809 +241592 +253502 +609800 +259085 +291201 +247056 +321924 +603744 +326051 +301979 +317790 +328753 +310311 +219429 +326160 +247509 +274303 +617930 +246005 +312941 +296472 +245171 +311824 +222156 +623305 +233805 +318627 +340793 +208841 +283525 +236805 +310242 +288925 +304043 +326176 +328784 +284432 +239351 +256467 +256366 +311994 +258300 +330603 +623061 +631782 +299208 +335508 +297497 +311335 +245479 +263075 +268626 +266290 +276836 +336454 +612096 +238084 +609440 +281098 +301239 +219606 +299741 +236745 +613799 +277757 +610782 +258407 +314909 +8666 +258759 +607182 +327341 +312762 +921672 +613167 +287594 +298838 +251702 +612593 +617965 +604296 +242438 +618452 +609564 +325952 +268367 +214793 +301268 +626470 +288674 +235999 +237046 +247810 +626147 +235272 +316453 +230756 +317548 +275599 +219982 +323677 +268292 +632536 +262040 +611687 +259737 +274160 +327306 +222279 +279075 +233316 +219299 +301094 +340227 +277053 +314212 +609607 +294514 +215597 +298780 +228725 +630863 +230735 +255865 +317767 +255307 +327287 +263007 +326398 +226369 +252124 +624074 +266682 +298065 +275329 +326847 +220034 +269499 +339228 +230570 +261575 +328542 +302734 +235012 +329700 +307267 +300333 +281595 +285446 +260507 +253731 +268307 +256401 +255860 +606724 +336559 +219743 +299740 +239517 +605428 +263412 +628406 +287429 +211983 +221437 +233482 +227977 +266308 +224460 +214962 +276132 +240385 +221540 +285462 +242933 +315842 +626897 +307169 +339392 +612131 +615253 +310184 +245988 +291227 +252829 +600368 +336452 +268269 +324440 +238701 +337732 +270447 +265684 +296681 +268383 +235233 +249100 +605209 +330669 +313668 +240007 +267281 +299996 +252242 +622571 +253644 +272281 +242293 +608901 +618593 +337713 +606198 +300343 +235572 +254093 +286801 +241959 +235995 +334592 +231055 +613804 +282693 +300318 +331327 +320923 +220704 +230663 +269122 +239342 +246785 +216366 +314018 +605804 +607177 +300272 +293731 +252431 +265478 +259663 +220847 +268280 +246754 +268426 +242932 +297880 +249291 +288263 +318550 +229514 +340642 +276358 +211732 +300692 +283277 +303862 +256441 +254069 +283201 +224088 +299983 +281148 +251606 +301263 +237917 +238177 +274444 +234119 +301572 +607721 +269860 +287098 +267464 +287386 +286547 +329458 +218105 +267237 +627197 +323414 +330165 +281511 +221060 +243054 +266656 +220423 +280478 +254129 +221041 +223998 +251954 +212879 +600645 +279102 +237253 +607996 +220895 +316566 +274476 +325919 +302628 +625827 +276957 +609575 +271938 +340904 +234161 +318036 +627630 +213131 +628097 +602860 +231287 +608099 +289137 +264143 +275038 +625626 +629376 +260822 +234383 +216809 +252078 +614195 +234094 +313769 +253642 +221058 +334218 +285950 +295174 +311502 +314193 +236132 +240629 +231052 +302503 +303312 +212831 +272487 +618285 +628146 +298947 +281490 +321567 +256377 +329596 +282826 +230857 +252381 +329328 +278955 +210405 +284553 +307942 +224342 +301489 +311522 +230984 +286641 +219914 +284740 +302197 +607774 +327817 +608906 +608720 +239962 +267687 +225229 +607665 +627191 +312631 +626632 +267161 +629038 +612531 +256919 +302155 +230626 +602041 +254801 +236612 +619470 +608373 +311778 +605937 +602773 +255140 +244240 +120214 +273362 +618101 +609039 +278124 +283833 +293529 +273392 +335002 +263946 +217701 +223111 +257293 +254060 +623645 +285492 +253461 +270704 +244230 +329195 +322491 +605041 +608524 +238214 +603028 +262058 +226016 +284561 +279697 +205049 +271927 +315744 +291734 +286852 +309169 +322250 +221289 +266831 +324634 +214936 +332200 +246648 +220260 +203872 +308363 +308316 +267132 +200888 +256627 +229716 +248320 +267864 +230803 +260011 +220540 +257475 +601876 +263061 +316165 +324630 +626829 +233950 +322972 +247295 +236184 +315982 +623403 +332214 +295918 +622735 +254470 +229517 +295823 +279401 +221808 +239530 +258990 +206807 +259158 +253534 +275433 +622214 +256340 +239606 +255114 +223461 +307441 +261270 +315007 +221003 +256420 +613665 +218793 +225967 +911333 +236913 +271910 +236954 +627547 +242181 +234290 +249243 +265122 +230894 +257004 +625064 +605087 +223241 +302803 +605728 +613667 +315274 +210867 +299875 +291867 +298786 +305299 +268291 +329430 +223290 +331631 +323422 +247674 +330114 +277102 +627433 +268116 +626279 +320598 +255878 +606046 +212043 +237645 +224058 +254446 +325703 +256311 +309450 +607295 +607139 +322113 +256417 +235874 +315877 +227477 +235837 +244232 +621886 +232533 +611092 +303609 +224804 +277016 +274825 +253048 +299392 +239784 +266061 +257707 +224931 +219706 +629414 +246643 +226858 +313871 +215934 +627263 +315640 +258109 +307081 +308454 +219491 +263506 +300045 +260352 +252730 +247565 +221448 +267256 +629496 +304284 +234608 +230890 +306615 +256545 +232975 +266326 +261769 +280995 +313327 +256544 +305305 +261967 +247762 +284321 +607785 +289603 +209801 +230725 +618349 +249379 +611742 +208250 +316682 +267386 +224176 +291766 +283111 +265940 +258754 +607292 +321549 +321107 +211779 +275283 +218598 +295576 +301368 +253389 +210514 +265546 +318515 +288241 +238512 +229042 +326421 +317325 +314247 +301616 +301443 +285189 +265073 +241640 +239521 +267777 +293511 +339186 +328770 +232913 +259504 +285150 +285901 +266059 +245319 +286125 +291364 +279898 +245743 +625977 +308364 +285259 +120227 +326660 +256230 +291679 +245121 +626794 +263913 +331452 +228728 +247723 +222333 +225955 +611373 +286933 +329308 +215372 +271921 +209205 +322369 +601180 +220527 +606805 +606861 +632487 +236811 +910831 +228169 +222051 +237835 +614577 +340163 +274916 +314891 +220432 +330222 +252756 +336940 +256483 +293476 +259867 +213841 +228801 +8599 +313353 +267414 +255170 +301519 +618025 +224051 +613588 +228053 +228647 +628959 +283464 +256591 +294650 +228254 +248828 +238548 +265747 +324408 +912263 +291216 +295185 +604251 +246775 +250124 +601852 +268314 +266106 +278616 +282589 +328264 +303482 +271875 +246335 +334454 +623783 +297882 +253221 +333442 +310651 +316736 +340551 +281473 +287530 +268777 +290925 +340828 +242905 +220074 +609836 +613549 +622468 +627446 +613465 +315902 +279723 +608740 +909920 +230831 +263207 +259014 +600841 +275078 +617060 +287716 +619993 +264173 +233015 +625814 +608926 +306447 +298457 +626034 +626117 +222970 +627372 +305853 +223317 +211759 +270586 +221056 +252184 +276781 +632277 +286719 +269289 +246798 +233174 +292259 +219828 +280469 +230232 +222048 +231485 +274090 +283798 +279818 +303022 +623733 +341222 +219636 +339897 +605767 +300676 +248005 +255386 +236395 +279081 +618224 +603458 +255459 +249690 +619411 +246673 +228746 +276969 +614057 +326665 +617306 +622868 +288146 +235827 +615735 +632445 +278860 +221046 +609465 +327908 +289615 +215985 +298761 +201052 +275063 +300582 +276136 +261057 +613960 +341197 +225553 +242273 +291125 +310451 +613800 +627266 +612218 +288701 +301011 +609349 +631696 +605036 +246678 +625718 +255820 +233985 +268144 +274037 +320637 +273438 +293836 +283794 +234629 +293890 +236182 +222077 +295118 +260694 +227674 +219678 +313116 +294665 +293850 +323475 +623637 +334098 +301476 +293834 +218626 +301370 +256667 +217891 +612052 +307869 +248815 +216803 +242008 +249290 +329962 +310312 +253474 +607616 +226756 +224814 +239476 +287080 +222152 +276993 +257916 +240080 +234076 +301196 +241744 +229575 +612545 +610456 +247630 +630680 +631507 +315562 +625730 +606111 +340055 +624672 +317989 +324600 +324595 +272919 +603941 +623501 +613202 +302739 +606476 +625451 +212311 +318973 +247877 +239379 +315525 +243756 +619660 +235745 +217873 +217480 +232651 +264329 +201880 +268333 +299192 +224878 +311565 +236694 +337146 +909954 +305532 +248605 +330770 +327465 +604344 +228293 +217809 +337654 +214181 +237191 +262067 +266800 +265506 +211887 +285739 +204722 +608978 +214003 +247176 +270625 +267907 +293992 +268422 +241762 +316552 +249012 +306406 +249163 +257542 +221281 +627794 +227355 +265435 +273192 +257466 +615785 +288466 +267854 +623553 +241402 +324247 +317334 +241405 +323195 +302915 +229108 +300186 +616499 +209437 +287863 +316639 +265743 +247644 +236240 +318920 +626055 +247624 +285533 +269222 +320731 +236358 +284515 +318704 +278428 +302202 +312290 +326112 +327579 +290526 +214013 +254410 +231267 +274481 +270616 +323516 +333800 +313284 +216710 +277068 +608930 +202145 +228313 +201067 +237643 +224030 +278368 +331018 +616121 +285296 +239302 +314087 +618548 +323267 +269374 +600067 +262078 +309846 +249021 +330888 +316067 +211640 +604974 +285404 +285870 +235616 +604659 +623906 +241069 +267916 +611979 +281166 +215252 +309674 +249313 +287993 +312301 +229779 +299865 +241270 +261378 +254044 +268288 +298664 +301202 +257876 +215181 +267093 +224765 +267675 +241995 +321919 +320333 +283141 +230829 +224101 +331107 +221685 +205135 +261605 +236788 +244121 +206117 +259312 +244597 +217643 +628691 +632858 +211708 +266445 +318708 +287532 +331171 +333924 +267934 +623151 +275589 +605676 +230010 +237671 +220668 +323241 +238640 +326006 +228513 +275060 +608490 +287703 +608638 +268304 +258682 +283503 +213599 +318736 +628552 +238778 +227458 +223344 +246556 +255070 +325327 +247522 +226462 +314935 +247115 +257695 +289841 +289712 +624280 +623720 +263878 +311932 +628151 +286462 +248092 +308428 +262263 +286413 +295985 +261152 +336440 +237241 +258992 +207807 +247602 +249898 +603002 +314031 +213374 +261726 +305280 +286100 +622749 +252657 +237062 +241861 +278213 +340983 +287143 +293848 +268004 +316746 +228087 +221085 +268171 +265395 +627351 +310790 +257082 +293662 +605650 +237984 +610419 +226187 +217927 +231717 +614964 +219612 +267931 +215009 +216125 +211624 +276798 +323636 +340318 +281906 +279735 +224909 +217246 +321707 +328170 +221035 +622483 +237339 +295039 +228292 +608243 +269210 +295153 +252220 +256736 +272732 +237365 +267369 +615608 +611089 +622428 +294035 +285026 +250072 +317555 +323420 +222378 +288481 +236716 +233846 +240994 +229883 +280532 +321777 +615755 +280010 +268498 +228827 +625508 +312219 +329363 +334470 +221946 +278794 +245226 +310018 +618326 +602306 +252759 +253729 +608129 +298022 +257159 +305377 +252012 +285712 +224753 +239640 +251072 +327710 +293560 +256965 +247599 +322977 +604778 +606042 +232249 +328568 +618046 +300614 +218684 +224801 +250136 +629771 +282769 +309129 +255827 +287872 +295463 +913033 +212287 +628039 +284625 +610727 +288298 +251383 +325325 +322682 +248565 +287087 +285897 +230862 +340507 +232305 +260809 +289714 +9802 +233358 +321498 +631577 +618010 +623703 +295644 +209157 +284534 +607656 +615722 +314978 +255569 +266544 +317450 +603502 +295775 +212498 +227750 +285245 +215007 +291722 +300303 +254987 +327875 +241741 +276952 +235902 +323777 +223592 +317316 +287366 +334763 +294095 +263476 +621368 +307760 +231072 +218132 +215370 +624010 +314768 +216714 +289384 +330486 +237667 +233294 +287411 +220656 +216036 +622527 +294608 +241342 +314889 +212104 +236216 +310339 +256601 +269923 +262247 +271838 +281614 +315639 +631582 +211257 +318531 +301728 +607685 +298336 +214699 +232172 +230635 +273268 +235381 +212827 +612765 +201095 +260849 +284294 +272390 +254511 +247371 +601070 +622888 +308665 +279438 +260210 +234117 +210316 +323099 +235472 +241669 +312306 +270371 +245267 +296474 +223865 +260086 +612748 +611187 +301625 +210680 +303740 +312253 +234330 +263783 +236234 +302919 +293899 +300217 +205005 +215297 +267259 +205357 +628934 +318770 +318729 +256523 +324621 +228740 +223423 +337057 +265697 +201729 +278246 +310765 +289887 +308912 +254227 +251276 +257859 +278850 +326649 +244305 +268134 +626061 +307320 +249812 +319360 +221365 +230748 +623006 +267255 +237228 +233409 +249710 +605580 +219291 +260051 +630665 +290888 +618113 +323091 +329283 +631510 +242635 +296345 +243046 +256453 +340391 +609554 +309395 +308393 +309064 +630690 +312649 +233346 +267155 +303254 +200512 +321121 +285073 +220936 +339513 +237651 +608153 +265967 +632217 +221671 +321366 +603676 +291762 +287767 +611488 +624370 +263240 +340015 +291060 +265549 +275025 +619349 +273773 +268392 +265841 +214261 +216271 +316969 +624958 +311523 +233980 +9898 +336152 +611591 +218647 +9849 +614708 +272134 +613256 +247745 +254256 +257023 +256470 +261317 +632469 +312850 +293831 +303717 +259709 +314032 +337251 +257593 +291844 +611538 +268113 +252018 +316795 +311806 +334274 +260965 +214324 +330552 +294963 +224495 +265603 +295254 +281627 +239328 +262413 +327635 +324340 +628533 +237862 +300948 +259569 +612438 +207419 +608775 +609490 +607728 +310750 +216513 +218331 +295485 +230676 +295412 +245178 +288202 +311257 +248061 +315530 +335587 +248273 +262059 +203428 +322739 +615653 +300115 +219040 +230828 +336456 +221564 +223605 +282118 +299566 +316238 +326781 +222800 +243868 +233681 +614492 +602570 +621353 +244463 +305436 +288429 +631011 +270139 +228754 +216774 +291432 +223894 +321836 +284884 +255298 +219480 +220098 +327343 +618154 +612552 +624164 +322124 +221148 +239217 +618563 +614034 +302005 +204263 +294154 +279389 +291068 +313976 +626491 +224838 +295191 +332274 +282521 +220664 +322709 +260936 +335542 +338060 +233479 +282743 +261227 +265971 +221491 +315105 +269665 +273105 +311092 +302314 +200190 +208661 +610401 +304755 +260860 +216820 +244246 +266608 +617700 +267219 +325929 +279558 +604691 +253079 +911424 +313339 +334011 +610793 +617805 +302648 +609694 +8526 +334360 +288526 +290022 +329017 +224572 +244166 +341089 +253739 +640714 +322078 +294962 +218830 +303837 +250117 +604305 +329280 +278138 +313972 +319017 +612308 +629682 +226007 +224047 +268227 +219632 +300081 +299490 +609132 +295244 +319132 +614048 +249658 +206205 +302494 +339095 +318621 +291528 +333701 +618333 +619939 +300768 +324410 +256570 +315564 +222064 +251617 +268412 +296658 +243647 +287398 +217275 +618520 +290040 +284024 +312117 +262574 +314653 +247684 +235585 +309712 +267768 +316384 +331112 +619039 +286276 +233976 +252589 +262010 +204472 +614204 +626555 +302315 +606965 +268692 +274325 +223243 +244492 +335915 +251767 +231495 +316331 +286570 +262205 +284926 +339462 +228685 +246646 +254747 +606058 +285613 +294537 +218329 +293615 +235604 +614244 +284223 +612250 +215781 +334419 +227947 +246334 +234014 +201472 +605574 +273816 +632472 +606838 +234914 +334048 +269300 +605607 +239382 +283755 +224017 +238988 +306686 +293796 +276913 +252095 +228659 +315407 +287094 +266535 +200252 +908899 +270460 +226415 +232245 +612564 +234987 +300761 +229275 +221165 +223451 +229958 +212985 +235058 +628183 +605608 +299091 +221761 +245113 +316615 +215098 +272375 +240497 +298657 +330283 +248195 +226195 +267264 +320034 +278732 +251018 +619806 +237924 +228229 +231747 +262037 +618094 +257644 +230906 +321323 +221123 +221928 +223497 +617053 +287923 +290870 +229287 +245202 +228203 +265364 +284613 +275392 +259796 +278367 +287432 +266172 +289159 +273965 +251766 +297847 +325965 +320602 +633174 +235224 +253970 +321918 +246800 +328421 +239506 +308637 +605923 +302451 +228005 +299293 +285368 +258339 +318117 +267746 +234027 +213669 +615954 +211686 +304925 +301096 +308672 +263246 +266616 +273861 +297504 +239621 +237636 +224885 +631673 +613574 +322056 +212488 +255264 +628687 +291062 +623868 +328079 +208116 +237407 +299500 +260821 +239953 +230381 +322089 +218732 +258713 +219641 +205349 +602133 +302505 +641543 +237449 +232366 +314581 +337569 +268776 +201068 +609909 +256528 +218246 +298257 +283686 +632539 +232959 +320298 +256955 +240885 +285836 +302139 +303457 +222164 +330111 +213577 +278433 +613781 +274146 +315134 +211928 +239223 +302441 +609149 +294960 +221244 +201862 +600838 +614897 +205256 +249826 +223166 +284915 +321271 +236323 +279779 +274501 +222995 +247006 +275547 +254297 +631986 +611951 +334030 +325364 +274326 +267897 +210021 +611709 +251396 +617511 +602923 +280053 +326476 +247521 +288143 +215434 +219009 +629251 +257666 +320974 +315066 +609198 +329548 +331709 +278365 +231083 +255851 +216528 +287026 +612546 +284405 +293692 +288881 +240891 +632614 +316838 +321545 +200999 +311179 +273034 +224823 +220941 +328231 +625984 +312450 +287568 +230855 +247825 +606352 +287352 +326245 +235086 +618103 +226977 +314194 +252682 +263455 +229603 +255073 +287711 +615172 +235092 +338875 +255768 +214469 +239509 +615739 +294905 +258542 +219885 +249298 +340929 +273003 +240009 +299517 +263374 +242013 +610988 +218699 +256617 +612665 +289511 +266473 +8731 +603960 +262824 +218916 +283216 +9688 +304235 +262053 +602428 +340040 +246815 +273121 +266214 +322744 +256997 +212250 +609067 +224251 +247743 +266504 +200880 +313122 +249612 +202167 +293699 +313737 +600394 +300089 +269099 +307688 +603049 +221091 +313100 +230955 +251722 +224737 +248267 +299298 +266423 +333998 +288577 +284892 +229127 +311399 +614727 +284848 +214994 +230569 +231045 +605119 +229813 +605379 +303573 +300194 +260371 +619833 +261483 +233890 +274966 +312216 +615905 +283396 +247162 +286831 +310203 +236623 +242617 +623046 +615246 +226172 +236536 +283567 +315659 +617595 +268247 +262569 +263183 +249227 +255666 +238804 +328379 +607858 +223156 +607510 +629263 +200214 +314159 +245071 +318997 +318240 +632239 +293674 +268177 +336291 +604752 +252877 +232816 +230326 +600065 +222618 +301668 +227464 +300368 +264666 +613877 +273190 +242411 +238978 +302453 +209578 +277025 +297799 +307215 +258813 +211662 +256495 +256479 +325329 +241951 +225551 +275861 +312845 +270722 +625915 +311695 +235626 +318499 +241523 +304210 +222317 +320441 +628372 +239990 +332462 +295172 +317631 +233659 +274352 +281532 +268429 +331344 +624841 +611796 +330381 +327706 +217485 +221413 +245418 +261861 +281877 +260711 +224282 +631079 +205509 +222228 +218659 +294965 +630023 +253831 +219286 +218869 +602541 +275182 +256485 +282413 +314326 +632860 +289326 +605303 +298951 +318246 +276284 +212671 +280030 +311610 +222199 +268088 +243406 +274409 +225282 +220694 +236250 +622936 +260441 +625167 +339402 +618871 +630861 +628858 +223143 +238665 +273772 +329033 +241783 +338271 +294494 +266176 +252579 +273992 +606134 +261982 +212877 +328060 +623446 +254983 +291787 +306681 +241118 +267173 +632222 +315349 +310938 +609321 +298865 +311929 +323217 +284862 +246666 +276116 +604842 +212844 +202896 +215554 +247567 +625039 +321491 +244684 +334084 +626182 +289434 +298245 +334271 +322430 +236176 +237590 +632479 +227634 +211948 +296688 +331389 +604148 +252847 +247401 +8585 +289719 +217067 +262241 +617253 +267198 +608893 +295300 +302836 +300968 +326342 +290492 +221550 +233884 +209656 +605356 +244725 +270647 +273341 +238055 +273867 +217429 +301754 +252318 +312797 +306260 +220771 +301230 +320270 +609642 +618263 +272853 +320689 +227156 +253990 +278558 +253770 +312829 +316596 +277011 +286692 +298588 +333042 +230926 +330723 +244557 +614578 +220535 +626749 +238541 +269309 +312657 +269796 +612585 +278267 +324445 +120222 +268921 +249232 +608921 +235461 +259108 +298555 +264207 +603542 +626111 +218259 +303522 +260058 +236699 +289285 +294046 +255472 +313979 +339032 +317862 +312844 +600845 +266379 +603425 +298127 +295645 +330195 +251380 +304914 +233672 +304217 +327582 +216746 +283632 +261248 +226438 +327697 +229036 +327243 +283543 +237255 +618792 +604674 +214107 +300146 +224897 +337258 +239694 +297929 +339984 +256759 +337596 +612644 +275840 +326943 +600792 +216166 +233199 +236027 +330825 +261532 +282846 +219522 +328330 +241985 +254304 +253303 +254992 +282083 +320683 +255267 +607868 +274575 +328536 +277829 +312830 +255409 +252986 +604140 +278793 +206570 +601743 +228344 +220617 +315454 +273365 +602694 +217941 +632433 +285192 +628545 +261114 +219333 +219055 +301257 +329847 +201284 +247541 +628343 +313193 +335380 +291242 +305564 +212891 +294115 +627948 +286836 +263741 +286713 +623119 +323312 +230399 +100205 +611421 +338543 +268315 +298861 +330975 +605891 +246799 +619491 +284518 +219558 +315054 +304987 +251173 +284460 +211485 +295835 +610961 +312758 +611517 +258440 +332885 +319000 +256899 +320013 +253643 +206710 +230548 +262863 +235612 +272481 +236231 +330396 +254618 +270780 +262184 +211927 +318966 +628245 +624857 +229604 +261732 +327402 +300819 +624097 +310482 +235798 +228661 +263671 +603824 +629586 +205854 +632417 +621195 +253744 +609146 +281824 +275212 +237720 +255227 +248615 +630837 +618558 +224808 +622845 +291650 +276275 +611332 +263630 +273119 +231099 +247330 +275768 +329800 +307866 +604779 +226701 +245819 +224009 +246698 +232523 +307079 +275855 +286737 +245500 +317714 +269688 +623372 +311549 +327488 +239416 +262455 +207858 +908199 +221314 +336917 +336938 +251373 +257245 +285099 +605404 +626643 +304255 +234522 +299386 +320939 +337567 +286140 +605632 +311710 +227073 +257444 +294729 +279068 +227290 +283314 +245278 +254326 +299242 +608058 +298003 +282932 +262030 +248753 +224770 +625631 +223071 +280157 +605277 +322259 +260667 +606923 +315308 +241378 +257647 +602515 +283670 +232212 +274063 +632881 +120228 +320090 +299237 +320360 +265863 +301507 +299731 +9848 +268342 +624040 +237210 +244087 +278202 +253824 +300025 +321794 +286130 +216355 +227897 +275681 +284725 +622659 +318273 +227680 +305272 +329004 +254647 +304003 +323402 +299280 +329339 +256764 +244388 +297444 +295162 +273292 +240317 +288173 +238486 +285501 +289139 +254027 +216331 +268299 +326792 +268639 +235303 +309980 +609143 +215024 +606326 +612742 +230307 +224375 +219081 +641592 +290846 +261905 +314056 +627473 +607109 +606971 +624969 +239350 +614765 +223153 +334021 +212446 +218868 +247970 +253716 +237695 +309502 +300965 +616027 +259735 +249314 +239471 +244767 +298099 +601783 +275936 +322669 +219123 +632694 +276032 +250167 +211938 +273155 +249520 +280555 +285689 +220702 +312325 +256603 +285224 +239313 +262330 +333595 +283746 +221167 +261698 +334273 +278042 +606080 +320115 +219856 +236009 +314731 +629613 +284949 +331952 +277143 +631132 +609395 +314272 +235353 +337830 +621213 +226507 +240123 +260111 +318275 +236948 +263846 +220385 +233651 +265134 +298156 +628315 +248909 +286981 +244348 +274895 +255490 +202337 +336749 +611232 +276879 +224845 +253952 +339871 +251630 +318931 +230638 +255819 +630978 +620129 +295603 +279520 +605142 +268111 +286976 +209116 +265601 +284940 +312251 +203039 +227303 +318424 +318552 +275289 +258604 +300820 +313749 +218822 +306395 +281961 +230394 +256535 +307270 +232600 +215455 +252944 +218138 +274783 +287056 +333020 +284455 +315040 +305020 +270011 +267200 +214570 +299755 +216695 +265103 +275052 +616882 +276926 +220505 +222021 +284181 +219367 +287755 +290562 +339109 +285089 +322953 +322146 +216181 +248669 +600908 +322788 +247447 +253924 +632893 +203994 +229801 +605151 +232016 +233325 +228029 +339834 +256486 +255772 +609892 +285204 +337479 +229830 +217811 +226814 +299302 +312795 +257899 +285051 +610542 +262049 +273895 +616417 +328067 +239301 +281501 +239543 +297679 +257867 +230421 +609396 +278408 +318088 +221030 +272427 +327228 +632853 +295097 +621270 +233339 +609667 +602186 +260117 +237855 +274078 +624526 +268904 +247548 +239432 +220088 +314394 +325940 +276728 +612645 +311876 +613654 +289191 +630745 +241025 +308468 +308934 +298238 +302603 +909389 +291812 +619086 +313695 +254974 +234200 +339253 +278320 +239599 +224916 +259068 +246172 +282559 +282638 +612493 +233158 +230962 +271986 +235688 +622711 +226010 +265634 +314383 +610320 +223824 +314284 +330364 +313169 +202182 +608695 +248095 +262469 +278152 +624439 +208631 +252234 +265156 +200285 +328600 +305134 +227390 +336724 +227631 +241382 +230310 +254239 +260353 +287438 +255816 +219654 +280271 +257914 +303039 +233157 +282139 +600382 +307812 +603809 +237739 +627783 +299854 +319818 +226073 +231135 +306920 +227656 +293808 +215353 +253214 +260844 +606546 +632274 +241242 +211382 +614960 +237096 +266588 +321403 +226718 +309540 +224898 +611063 +337739 +261034 +299732 +284126 +300674 +318597 +233996 +612576 +310912 +267100 +608555 +218123 +235502 +317512 +607078 +100016 +312068 +236521 +328270 +282574 +242146 +219265 +321985 +341139 +226180 +299810 +284331 +268300 +252605 +255467 +232139 +266306 +624351 +611247 +272178 +310920 +229063 +296671 +287462 +300685 +321586 +312474 +616015 +287752 +319055 +277182 +213543 +326736 +336079 +312789 +271847 +202584 +220272 +318225 +221707 +289454 +296410 +912163 +226506 +626466 +622883 +275111 +234843 +312818 +609883 +321035 +252846 +255730 +331294 +618091 +624433 +334845 +320823 +318337 +243881 +275012 +610451 +314697 +250268 +200130 +288653 +215064 +272247 +630006 +612058 +242670 +629320 +259141 +320294 +616160 +251802 +239325 +310886 +237026 +298019 +318979 +228319 +626986 +267959 +262493 +339828 +315170 +317699 +313652 +616564 +630846 +248594 +224890 +212792 +610532 +242309 +259091 +266634 +912847 +293991 +297727 +601963 +273701 +223936 +200301 +228734 +258509 +322139 +266545 +310372 +332769 +604263 +201924 +263472 +623608 +299726 +333936 +302031 +287732 +281633 +258753 +262663 +909181 +247550 +262285 +308370 +230826 +631149 +236739 +257289 +239993 +609060 +308765 +290597 +318714 +230739 +272276 +309006 +291784 +261776 +222305 +329761 +305477 +287514 +616305 +624673 +318051 +334942 +235098 +628077 +269774 +619583 +336936 +220507 +229773 +330301 +223060 +331958 +255741 +230495 +288557 +287704 +628605 +239159 +308792 +273193 +911374 +276980 +294713 +332199 +272821 +286047 +334988 +613236 +246994 +620270 +299016 +324571 +221638 +294947 +276914 +232989 +220558 +294852 +214380 +222983 +603288 +241548 +331605 +248364 +276147 +261166 +333659 +235493 +315158 +236549 +276322 +314180 +230484 +273610 +251304 +212814 +241187 +601716 +242244 +334960 +230917 +612955 +263836 +256491 +625163 +269706 +308952 +229289 +340117 +307783 +331576 +612869 +261954 +318329 +612294 +219852 +245454 +627386 +230777 +281359 +625835 +623711 +215866 +231167 +228758 +323020 +263361 +283615 +329908 +320969 +261971 +309834 +227793 +295709 +287465 +618334 +302277 +220077 +219993 +605102 +320659 +621992 +295371 +226225 +289198 +619159 +322104 +303848 +229915 +302605 +263091 +318053 +623767 +619209 +268441 +295994 +9670 +260347 +607697 +624296 +627545 +623328 +293993 +607114 +334034 +203161 +252210 +246980 +271739 +239349 +321482 +331416 +275386 +216546 +291120 +287811 +323452 +613318 +220579 +315032 +225744 +339231 +242424 +250388 +230464 +120215 +609086 +240852 +275604 +239143 +333721 +278469 +227078 +602633 +258888 +313553 +611887 +269725 +316532 +614182 +619012 +272176 +321913 +601933 +253602 +221694 +631926 +314685 +330460 +303214 +612743 +607379 +631792 +217937 +315485 +330792 +219254 +289126 +284961 +306425 +258405 +339970 +273220 +237120 +286717 +260897 +615187 +627727 +630123 +219834 +325936 +253845 +230845 +306488 +257641 +273673 +250277 +200720 +218111 +228893 +211821 +238273 +312497 +279828 +245332 +230870 +219755 +330675 +259328 +227763 +269463 +237398 +631129 +236157 +276562 +217405 +607882 +315970 +227463 +322120 +610795 +262595 +217139 +268167 +289497 +228999 +273485 +242416 +238969 +329258 +219266 +624183 +908002 +314762 +300028 +315997 +203459 +252811 +236959 +286674 +268105 +335377 +307397 +248303 +625592 +287661 +252191 +606818 +300957 +913877 +252159 +613981 +614328 +607011 +316687 +216076 +242095 +268270 +321125 +330709 +243826 +219943 +909581 +268108 +303785 +226456 +236621 +231143 +223478 +281447 +268211 +216736 +291840 +609403 +334590 +608322 +228439 +237621 +622019 +609495 +330692 +328178 +243115 +236605 +244422 +323883 +268390 +611115 +221755 +227279 +288383 +214954 +604387 +232545 +612407 +606614 +269238 +617779 +605167 +314334 +623912 +608393 +216937 +600708 +314175 +621277 +316383 +273427 +301144 +303417 +285363 +323260 +627515 +609409 +613795 +249215 +616919 +231982 +219819 +238885 +207685 +304008 +237443 +269961 +306682 +247555 +619167 +261562 +617837 +285119 +223367 +253254 +268739 +623486 +221453 +237461 +237065 +298976 +211690 +281191 +204643 +235655 +257720 +246906 +253112 +279100 +324448 +265287 +226824 +322145 +322886 +632556 +270327 +309792 +327382 +293605 +276074 +336155 +269124 +291371 +318725 +315041 +269211 +215543 +273266 +232631 +279850 +287723 +621216 +299089 +335684 +326814 +257241 +610951 +632084 +215320 +279185 +626845 +610741 +249588 +314951 +629958 +225662 +298073 +335037 +232652 +290876 +222994 +211727 +281056 +242928 +625472 +200187 +249236 +298337 +201666 +232287 +299111 +280751 +284441 +603719 +323961 +274964 +299035 +603437 +230941 +220546 +250623 +320445 +254277 +247448 +315631 +202022 +605134 +254465 +261449 +609112 +217976 +317601 +322581 +612638 +330462 +247688 +314548 +249700 +334493 +248569 +607197 +322350 +600211 +319011 +256823 +327412 +627990 +234785 +261652 +218695 +230840 +628170 +237404 +223937 +303176 +318946 +327992 +336495 +324523 +286059 +277151 +272548 +322966 +307245 +266515 +225187 +606554 +219533 +251789 +302902 +230520 +281648 +322428 +618159 +275450 +309704 +289412 +329268 +320915 +618516 +242038 +220706 +265167 +244633 +286397 +216026 +233967 +314328 +328967 +285627 +287575 +337415 +229502 +315629 +306299 +243520 +231106 +313362 +239381 +236936 +627676 +303140 +602531 +911672 +336453 +298653 +226317 +295157 +241498 +313153 +281171 +912364 +240710 +307265 +239198 +231008 +286510 +300554 +246073 +618247 +300091 +600399 +315323 +216709 +304222 +228082 +268562 +242807 +271926 +249714 +600385 +233747 +262011 +267099 +303122 +224791 +223957 +246910 +628523 +219543 +327091 +296526 +230683 +618174 +258105 +201900 +271867 +287774 +228857 +318669 +299379 +306662 +221519 +611733 +214989 +223782 +321132 +235740 +625014 +610725 +272820 +271494 +329682 +269797 +275672 +299709 +316436 +294953 +250326 +261556 +255783 +314648 +314182 +607793 +326885 +339251 +604168 +278117 +339081 +335605 +290424 +245449 +285487 +282970 +247754 +218255 +632163 +221776 +613870 +216865 +301656 +243616 +273428 +605410 +275090 +324589 +318338 +208572 +232997 +307201 +210085 +276475 +300407 +247540 +260932 +237942 +244011 +609121 +254783 +281666 +268182 +251149 +270699 +315261 +267210 +239321 +296588 +220644 +605176 +230877 +600371 +223031 +312641 +272851 +229533 +240390 +243910 +232658 +254341 +250290 +606636 +269072 +237087 +605497 +268520 +219690 +618773 +256385 +262374 +286287 +239376 +265648 +301704 +305457 +331392 +282864 +218027 +338141 +328223 +219195 +252981 +326043 +262491 +245257 +606216 +213487 +612630 +301466 +314509 +272081 +298561 +327261 +610875 +624543 +283110 +217855 +625070 +256549 +334431 +323004 +230598 +268208 +609508 +202686 +254810 +253189 +302530 +631679 +246273 +309551 +285257 +327169 +212237 +286143 +243103 +624488 +619302 +217902 +605138 +302349 +247007 +269149 +312190 +211578 +260464 +236515 +320892 +280741 +251948 +299582 +206469 +294440 +312718 +226282 +229971 +337392 +604182 +631553 +332136 +324451 +221263 +277031 +248654 +298076 +216693 +262194 +314282 +254360 +218816 +326780 +295366 +233605 +270587 +325357 +308807 +212839 +310806 +241476 +261053 +250289 +293441 +330254 +289076 +278380 +287513 +310736 +243136 +243470 +629708 +278796 +316738 +295043 +200755 +626656 +618601 +301723 +627442 +249327 +606423 +221906 +331187 +205774 +248080 +201438 +287442 +301816 +305081 +245866 +605195 +202887 +612633 +314126 +276347 +264257 +226513 +327015 +268242 +261742 +279933 +239983 +600676 +247926 +615217 +334987 +322158 +241062 +262618 +288632 +294409 +308724 +600709 +275094 +223414 +231019 +320043 +620196 +273455 +301344 +240700 +270588 +334054 +234096 +295006 +263657 +285787 +284920 +237327 +263479 +248548 +273051 +308126 +232782 +615371 +220180 +606400 +246806 +318520 +268540 +300038 +307110 +296617 +287226 +256848 +285209 +207467 +318974 +256294 +281010 +274148 +236215 +320535 +337702 +294983 +236795 +310229 +307036 +278871 +295920 +249168 +267309 +252424 +254573 +286900 +224783 +605088 +613174 +618480 +252716 +246645 +607647 +625500 +267381 +268403 +301974 +288279 +284262 +313224 +237714 +274454 +248224 +235634 +288570 +278901 +316559 +309201 +298418 +220464 +602453 +308225 +301338 +253706 +312135 +247656 +267196 +238579 +315322 +242820 +311848 +226930 +306125 +320745 +255622 +608830 +631728 +324356 +202835 +215426 +223670 +230354 +228885 +612944 +604244 +236695 +236425 +332772 +289220 +323944 +321868 +247322 +253511 +303728 +251812 +254791 +215851 +617639 +234019 +205827 +262319 +294343 +608498 +299878 +318961 +276891 +293536 +237501 +243477 +624184 +235255 +276953 +613598 +231086 +207599 +299446 +309485 +227987 +223049 +304116 +624297 +255096 +908004 +313532 +245492 +235486 +300807 +252045 +223131 +257670 +615074 +268744 +219952 +219250 +227541 +624341 +214948 +220207 +333657 +304814 +217881 +265791 +254471 +332011 +299999 +617044 +605309 +304865 +628735 +314903 +238576 +322726 +249319 +213206 +600827 +241928 +253756 +285837 +233783 +205119 +255463 +323474 +623898 +259264 +625122 +317382 +226534 +281341 +286814 +331855 +324459 +326113 +602805 +255178 +607524 +307358 +312395 +293769 +315614 +272490 +329830 +301340 +620268 +628763 +229984 +301905 +251298 +9661 +293931 +245085 +608743 +265260 +254086 +218366 +607371 +238875 +608672 +265010 +280779 +632233 +230668 +253019 +615258 +254733 +260266 +313131 +279337 +221417 +604123 +256512 +251391 +242658 +334315 +211267 +245410 +224001 +285974 +319907 +271881 +328138 +620188 +289517 +284628 +253057 +289572 +272811 +235063 +606176 +207354 +241399 +236394 +328149 +256962 +232037 +250320 +275166 +277988 +230249 +233130 +252361 +626212 +616236 +256481 +218346 +277050 +279529 +233607 +305311 +603111 +242203 +218286 +309731 +220450 +201106 +622661 +267678 +300602 +321263 +326370 +262555 +262159 +221077 +332881 +274505 +294146 +275413 +615594 +297373 +333650 +611745 +245536 +236702 +221455 +322869 +236668 +618537 +265862 +229715 +340101 +208747 +606142 +236101 +625913 +255591 +304867 +207043 +622091 +312015 +201381 +268987 +264417 +223794 +631773 +245141 +270597 +221094 +262025 +272006 +201569 +263560 +221684 +623393 +325361 +302098 +228455 +273175 +272086 +304266 +630097 +237688 +618323 +268151 +200294 +244514 +609724 +323126 +234065 +216917 +314283 +232624 +228581 +275148 +623127 +307117 +235864 +329389 +213904 +281357 +232377 +237502 +286089 +269903 +263268 +218460 +324048 +334373 +621196 +257096 +256830 +230970 +316577 +232933 +619236 +226837 +315127 +339092 +317547 +273897 +293416 +911409 +271492 +335855 +220264 +300757 +213729 +323543 +248789 +612610 +604391 +324182 +299376 +628326 +230595 +267877 +281025 +271818 +630786 +203376 +231451 +229629 +284584 +293923 +329519 +219438 +226070 +227619 +317485 +338912 +321931 +305662 +318762 +262062 +257398 +608641 +618833 +268303 +620108 +256313 +283138 +609431 +218890 +332035 +238157 +327377 +608637 +247041 +262335 +301363 +299045 +280169 +240624 +201917 +302040 +631617 +603525 +300727 +222043 +611001 +226639 +304084 +201148 +324478 +253696 +205202 +622071 +287693 +213996 +331388 +335590 +622096 +224344 +297852 +244233 +211859 +236030 +260276 +249219 +228697 +619572 +201590 +340755 +217754 +224250 +261466 +624310 +328048 +315503 +306105 +622575 +242264 +301538 +302265 +220008 +261358 +287437 +333611 +248405 +607642 +609005 +265124 +331659 +275049 +265802 +287500 +617844 +256303 +276456 +615307 +237800 +224786 +254028 +328098 +245058 +232331 +284501 +253532 +288199 +8503 +268782 +235718 +245641 +276621 +336567 +233969 +228789 +274046 +283219 +211361 +226160 +313841 +277778 +246812 +329702 +300975 +275157 +609897 +269131 +240842 +269327 +222771 +333647 +214306 +276502 +314692 +218442 +295151 +606464 +286001 +286065 +306124 +247587 +295160 +619610 +629004 +251906 +230518 +306475 +610349 +340185 +307767 +269161 +286148 +341054 +620142 +613717 +626775 +269194 +267322 +256447 +233608 +322346 +309194 +310539 +283849 +287804 +211564 +331816 +318213 +329199 +316161 +602891 +260524 +284119 +216679 +228815 +262208 +632482 +269159 +291796 +255182 +251384 +274393 +272593 +617972 +279017 +281559 +309018 +323343 +340903 +323145 +294104 +268285 +229418 +286783 +230658 +289277 +245061 +315043 +256450 +216586 +220240 +340528 +301536 +203576 +264296 +623708 +260174 +602108 +265447 +618511 +332230 +305869 +219129 +274125 +231059 +293577 +268834 +253003 +323053 +600058 +224130 +273410 +200250 +600050 +315009 +309376 +228473 +618083 +613245 +217727 +326988 +334056 +203715 +619347 +623914 +603864 +619525 +322096 +234216 +256980 +257750 +224635 +311776 +224904 +247645 +315378 +605141 +235536 +626248 +271930 +250179 +624697 +603564 +235065 +322300 +306058 +609087 +258133 +274392 +248608 +244744 +301110 +609110 +262782 +230832 +223483 +265191 +609604 +628634 +220999 +265809 +277610 +339873 +308253 +233766 +320359 +298471 +237524 +200611 +272282 +315232 +268962 +245066 +339579 +340330 +278758 +220281 +253453 +233709 +219313 +221538 +321547 +317217 +239188 +321160 +320963 +294236 +237620 +239320 +631914 +262099 +326501 +247584 +267111 +286228 +262445 +297503 +339220 +324499 +243423 +208388 +254638 +303139 +214063 +612227 +255714 +312227 +312579 +606605 +226460 +297967 +294171 +213467 +332420 +251747 +329859 +247620 +332393 +120009 +322655 +253767 +296312 +262005 +328010 +604307 +249801 +239420 +273483 +268373 +222236 +203613 +329724 +338478 +319899 +312455 +236953 +221581 +317743 +609532 +223945 +298333 +252984 +309056 +272632 +249982 +331125 +220349 +218217 +617143 +317057 +236391 +605028 +246690 +261412 +283148 +221048 +280716 +265668 +284076 +218191 +238608 +213015 +630956 +341225 +323310 +258748 +335980 +201038 +226661 +627134 +600398 +249687 +283745 +293419 +229920 +308816 +217299 +202596 +299527 +236026 +253866 +271819 +232798 +252436 +332327 +120219 +331744 +276443 +222886 +275437 +275958 +334515 +322408 +235689 +226037 +248272 +319998 +302964 +609691 +317116 +609795 +235368 +324538 +315348 +231809 +238531 +267626 +260685 +323009 +324272 +631731 +624199 +220056 +327196 +200230 +217564 +216967 +260602 +212088 +310230 +245959 +340176 +302717 +321698 +241642 +218151 +322566 +333096 +249193 +252522 +322784 +242135 +245084 +314156 +271860 +263274 +626736 +235291 +289041 +336629 +312998 +299925 +625862 +231481 +622939 +309477 +236142 +230953 +225281 +201630 +628264 +233185 +256317 +604319 +602354 +314036 +293468 +288076 +310411 +328671 +245993 +603654 +309985 +625997 +222878 +235926 +210948 +285729 +618925 +249165 +267496 +607679 +263262 +276904 +321253 +616791 +323262 +313117 +321209 +631186 +218133 +226217 +273806 +246461 +201167 +243409 +285609 +632241 +215503 +317814 +335141 +298891 +219500 +312584 +321683 +612050 +216867 +315548 +237100 +274995 +605482 +615834 +322582 +329841 +228320 +257243 +616509 +249059 +217724 +246637 +316244 +245574 +268313 +254020 +218479 +251845 +604240 +241945 +298559 +340419 +246688 +275217 +236437 +265094 +248169 +268598 +278580 +234814 +219889 +244156 +329534 +256598 +265098 +612581 +631610 +294742 +337895 +262401 +313847 +328888 +323495 +327758 +629222 +262270 +323940 +611760 +290861 +340121 +251938 +340854 +276614 +254509 +260794 +263078 +308896 +603567 +241883 +613827 +220129 +251245 +315103 +314872 +321765 +320325 +336283 +256596 +243625 +311331 +266768 +235016 +208108 +314362 +204961 +327791 +317590 +314234 +631628 +631692 +312706 +302102 +335691 +219823 +232100 +913097 +604868 +221594 +260304 +302896 +267194 +312713 +222107 +249105 +239838 +247252 +200174 +261409 +283959 +201655 +277906 +224274 +297898 +308223 +339580 +286758 +245236 +209035 +254038 +230795 +219979 +309666 +238808 +331924 +298216 +284231 +327076 +230992 +245074 +202579 +311840 +308313 +223409 +242792 +261541 +218496 +286061 +610055 +286348 +239446 +620256 +321162 +265954 +274410 +200194 +324639 +238550 +289365 +233999 +277116 +294976 +617978 +322620 +221844 +218532 +235581 +629887 +235808 +288248 +250071 +248367 +329580 +263340 +333978 +628589 +285663 +623123 +281354 +621208 +217768 +224416 +321553 +327357 +608472 +328545 +335905 +624732 +256605 +609484 +318800 +632912 +239484 +276454 +265828 +340368 +271711 +263234 +283568 +272715 +264336 +609848 +627954 +276662 +264933 +215553 +261525 +253960 +214584 +611362 +262890 +303630 +309620 +315296 +235249 +302067 +291903 +232325 +201439 +288385 +607962 +618470 +239910 +632806 +293449 +237644 +231281 +251668 +201853 +205031 +280761 +618272 +316088 +263014 +329701 +220916 +221249 +283607 +223335 +627021 +218265 +270696 +262002 +289146 +252311 +315195 +241111 +325977 +216890 +307663 +622254 +219830 +248775 +247276 +293745 +213380 +276741 +305064 +605509 +286661 +268632 +267563 +327595 +284709 +219848 +318389 +239679 +314991 +223679 +275827 +622587 +245142 +255326 +332683 +236252 +313149 +300893 +259869 +268423 +295487 +248993 +258414 +326000 +336607 +238325 +337490 +235645 +209234 +256705 +624675 +610580 +606754 +313062 +251863 +237028 +223293 +230574 +276447 +232123 +298634 +255577 +233533 +294931 +275071 +304855 +269240 +287674 +213646 +629073 +317647 +224442 +337822 +604278 +330076 +610307 +911027 +266838 +219867 +318606 +606895 +252581 +320024 +623845 +264266 +305036 +213026 +222163 +308356 +306633 +627479 +316796 +310490 +256585 +309865 +329672 +202913 +275257 +214373 +249315 +247035 +285095 +312583 +269165 +274988 +600851 +300508 +621696 +314884 +212430 +214576 +334010 +251850 +220942 +219800 +256625 +301214 +327650 +337154 +230389 +246558 +286910 +291194 +210496 +329404 +606576 +630864 +278648 +293878 +216203 +313203 +265788 +277004 +226588 +279985 +248647 +623436 +271780 +302203 +323842 +318992 +217843 +297905 +308129 +311803 +288585 +276834 +322304 +624808 +610950 +230665 +221412 +313105 +291044 +232267 +606076 +290251 +224927 +287412 +628726 +274799 +318600 +261600 +255330 +285895 +277691 +216471 +618078 +317371 +228699 +276813 +632905 +270107 +312060 +294401 +283466 +243542 +611961 +262603 +224938 +294924 +248538 +293700 +241542 +326429 +609401 +283634 +306897 +291841 +332304 +622631 +252766 +236296 +616024 +263182 +341508 +625745 +623515 +603181 +312559 +221246 +608180 +298633 +612133 +201842 +249682 +260986 +607643 +219680 +265847 +212343 +320693 +256392 +316704 +622294 +273967 +620103 +207777 +625798 +252534 +298960 +601725 +612208 +218539 +280104 +289119 +330852 +609035 +318458 +269181 +324509 +317665 +325866 +299130 +314534 +282111 +288535 +321658 +336077 +327325 +318798 +311413 +314355 +222057 +231016 +256206 +251885 +312331 +285924 +272944 +265838 +627749 +606979 +212045 +218536 +322465 +329798 +233240 +338335 +331430 +220338 +290248 +221075 +258984 +242334 +220239 +239347 +256566 +260493 +208417 +246449 +297116 +319913 +217751 +306020 +274473 +604102 +272211 +271578 +275597 +307047 +321636 +264034 +608732 +283454 +298081 +202855 +201177 +278698 +604311 +609815 +246650 +299292 +321751 +289720 +323378 +234895 +219261 +304163 +278723 +304029 +247975 +295181 +610925 +608535 +256061 +340831 +201098 +275800 +239696 +274914 +237133 +339239 +230991 +234127 +221063 +272113 +212520 +601074 +273743 +8452 +323494 +305707 +623248 +619871 +229445 +8603 +280209 +284080 +312478 +234083 +262568 +227248 +257516 +226555 +286328 +299469 +288501 +226267 +264772 +221093 +268354 +250349 +287894 +630110 +227769 +295073 +300879 +317052 +266025 +285144 +229255 +224218 +249184 +259939 +610115 +339347 +337183 +618459 +268456 +236097 +276941 +219177 +213342 +318939 +631399 +218306 +301763 +278940 +313102 +273645 +262162 +287475 +201731 +307387 +314206 +221955 +339567 +605963 +231097 +213280 +301112 +331296 +604742 +281271 +624773 +289049 +309416 +201665 +316304 +311374 +289253 +218379 +232737 +201227 +256672 +212457 +213144 +641336 +221836 +215832 +274027 +339529 +258630 +284167 +328636 +618841 +632207 +254279 +202020 +277175 +293881 +248891 +312639 +623613 +201711 +216647 +609570 +624170 +293727 +282586 +619046 +291234 +608622 +303454 +311159 +306386 +263744 +602200 +261366 +216856 +295669 +287305 +283288 +263330 +212100 +210906 +265612 +256404 +310932 +309646 +264951 +238113 +329589 +270247 +607220 +265570 +230889 +316456 +220220 +606853 +249266 +263159 +254931 +269301 +610711 +267525 +293738 +316845 +303458 +300256 +605807 +215118 +272260 +252523 +294263 +626838 +303655 +262190 +231041 +608703 +607821 +611636 +245000 +259619 +275343 +216489 +254368 +248417 +220611 +609201 +246976 +201716 +300339 +216088 +247860 +8741 +233424 +304039 +252542 +269281 +607052 +298549 +340718 +288502 +237040 +247518 +262150 +335910 +339977 +624473 +316990 +216888 +610110 +230818 +335091 +217565 +306528 +261365 +327199 +322721 +628215 +631774 +215132 +259608 +247608 +260113 +257544 +329925 +272927 +631722 +237907 +265282 +249182 +255597 +320769 +340753 +317452 +334524 +628705 +602646 +235278 +327750 +220905 +600785 +325323 +298642 +327173 +204757 +222137 +284427 +278967 +278232 +337062 +329935 +277784 +206929 +608945 +274805 +238278 +217524 +267526 +317321 +318950 +260341 +307596 +279848 +618392 +271880 +278534 +324321 +332987 +247415 +303163 +255350 +272956 +619161 +282882 +233745 +271496 +316570 +298348 +247260 +231266 +608578 +285949 +273385 +324085 +218851 +271853 +612862 +223210 +302869 +625788 +293643 +307203 +316145 +330340 +621724 +266505 +249288 +260733 +328285 +612276 +268955 +322283 +212579 +608123 +321680 +298100 +309741 +264719 +338452 +616917 +231378 +323013 +247331 +215231 +241849 +618262 +9775 +240144 +316679 +288532 +301216 +216837 +321876 +242341 +256871 +318947 +275214 +261487 +224739 +287678 +253066 +335383 +316157 +303933 +248613 +258067 +282899 +322084 +218129 +331130 +618082 +315549 +208529 +235892 +238013 +278006 +332331 +295352 +306476 +603710 +228762 +314774 +331655 +201342 +221724 +237331 +616827 +213061 +313376 +314310 +614655 +303821 +235256 +606577 +299834 +313617 +262773 +601865 +235934 +220063 +605065 +284494 +248668 +600654 +265974 +218264 +249271 +321659 +215013 +318960 +336104 +236708 +228076 +619318 +261375 +214425 +298192 +615030 +301045 +282027 +219795 +267802 +269219 +332165 +262512 +341157 +627403 +222045 +328029 +267985 +221276 +209825 +221345 +221783 +302411 +215486 +286927 +238405 +631674 +330468 +622764 +628739 +268266 +300289 +333813 +220197 +279313 +605835 +308755 +301875 +621341 +287389 +265613 +606981 +255614 +618673 +210615 +226238 +218108 +609777 +260088 +211372 +220775 +617430 +250106 +256547 +252395 +609033 +334263 +291102 +336803 +294785 +619547 +335328 +601573 +219696 +240837 +619793 +332209 +314354 +316991 +315405 +262007 +227874 +224132 +600610 +300883 +270640 +275707 +612889 +201056 +293412 +309283 +605073 +259586 +306250 +219399 +909045 +600914 +212180 +611640 +220290 +329988 +265148 +211837 +223654 +262789 +275785 +333653 +235515 +309651 +299608 +277975 +217605 +330134 +607579 +618760 +306901 +231021 +256353 +603160 +265179 +242340 +268448 +254133 +250271 +211012 +302329 +251253 +308340 +221319 +318986 +261786 +266226 +620241 +302397 +221117 +269567 +615094 +253205 +322111 +215180 +212133 +268274 +226675 +210743 +238454 +631794 +628575 +314940 +305003 +294096 +224386 +303580 +327744 +610781 +215458 +258325 +200228 +235009 +314786 +609382 +240720 +323071 +293876 +254206 +202819 +230886 +239582 +229261 +628154 +230935 +220109 +215150 +215949 +602245 +320503 +627401 +230768 +613589 +311596 +321932 +312256 +307529 +286196 +268404 +222083 +229827 +217140 +263684 +241778 +240328 +251482 +263643 +261651 +335555 +230734 +324604 +286503 +330912 +305736 +260123 +307701 +223539 +616823 +261162 +285024 +301789 +303779 +605357 +9902 +224189 +205819 +331600 +606009 +257774 +269206 +297392 +226919 +601148 +603445 +607784 +278912 +339563 +614030 +255507 +270591 +230244 +254955 +265811 +269113 +275666 +618600 +281903 +258413 +206634 +299794 +253166 +331330 +256220 +216487 +287966 +621429 +206173 +285838 +236632 +302817 +270379 +265885 +307608 +244176 +296515 +239162 +632436 +251712 +313238 +273584 +251794 +241161 +222170 +223485 +262476 +256364 +281869 +329138 +256504 +244089 +246902 +315191 +310917 +335880 +323179 +235365 +339643 +301647 +296551 +308630 +254397 +217231 +299030 +232253 +608808 +625457 +298498 +613571 +231688 +323027 +258063 +330756 +231576 +265654 +248782 +605456 +326718 +312182 +284274 +201720 +254804 +310201 +606572 +326632 +226234 +284658 +298656 +619305 +262561 +247277 +631829 +207573 +618538 +307784 +235414 +235489 +252916 +321495 +302004 +334380 +224774 +618432 +619230 +302549 +253552 +260633 +222665 +623744 +309600 +604215 +295456 +279757 +256994 +622612 +200923 +623920 +296590 +318299 +313699 +257806 +257093 +252904 +231710 +254661 +278656 +294213 +285687 +608039 +623354 +259229 +213631 +276950 +247919 +603191 +222218 +301134 +632453 +303651 +268548 +260830 +303939 +251420 +320000 +249667 +277008 +225488 +324176 +330035 +285956 +278257 +285477 +224326 +340877 +316477 +241447 +265454 +205095 +624320 +235088 +630162 +223820 +287441 +335040 +270658 +628919 +621181 +278673 +265827 +272947 +631909 +279673 +236575 +227498 +312461 +324284 +310005 +319918 +602893 +268393 +621200 +218199 +270923 +256592 +253148 +276994 +269912 +208856 +275987 +237156 +241344 +253948 +296582 +299855 +261594 +304851 +273069 +601021 +270019 +216594 +909121 +601869 +613261 +220550 +267608 +232635 +626576 +259024 +604248 +601763 +314839 +606857 +284573 +219188 +206918 +237136 +308459 +223248 +300299 +216852 +248537 +227348 +244565 +248258 +269133 +249065 +230882 +259602 +211861 +237927 +281222 +213651 +300934 +248295 +277580 +225336 +323540 +327142 +220448 +299266 +301060 +269182 +605955 +258359 +271803 +291490 +301709 +200639 +606438 +286014 +336289 +252927 +267072 +612306 +289616 +624450 +303559 +322246 +255038 +286154 +215056 +605045 +310498 +313288 +221832 +214657 +254156 +336306 +317941 +327424 +628574 +609920 +220261 +218703 +286403 +248465 +315760 +200970 +242666 +266507 +299843 +256975 +216353 +300468 +312942 +273658 +600533 +258966 +607029 +299598 +204477 +236802 +624398 +262281 +232273 +290529 +628086 +277863 +322621 +231027 +272444 +310625 +233826 +303698 +262055 +233285 +217895 +624448 +339167 +271872 +252774 +290454 +609609 +628665 +616179 +321675 +245301 +287874 +610886 +612755 +337747 +608104 +272584 +297506 +254246 +309509 +315871 +240117 +278913 +334420 +618806 +222963 +309584 +263295 +625889 +232629 +303301 +309782 +612600 +252025 +263963 +266649 +618006 +202156 +239368 +212292 +224925 +627658 +291079 +294074 +257462 +255104 +341300 +284464 +252890 +604862 +281035 +616442 +263218 +268569 +319661 +619326 +217381 +9656 +224332 +335476 +266600 +324615 +311686 +223326 +218205 +295216 +217953 +304162 +302097 +253316 +237333 +331583 +224851 +226248 +618277 +321529 +623748 +241665 +270689 +281957 +223057 +221855 +236494 +213496 +611411 +249248 +258068 +273784 +293852 +332622 +258644 +251871 +226213 +200497 +298930 +320421 +262632 +255538 +231096 +307179 +611430 +306707 +318906 +307526 +321141 +287503 +303942 +236307 +258321 +253369 +260511 +266589 +322237 +302925 +233665 +322298 +295220 +222980 +624680 +602131 +630095 +237410 +275702 +609751 +308803 +241676 +337820 +307952 +222422 +280464 +616644 +254518 +626392 +244452 +625637 +321842 +248763 +298376 +224865 +609771 +223736 +267159 +334298 +239324 +602962 +613504 +268154 +249440 +251955 +200197 +618116 +257244 +286106 +616783 +207667 +248575 +276112 +230969 +280983 +304054 +614768 +274678 +210007 +287448 +243906 +311904 +247710 +617457 +301901 +329547 +218560 +291401 +295031 +212025 +632108 +625385 +304193 +303561 +235774 +605451 +614739 +312519 +269754 +335809 +222887 +277188 +307108 +606210 +611351 +332933 +627046 +228140 +291235 +218895 +311529 +311082 +256316 +220868 +269608 +261426 +322778 +602239 +909785 +294150 +212128 +330991 +608988 +201535 +330272 +295182 +303535 +223050 +221065 +260395 +222667 +336475 +310644 +224903 +338264 +230749 +256579 +234992 +295130 +307384 +246095 +625691 +619738 +245047 +259082 +232140 +607322 +230785 +617340 +303101 +211392 +286786 +250401 +328553 +268469 +626705 +262209 +220607 +323943 +296777 +239604 +256489 +252618 +248716 +269193 +201607 +322041 +228579 +8435 +230674 +242829 +233078 +235897 +202654 +302088 +275952 +257144 +273451 +217815 +606032 +275626 +609253 +268472 +283797 +631571 +320560 +314508 +296108 +311263 +611221 +315198 +278242 +273195 +328412 +236894 +220089 +321821 +339787 +255568 +230779 +223262 +215752 +264552 +302290 +267184 +339918 +214539 +317100 +212998 +298409 +250594 +223849 +228045 +245015 +268379 +621329 +262042 +609794 +330665 +615603 +230981 +629604 +288899 +279062 +321624 +330266 +629745 +312610 +337043 +249157 +222575 +224216 +257094 +623015 +616496 +310098 +335623 +624401 +224914 +606719 +303724 +627148 +622890 +268621 +612691 +252206 +624016 +302170 +275606 +291156 +296009 +267800 +237344 +908571 +632861 +227959 +257386 +275297 +294477 +330170 +289376 +286110 +301665 +314911 +228064 +298790 +604952 +332020 +212492 +323316 +225695 +340020 +618372 +275721 +318553 +632420 +219224 +261296 +227701 +611428 +303221 +218362 +217180 +226885 +223646 +263953 +331051 +215549 +303197 +302345 +256384 +602405 +624721 +334455 +621222 +612393 +296648 +277588 +331015 +218590 +909521 +299336 +259882 +248454 +326948 +215961 +335042 +331745 +318580 +279233 +311301 +317205 +267374 +335929 +313013 +309518 +233297 +614541 +609608 +613849 +322035 +208650 +263673 +296507 +610706 +336845 +310985 +631687 +273597 +247601 +246001 +319188 +318723 +337776 +253562 +615313 +610613 +620237 +312121 +284438 +285614 +254300 +266617 +272834 +303451 +237181 +237068 +224936 +270108 +602068 +641067 +269296 +247899 +328502 +627569 +262262 +227817 +212617 +340560 +282543 +241325 +284607 +248902 +256615 +229165 +341196 +316601 +322375 +249845 +320045 +232453 +320372 +230361 +607040 +307238 +266026 +280432 +326581 +240819 +338802 +247072 +263017 +221234 +613680 +276176 +260759 +601714 +300042 +222919 +282059 +606079 +328389 +248590 +631952 +287119 +309322 +618106 +625689 +252217 +611626 +244149 +267775 +610717 +260408 +241719 +305780 +207643 +222492 +245459 +632868 +267175 +296679 +225349 +222462 +247784 +231079 +615412 +252213 +304806 +303675 +308037 +310656 +612226 +250152 +329575 +613703 +265721 +340685 +629418 +243153 +274602 +250367 +618468 +249160 +266194 +618899 +9702 +260647 +235586 +310279 +230848 +273335 +303115 +213952 +311339 +226544 +205675 +275137 +248277 +335585 +221716 +316488 +296138 +239418 +317587 +234118 +621761 +306784 +260260 +248338 +333700 +324136 +289648 +295128 +235418 +243556 +282542 +266002 +607254 +316897 +274646 +202247 +301587 +308329 +303729 +321968 +256429 +253187 +262362 +626373 +318772 +260997 +263271 +221323 +293675 +312504 +318617 +277070 +322082 +220570 +300201 +218588 +616512 +604713 +614352 +301671 +268282 +220275 +305147 +230954 +602235 +240530 +611253 +269868 +285395 +311611 +334287 +273072 +212239 +264399 +324603 +233680 +245137 +322936 +610547 +260429 +602779 +219359 +233047 +304185 +335333 +627536 +333980 +273418 +253445 +238589 +220480 +248778 +602667 +270609 +255774 +626269 +316591 +624817 +300330 +257367 +324592 +255202 +270701 +224759 +273666 +245080 +260687 +241587 +329878 +336585 +605882 +273297 +312284 +629861 +286552 +221092 +259848 +303723 +612627 +218605 +281474 +259679 +310957 +294683 +268436 +281459 +218197 +327996 +246016 +289350 +317544 +618853 +299384 +248474 +623098 +290344 +314455 +626050 +627384 +626893 +282911 +229712 +334322 +611526 +242664 +311086 +285036 +244957 +313716 +219050 +218071 +326991 +262775 +321310 +297925 +273010 +235184 +315222 +618499 +248083 +317803 +311367 +245728 +321480 +610531 +278709 +266250 +220274 +255914 +200475 +603843 +605427 +612330 +316966 +322033 +225522 +316492 +336893 +615362 +609796 +322920 +200515 +318493 +605170 +247687 +322019 +216130 +337069 +295068 +218525 +220064 +304900 +263005 +302937 +239578 +261079 +286176 +607232 +325997 +288568 +232460 +335439 +338957 +277079 +255886 +625988 +273845 +231590 +259527 +330850 +223276 +312496 +293948 +285878 +268675 +254116 +278803 +607446 +274889 +268293 +237423 +322652 +208119 +317738 +610967 +236797 +311435 +253463 +242870 +258980 +289582 +236999 +303689 +288940 +237946 +629677 +301678 +295434 +317930 +628802 +232296 +314171 +331239 +266810 +222699 +268432 +299724 +281590 +274139 +236076 +298204 +625158 +612617 +262557 +203761 +212654 +307551 +335090 +269883 +268445 +327409 +266417 +308518 +252812 +235962 +214755 +304181 +261440 +312097 +262931 +241851 +601055 +289209 +630119 +231551 +287975 +268256 +268931 +255230 +608502 +256624 +618312 +278177 +257505 +333620 +618199 +230401 +213217 +221898 +223091 +296042 +283576 +214129 +267700 +320571 +619231 +246791 +279579 +605013 +201678 +238811 +281331 +219276 +268985 +324311 +327114 +303812 +227669 +276933 +295231 +608166 +617445 +216110 +289064 +603038 +299909 +618796 +262922 +299605 +615703 +203926 +222500 +284025 +321937 +319209 +304700 +306890 +223263 +625045 +626941 +617393 +212531 +249032 +275268 +265116 +618075 +230883 +243834 +312382 +207276 +623472 +269978 +333143 +256639 +255740 +326579 +297824 +298171 +321802 +625270 +243840 +325931 +272608 +247619 +267024 +322175 +612563 +323674 +269959 +300324 +270228 +630732 +273519 +320789 +334353 +219346 +606800 +256396 +237956 +630917 +247613 +619246 +258600 +299214 +249425 +293887 +253277 +272234 +627951 +261920 +290886 +316472 +326711 +245052 +322130 +609551 +254082 +314636 +222664 +262107 +236962 +245916 +317221 +249976 +235321 +244749 +221967 +609062 +242597 +623606 +258454 +330098 +303786 +284851 +337116 +257182 +245101 +234876 +222334 +618587 +340429 +249958 +610996 +603862 +206875 +255609 +220157 +247829 +325356 +307499 +228622 +316167 +316571 +257137 +617521 +221686 +249322 +276981 +277910 +619543 +295164 +299330 +227560 +263308 +246953 +254555 +339804 +226515 +279494 +220322 +224944 +267291 +253896 +604771 +608466 +269568 +263104 +233039 +212004 +627869 +315111 +296036 +328222 +273571 +253323 +303418 +291630 +321315 +265926 +337703 +308125 +303840 +252085 +618805 +300928 +230583 +273512 +303987 +305340 +605701 +607466 +314582 +231113 +305507 +261826 +213091 +295907 +261659 +326795 +330513 +252908 +284085 +300778 +274656 +218081 +226164 +309127 +626391 +310477 +252802 +285171 +200476 +612219 +256686 +259348 +312411 +216270 +298131 +313058 +235930 +622976 +249196 +221280 +288097 +221661 +265031 +308601 +304998 +235677 +223927 +320539 +286071 +604825 +295122 +218486 +250333 +256776 +605057 +229676 +603568 +300825 +258204 +249191 +602114 +320860 +232790 +303904 +334487 +277133 +318483 +247635 +300288 +331896 +336050 +912716 +268331 +253437 +230660 +629012 +224170 +241604 +297887 +316526 +293803 +220673 +285775 +606110 +244717 +221624 +286305 +218730 +628423 +313419 +614100 +212969 +274690 +262323 +247989 +241858 +247452 +219363 +236721 +289108 +219175 +229993 +223011 +279143 +227204 +294161 +229460 +275357 +311875 +250442 +630992 +324004 +255387 +269292 +311987 +267225 +625496 +607817 +340217 +315412 +257657 +227012 +301056 +277049 +243574 +295533 +314314 +312221 +237450 +600806 +318555 +249249 +304842 +249145 +298167 +613762 +335101 +326640 +227239 +222078 +203200 +303791 +613265 +272289 +251522 +237383 +318536 +313755 +249670 +266136 +285708 +223920 +289319 +223064 +245427 +330547 +300427 +300632 +309634 +909231 +607522 +336295 +322003 +248420 +323522 +318159 +222738 +616905 +302050 +322693 +303795 +316004 +330091 +300027 +259705 +201962 +266851 +621297 +285621 +211512 +260864 +622909 +303635 +213139 +326011 +289540 +910074 +225342 +276954 +253487 +255137 +318485 +267207 +311765 +339728 +334382 +269981 +336939 +312717 +246587 +287430 +328402 +235470 +265494 +282533 +230278 +293765 +246810 +218564 +260330 +223445 +264605 +218223 +621210 +219707 +270525 +233679 +329153 +228567 +230944 +271959 +202903 +333632 +625826 +281196 +316471 +248481 +331037 +248222 +206148 +281854 +317576 +212352 +205443 +266777 +317635 +269427 +249696 +268272 +312372 +257928 +305479 +225344 +333745 +220887 +212205 +312826 +237375 +335607 +258239 +201823 +625462 +302991 +244170 +222915 +270062 +230374 +244132 +338413 +282250 +248940 +278594 +247062 +250241 +242270 +216785 +266284 +603392 +225454 +908349 +609029 +614155 +219004 +294523 +274345 +314587 +306321 +262652 +606888 +627976 +243719 +315130 +288663 +255364 +218152 +221509 +245072 +284909 +230892 +604005 +231010 +266033 +317721 +277440 +321557 +276867 +256354 +307442 +318050 +214666 +305661 +249580 +320136 +625955 +9801 +302083 +235212 +247513 +305370 +331090 +607297 +314988 +304072 +609402 +299600 +287453 +262402 +340210 +300869 +281971 +333594 +605420 +248992 +232814 +333952 +612534 +330186 +220720 +300193 +267995 +251555 +330269 +223463 +312691 +273831 +268795 +253274 +334134 +221126 +246745 +248434 +331892 +285010 +235863 +306605 +316580 +283556 +332428 +240500 +240258 +215594 +299105 +299660 +620152 +214455 +328405 +618156 +241988 +205252 +285037 +239515 +336932 +251750 +236665 +269217 +269045 +298450 +322155 +286531 +631002 +249362 +265611 +251008 +248368 +608712 +613622 +285343 +612224 +252263 +259276 +247846 +609719 +232372 +239318 +622400 +236638 +276516 +246795 +237846 +624382 +203427 +276898 +617896 +291612 +309067 +303797 +214499 +300106 +605549 +626954 +9676 +337283 +624872 +251309 +301803 +298900 +609573 +288328 +227964 +262032 +626524 +223744 +277870 +206283 +250589 +274404 +237713 +240394 +324008 +272200 +328582 +605285 +265177 +252743 +274903 +299347 +253773 +600890 +337785 +247733 +205436 +219262 +612280 +231050 +247633 +230797 +316414 +315925 +249929 +227220 +266394 +239986 +305316 +329832 +236269 +632492 +315663 +228368 +334540 +339431 +626579 +291329 +261075 +607768 +316369 +300881 +201837 +281384 +215143 +286210 +330731 +238193 +233701 +323136 +612933 +261741 +301093 +261324 +237471 +301785 +219120 +265867 +257007 +245009 +249708 +308465 +263145 +251557 +256583 +223048 +272089 +303511 +298893 +306483 +293488 +213531 +302795 +230177 +610746 +8635 +275689 +244130 +618826 +226347 +235186 +322339 +623764 +235527 +278997 +338524 +237105 +315477 +245145 +225204 +224211 +611307 +287502 +304857 +295710 +303514 +328716 +334241 +299972 +308968 +306648 +265099 +266765 +246618 +253818 +237421 +248013 +605361 +250050 +260773 +623541 +276051 +279004 +213927 +622523 +224197 +340519 +283850 +323085 +272823 +212652 +229334 +216295 +305676 +220335 +266723 +613677 +218504 +335020 +626585 +619120 +249804 +295165 +269175 +200647 +618914 +624381 +236032 +264098 +326651 +600932 +227462 +245355 +280496 +328820 +323380 +257548 +221441 +319475 +201690 +295620 +295192 +235323 +326481 +238833 +624759 +266712 +269722 +324496 +289023 +326483 +247471 +213681 +229244 +242294 +610986 +288024 +625863 +244122 +204697 +299962 +239142 +621272 +605228 +239184 +630030 +334288 +618162 +291458 +285038 +242852 +227042 +604450 +260807 +298820 +618045 +339105 +326740 +254603 +283157 +217820 +617989 +335933 +202305 +287702 +120220 +236642 +622331 +228177 +291851 +237940 +324313 +284434 +231023 +239346 +223854 +269980 +293728 +254996 +268358 +618743 +227612 +285132 +319007 +218637 +225076 +609256 +314151 +331726 +220035 +252881 +315177 +287344 +202405 +339681 +230604 +335577 +260090 +297917 +304228 +631171 +204997 +601033 +631883 +607126 +229810 +217778 +216356 +330001 +249664 +296126 +312417 +249264 +320873 +220387 +286962 +294192 +313305 +295226 +314742 +276971 +331484 +333829 +221952 +299221 +311975 +9886 +607193 +299071 +327334 +212269 +338082 +217622 +8634 +329774 +612269 +220727 +325976 +295664 +605751 +621221 +272206 +224275 +240583 +297843 +211574 +258512 +627156 +305125 +623303 +247786 +299620 +611107 +328247 +605969 +339113 +263252 +252494 +231640 +277118 +236336 +336200 +612352 +258583 +600063 +619439 +290963 +289968 +246331 +235050 +200240 +321606 +256448 +618347 +254528 +626844 +340480 +256973 +244255 +618487 +210385 +327565 +256397 +242297 +226135 +228461 +334013 +318003 +275505 +261299 +214945 +607937 +326455 +308115 +212470 +227430 +249280 +625852 +329346 +313440 +313369 +316379 +258221 +338534 +220494 +326835 +219041 +303774 +285758 +235141 +286730 +253181 +340124 +265104 +262315 +232124 +911837 +624924 +215360 +618588 +320070 +301919 +310389 +216474 +235589 +293549 +600396 +332094 +240013 +284382 +212692 +322285 +340340 +632913 +203314 +314003 +623967 +224263 +312420 +277879 +211898 +236635 +316345 +204072 +286513 +8430 +239108 +611425 +327616 +262149 +631435 +604577 +288587 +632413 +302364 +200443 +329926 +626729 +618201 +305654 +251356 +241500 +293751 +304963 +276164 +315961 +616480 +909881 +222562 +219603 +207282 +261563 +325622 +610565 +272790 +259881 +233652 +324271 +608352 +604714 +283499 +275852 +224862 +268172 +269228 +281556 +266008 +612113 +612035 +233460 +225267 +302798 +289880 +611141 +321881 +201749 +256482 +618346 +296541 +200716 +202088 +339070 +619762 +207542 +243496 +219965 +237718 +243456 +223600 +249148 +601114 +267333 +606321 +263188 +293687 +220891 +246039 +607214 +213238 +303700 +239685 +221446 +616922 +607584 +631704 +8657 +296162 +607013 +317983 +246998 +285202 +335890 +217314 +308183 +291073 +276320 +230489 +911723 +319010 +624874 +278144 +605267 +237722 +303917 +294342 +283279 +283530 +618636 +318977 +323375 +249736 +287361 +613169 +316458 +333909 +337250 +246680 +339177 +279587 +328988 +258307 +257219 +254370 +219042 +212243 +328309 +235993 +604531 +610370 +329645 +606634 +291352 +200767 +242177 +244997 +266111 +255863 +289949 +600059 +248135 +610422 +217431 +334587 +221255 +616251 +317235 +228572 +269119 +335182 +291244 +206675 +203636 +314618 +269573 +318184 +231058 +312784 +612413 +202287 +324416 +270629 +273558 +290497 +237561 +233649 +234180 +321879 +262327 +8554 +208932 +283770 +237726 +255438 +233485 +609138 +263142 +230993 +285861 +330300 +320694 +602768 +337757 +600387 +247551 +239229 +618690 +239277 +277062 +218513 +605502 +273285 +625214 +621364 +298063 +612577 +316309 +624557 +288381 +288964 +618273 +275280 +261376 +314484 +275223 +629486 +262033 +270351 +285848 +293713 +100202 +249173 +314164 +220410 +264613 +320845 +252222 +627155 +295298 +254862 +221813 +203379 +223913 +303308 +250345 +319987 +630657 +235073 +331084 +291799 +611007 +619061 +331298 +313133 +227004 +255080 +332049 +281841 +248288 +289485 +612285 +251620 +230715 +339539 +607015 +283483 +304099 +910686 +248261 +226539 +626375 +295568 +265792 +275139 +295155 +235221 +224747 +288956 +310496 +320091 +252096 +224816 +247468 +618799 +233615 +250194 +606104 +337054 +318899 +328345 +604271 +334258 +312979 +205004 +232055 +289284 +612415 +262755 +217069 +8758 +319454 +282300 +280307 +267487 +323216 +248657 +608303 +325326 +625174 +277899 +246691 +609154 +219671 +213645 +248497 +340485 +236283 +294744 +314324 +269966 +254677 +254383 +247045 +230850 +257953 +605543 +274778 +618450 +226257 +607276 +295222 +268284 +246841 +624806 +253521 +268217 +287410 +280550 +251200 +271503 +299815 +225661 +316432 +630749 +332059 +230113 +315165 +331910 +265877 +318929 +607212 +239560 +226446 +269153 +276919 +329500 +629088 +216215 +630849 +290098 +338065 +288304 +210345 +623757 +290148 +215330 +256581 +262647 +265182 +316955 +220851 +279972 +623994 +284924 +245808 +230905 +290161 +244643 +239988 +323987 +627146 +307360 +325633 +303922 +255285 +303006 +610953 +268926 +609562 +265151 +259118 +619706 +259649 +300870 +607406 +600400 +299176 +296693 +293883 +272509 +214840 +246967 +618096 +305292 +208703 +314343 +291053 +266546 +618603 +312307 +618359 +262539 +227056 +263400 +228334 +301070 +229375 +251235 +223044 +324257 +607851 +616088 +611855 +251429 +324439 +229921 +253580 +337399 +316716 +276828 +279074 +232835 +272448 +237785 +274896 +238447 +268322 +615897 +262533 +296546 +255451 +909156 +625579 +285061 +263429 +270001 +235662 +628198 +303137 +339182 +606956 +235237 +203650 +627056 +267583 +257654 +285174 +626210 +223608 +611333 +618109 +8517 +308051 +608184 +258033 +251336 +323362 +200200 +321171 +335478 +202083 +605445 +226440 +623448 +322849 +302669 +253376 +280078 +250284 +314055 +304165 +221350 +323714 +247528 +604590 +612116 +291405 +276974 +219514 +267038 +252572 +324318 +217033 +322998 +278170 +275005 +295234 +616344 +219146 +328621 +266005 +304758 +236486 +307280 +301279 +291798 +309361 +285827 +286533 +280519 +213969 +254774 +631112 +212754 +268360 +608534 +299112 +293591 +286446 +310884 +257964 +269167 +246837 +602007 +203767 +262523 +603839 +303850 +318878 +606797 +334433 +252563 +606915 +215281 +307532 +247652 +217549 +323287 +333598 +320651 +632165 +220818 +286021 +632293 +217311 +307379 +326930 +201751 +258657 +327203 +284953 +283421 +300300 +224690 +221150 +260911 +221320 +240446 +223328 +327403 +222741 +278525 +236091 +321883 +294332 +321694 +269138 +298494 +606889 +233036 +609398 +256812 +605093 +252943 +321501 +616155 +308796 +289424 +339245 +258862 +306398 +626812 +612281 +617606 +265172 +272073 +334079 +314263 +268301 +274922 +267179 +212160 +283367 +223359 +239176 +331644 +318249 +222714 +306414 +253141 +256502 +252499 +234015 +335746 +253837 +323947 +216373 +621727 +231430 +610425 +312126 +288710 +290488 +600061 +245025 +288254 +237936 +300966 +290025 +8444 +339442 +249259 +262029 +334081 +263468 +261980 +329743 +321855 +297467 +248826 +300710 +308130 +609775 +227799 +600933 +236314 +301764 +328708 +272886 +912351 +333858 +218070 +265137 +8460 +223040 +274137 +243106 +322129 +276930 +242991 +322742 +330015 +221823 +233513 +617603 +610279 +237920 +308261 +604956 +605368 +249261 +294509 +619674 +607545 +329871 +631395 +322156 +254941 +334291 +315068 +226479 +247083 +225186 +326928 +239414 +216483 +324466 +295146 +259418 +201100 +224763 +261560 +268478 +224797 +259349 +262996 +606570 +331934 +335879 +229231 +245482 +626628 +341116 +213855 +243047 +247348 +612712 +278192 +276909 +274681 +258898 +213266 +248178 +8630 +309837 +265213 +310849 +326608 +271909 +204398 +255262 +609927 +236308 +316173 +232513 +213031 +324365 +248402 +220339 +270573 +273061 +262604 +223495 +621227 +628854 +266422 +269282 +264717 +623982 +268073 +602621 +226820 +625621 +212785 +263435 +319995 +267617 +286639 +252314 +202735 +315579 +280765 +908771 +616170 +233074 +227754 +242284 +279365 +611761 +258942 +603946 +618112 +623155 +330524 +217665 +252126 +266931 +315131 +226043 +328870 +324275 +316014 +627543 +278706 +220031 +295845 +305549 +630911 +307450 +300519 +261743 +311804 +618093 +321455 +340060 +313478 +220447 +622882 +241558 +260875 +246389 +334324 +202897 +244100 +316530 +614507 +331606 +219417 +607361 +268347 +218595 +299990 +9769 +244975 +217512 +222104 +8388 +305404 +608723 +246561 +282091 +248893 +627828 +619712 +271534 +270435 +314364 +212811 +303872 +339470 +620297 +328996 +265432 +302021 +264448 +216171 +300504 +332278 +229642 +288879 +278976 +242385 +302880 +625341 +267226 +316965 +273475 +324660 +321739 +626057 +244549 +204059 +314983 +337365 +258259 +236117 +289699 +204905 +301120 +240185 +296057 +610840 +602202 +282539 +275303 +272581 +305321 +248816 +285173 +289611 +303519 +251131 +201626 +224548 +328514 +235200 +334008 +291512 +232598 +218696 +277147 +206281 +618902 +239985 +232106 +617119 +254022 +228149 +308389 +316866 +220944 +268019 +289592 +303806 +337905 +618863 +253131 +261523 +303447 +200931 +617678 +238316 +254319 +606112 +222353 +333837 +313256 +303974 +201024 +222476 +317304 +237665 +227376 +272391 +240222 +269440 +276282 +213382 +230929 +276093 +208740 +289785 +284404 +606786 +233062 +284868 +222470 +318809 +280152 +608995 +295449 +312384 +628788 +328652 +207948 +201380 +327063 +629347 +245457 +274717 +306537 +222623 +299101 +257852 +316266 +261977 +311341 +295397 +205150 +286888 +622082 +299097 +627033 +204555 +294098 +223585 +269233 +318097 +279352 +235293 +236931 +623228 +265759 +317142 +318149 +217796 +287763 +218350 +295107 +264639 +606692 +296570 +630024 +309377 +261231 +609687 +252375 +258280 +272684 +222639 +247473 +247228 +230653 +247300 +316973 +612216 +268184 +327768 +610028 +298106 +298364 +268946 +294609 +237819 +339656 +326548 +267439 +201370 +603500 +321571 +257098 +219980 +263027 +222858 +233232 +244082 +322449 +600578 +249296 +260379 +246622 +277472 +213277 +236839 +298164 +262744 +221666 +316096 +315653 +261863 +222165 +303941 +248523 +248784 +276984 +242175 +321608 +248642 +625308 +218354 +222307 +300230 +600680 +256439 +291632 +265927 +291780 +612146 +302346 +245003 +211347 +249202 +205066 +604814 +267352 +622114 +284899 +310333 +221090 +624287 +236591 +211820 +208341 +602156 +247340 +252284 +300604 +272619 +228694 +233263 +234798 +214004 +301204 +235305 +221574 +336921 +298701 +264057 +285889 +214009 +215174 +284552 +222620 +276996 +220933 +311935 +622876 +303944 +222645 +237997 +608790 +240382 +606799 +314331 +311660 +604568 +239268 +608829 +260892 +338200 +282677 +321647 +247603 +337075 +609840 +224880 +625488 +303031 +295322 +272613 +322207 +211816 +314753 +624871 +233847 +286536 +240555 +219945 +222225 +264083 +272852 +632819 +339523 +200235 +296613 +625448 +270641 +611449 +329279 +288974 +234970 +253663 +234474 +628168 +632756 +619319 +222517 +618284 +253917 +231979 +248048 +301124 +204863 +256362 +608197 +609027 +314293 +242107 +239536 +272515 +217647 +322893 +273243 +205987 +8581 +627701 +331501 +626474 +202222 +216813 +611004 +611388 +278541 +242262 +219395 +300452 +211998 +243393 +333796 +298742 +254675 +607099 +291823 +248314 +222322 +225938 +330788 +308768 +216699 +239296 +622724 +221760 +293932 +216916 +623612 +212188 +220582 +234954 +282818 +315333 +625452 +288133 +214986 +304265 +260906 +307207 +278857 +267989 +613004 +320594 +329133 +263186 +623518 +334204 +631789 +606144 +339621 +607832 +312092 +239357 +218674 +214122 +276794 +314453 +604733 +608784 +333844 +274798 +213254 +281338 +284747 +289328 +249270 +628785 +287805 +327455 +291618 +203083 +260057 +615112 +228657 +282008 +307617 +249416 +239244 +274856 +243296 +270273 +289755 +268262 +320496 +214407 +311879 +264645 +254349 +324476 +224309 +603847 +279619 +247573 +284863 +269441 +623883 +303422 +272957 +224561 +625131 +623809 +244941 +248560 +314838 +256314 +244986 +228631 +279228 +221660 +612555 +328642 +605149 +256283 +316630 +324359 +621252 +205533 +203885 +602640 +239937 +230802 +627152 +326044 +330136 +329029 +203406 +293638 +310235 +236658 +258346 +265879 +300100 +301031 +631830 +246647 +215876 +282506 +224233 +233904 +245977 +218731 +253322 +333624 +284373 +242551 +619647 +286753 +313173 +284995 +629115 +249499 +236021 +290011 +223252 +234847 +261547 +256464 +254751 +278899 +237194 +336230 +297475 +272563 +256096 +244401 +301342 +247208 +230860 +294935 +249273 +276745 +249691 +235325 +249181 +225634 +313552 +267351 +230105 +620221 +251714 +329322 +270369 +617199 +614880 +201412 +243066 +275978 +203487 +338972 +606304 +614606 +317620 +202487 +620136 +336427 +260767 +328443 +269983 +262147 +314277 +256797 +286431 +340941 +615102 +313658 +268324 +281365 +606411 +200950 +285540 +253297 +311970 +628276 +632838 +276907 +221415 +269356 +252561 +288038 +278425 +221274 +236106 +246644 +320214 +237869 +315087 +617754 +223501 +255135 +632075 +266835 +228559 +320121 +314522 +627395 +328893 +306435 +266470 +610414 +231724 +302270 +228490 +254243 +321791 +607842 +249167 +224937 +277775 +604891 +330978 +234879 +287615 +248623 +314050 +236107 +246711 +311989 +606163 +618592 +268930 +261795 +230915 +280670 +283953 +619325 +327691 +269302 +317744 +227690 +232068 +258453 +619619 +237292 +274388 +281628 +307392 +224818 +261696 +321156 +327153 +339620 +231453 +339136 +315494 +242316 +606141 +620745 +282723 +630752 +328025 +605727 +294561 +211873 +248376 +334542 +611553 +300838 +627025 +223918 +270182 +228844 +618024 +225670 +628065 +303926 +630652 +632587 +612562 +269438 +230614 +244672 +298395 +217970 +240579 +630731 +232620 +262293 +268455 +9924 +324557 +269015 +628273 +221195 +310206 +334355 +251269 +623961 +221399 +608936 +268305 +319923 +260165 +228629 +293814 +286442 +632840 +631105 +252558 +298603 +299429 +314120 +304617 +249793 +217190 +277082 +318983 +317404 +624935 +244442 +307891 +245004 +269285 +624033 +293498 +208319 +324211 +285092 +618237 +612654 +279093 +331683 +287841 +332078 +233190 +232454 +308913 +247615 +215750 +287901 +611493 +339382 +248567 +257305 +316622 +230793 +228677 +278393 +263707 +220256 +307460 +316254 +223630 +618525 +323148 +310196 +207326 +631323 +306037 +296595 +248663 +248010 +213881 +319167 +615146 +329784 +208814 +266907 +276937 +606156 +218968 +203189 +627162 +632240 +225260 +265381 +202955 +298355 +623963 +213967 +618335 +610446 +337977 +618643 +220166 +630013 +223489 +264123 +226465 +219676 +323535 +236975 +288136 +294266 +259743 +621386 +223098 +248622 +240665 +332058 +258443 +226552 +312632 +240777 +230974 +275751 +296500 +309460 +307834 +289452 +216556 +227890 +259219 +312851 +307696 +281164 +253544 +627416 +602736 +256768 +256961 +213349 +274192 +234542 +297888 +614779 +314879 +256563 +618322 +254065 +278629 +299753 +251761 +248043 +331270 +334952 +254951 +338258 +617518 +211439 +285135 +237581 +639510 +309528 +317420 +321730 +300805 +265803 +625975 +263567 +621280 +258750 +323182 +291111 +211523 +281604 +285055 +603794 +280255 +616228 +263484 +251727 +249858 +609898 +213634 +298592 +330569 +299657 +270000 +280393 +239224 +623439 +241009 +618692 +280515 +302638 +235771 +301244 +632066 +316511 +229142 +244229 +235439 +287482 +200918 +208091 +317662 +603718 +315019 +252212 +219817 +239534 +212797 +233691 +226154 +211806 +294180 +233786 +268224 +317433 +253087 +245070 +626766 +321305 +602295 +285593 +610551 +616419 +628688 +340751 +262229 +290613 +252463 +268466 +247982 +308620 +331505 +332580 +252918 +260748 +328328 +326652 +265742 +325330 +221742 +335692 +322698 +282688 +314817 +254889 +604093 +605717 +279519 +274123 +281668 +294049 +284391 +267243 +318563 +230963 +231500 +284514 +311205 +335716 +284424 +282679 +321692 +300304 +631127 +318942 +603587 +234049 +301174 +607896 +320966 +324298 +212790 +258617 +273411 +626467 +275201 +220005 +289941 +321427 +622856 +224819 +241269 +627959 +264602 +631092 +625673 +609761 +300462 +310712 +326712 +253649 +295016 +282522 +8591 +315233 +330430 +252379 +338463 +316371 +324487 +221362 +283533 +279790 +243016 +278727 +223175 +278824 +271714 +294293 +332276 +236836 +270574 +286522 +211437 +313296 +601760 +285461 +306088 +629472 +208670 +620214 +235711 +203138 +213295 +339409 +329910 +308003 +333794 +337372 +306093 +608981 +612170 +237369 +267521 +623422 +247947 +626797 +265189 +278612 +254448 +339760 +612279 +340770 +620351 +282036 +913974 +236316 +245268 +607411 +266029 +607415 +615068 +273320 +605729 +285811 +273669 +268142 +323541 +257056 +256372 +316978 +273986 +616233 +271882 +276297 +336202 +296482 +251480 +336355 +247475 +235806 +230975 +310034 +261868 +626920 +301470 +299084 +339829 +222486 +255780 +305197 +334036 +259196 +244952 +326635 +611659 +277120 +629292 +244766 +334082 +249200 +320959 +9737 +338866 +221407 +278313 +627374 +641530 +267856 +216227 +267574 +613825 +320576 +300584 +276187 +284550 +609046 +287617 +617001 +237535 +224483 +216923 +8600 +275788 +324637 +265139 +323427 +259166 +625316 +226565 +289600 +299094 +239171 +328490 +296714 +291832 +612016 +313243 +272764 +258932 +221027 +339813 +246961 +613783 +218467 +336882 +297446 +224766 +255750 +253162 +241544 +217152 +212544 +309150 +318497 +295269 +331873 +293398 +618509 +227177 +213007 +330803 +607476 +303472 +296115 +214919 +273719 +224119 +606335 +278742 +277006 +227190 +304753 +256509 +228989 +242474 +600796 +230876 +273677 +271936 +247616 +231550 +602102 +327627 +223807 +273737 +323711 +212322 +220506 +618438 +301177 +310516 +324622 +241309 +227286 +285746 +260142 +610756 +201076 +275345 +301260 +601138 +612782 +235560 +622979 +627037 +291771 +246539 +334407 +318759 +312304 +257733 +219235 +215080 +263306 +290623 +611593 +239423 +207638 +605771 +324325 +211625 +270436 +274237 +288233 +236701 +220901 +602130 +285463 +247516 +274846 +255512 +332830 +627895 +238353 +276206 +607133 +313161 +604668 +277122 +228488 +306997 +337986 +309786 +321122 +317753 +232164 +200701 +226494 +235008 +326487 +219418 +230919 +330516 +327232 +293733 +295663 +309139 +305986 +605448 +334327 +607041 +268329 +201204 +202809 +209653 +612334 +606010 +216384 +260764 +220871 +322307 +306873 +221210 +625396 +331806 +237242 +311278 +220562 +330060 +321573 +316513 +255811 +340884 +272612 +612022 +223234 +626449 +262168 +338977 +276970 +230844 +623424 +262163 +306999 +600404 +340719 +223138 +326937 +220631 +253754 +610594 +313360 +613817 +214794 +231031 +602705 +618118 +328408 +206734 +327648 +311701 +214625 +299086 +298582 +322020 +321520 +220926 +235730 +323263 +223323 +291761 +245872 +221922 +284354 +281738 +259432 +630860 +318514 +237909 +270120 +314926 +273406 +256518 +307877 +266579 +235878 +602843 +219986 +259064 +268853 +284532 +295060 +273049 +286548 +208813 +263363 +339847 +248154 +303434 +333804 +606796 +323408 +227887 +331623 +284558 +323945 +629388 +621321 +326512 +246599 +606728 +618683 +215248 +215270 +222212 +256718 +261618 +294187 +315106 +253755 +206707 +244449 +255403 +610872 +320368 +605103 +607142 +296543 +248821 +607960 +280929 +631483 +214148 +624054 +293980 +298974 +308469 +631292 +277134 +340950 +330071 +605159 +625531 +324189 +236847 +220794 +321067 +201871 +288195 +227202 +623379 +211403 +318941 +262614 +251681 +299345 +331251 +289581 +201335 +267044 +328483 +613354 +607949 +266789 +272976 +285075 +613556 +613771 +330892 +268366 +295573 +247835 +213592 +221379 +631512 +328162 +219607 +252975 +300376 +329679 +268112 +609497 +321749 +297408 +284442 +617659 +626035 +200234 +232158 +211691 +240460 +234391 +269591 +340538 +284522 +295091 +255797 +608873 +330571 +236964 +618353 +273340 +270137 +306535 +339106 +212663 +291866 +331947 +294601 +318530 +319938 +628381 +608977 +284421 +231171 +609758 +282255 +201938 +312444 +317766 +9774 +229906 +211386 +317672 +261499 +229112 +619163 +270833 +252738 +217453 +256622 +303685 +278093 +283605 +333834 +269502 +334202 +212114 +280694 +294025 +307888 +613633 +622728 +608407 +270598 +608998 +605288 +611528 +301509 +258076 +338164 +222925 +277166 +304137 +219944 +276569 +332720 +253477 +217854 +329648 +339995 +607521 +252988 +218057 +283025 +242339 +221095 +629829 +608593 +252610 +228398 +261572 +229728 +298162 +611146 +235476 +240865 +627322 +239261 +609907 +215723 +310785 +293926 +279781 +316468 +627429 +257410 +623742 +325383 +224148 +320755 +607491 +613689 +317532 +263287 +265718 +308417 +322605 +257488 +270596 +627117 +229612 +613257 +600391 +328695 +215032 +249013 +201588 +267232 +273063 +289843 +321780 +288611 +225149 +240854 +299255 +605243 +611346 +628100 +300206 +307574 +619870 +306298 +322333 +316337 +215414 +325964 +311870 +278530 +332350 +261611 +601826 +278228 +235154 +245513 +328287 +619194 +285273 +219048 +324280 +285034 +622867 +616702 +618337 +286155 +294282 +334946 +306587 +214134 +321725 +213034 +255292 +235595 +609507 +294838 +338849 +273133 +236443 +275209 +318062 +252132 +626436 +281608 +211917 +229390 +210459 +213948 +221013 +254711 +251913 +609762 +323646 +276929 +626572 +284928 +253650 +236777 +610480 +225387 +259253 +310715 +221241 +612607 +217436 +267129 +251804 +334257 +305762 +326435 +294341 +218740 +261537 +283401 +271691 +299434 +230869 +238686 +627949 +222550 +275877 +303636 +621956 +273720 +277109 +228052 +246020 +258740 +331333 +219579 +217856 +330309 +230837 +222230 +220620 +252145 +287867 +302246 +299804 +243864 +275691 +239481 +200239 +615142 +284094 +214355 +324233 +293431 +234825 +213202 +266030 +278417 +247779 +242507 +270253 +276948 +273083 +218797 +330822 +910048 +628063 +263500 +217334 +331707 +304041 +299957 +235966 +280048 +324202 +291280 +267405 +631622 +249674 +262301 +295243 +249430 +328263 +234040 +222023 +267922 +329156 +309086 +228074 +257253 +620315 +229947 +215504 +289194 +294390 +603416 +246725 +224834 +303914 +231424 +283597 +301995 +229825 +245506 +336360 +310368 +605613 +603240 +296016 +234122 +615423 +273820 +327932 +255961 +268689 +256386 +280772 +612063 +311849 +242306 +225301 +203646 +235358 +247933 +231986 +304020 +334843 +237246 +307659 +255755 +200349 +225643 +309952 +602386 +251867 +318352 +284474 +336506 +273024 +228261 +222910 +252951 +282889 +334584 +218903 +243554 +304015 +281289 +253231 +334283 +626832 +240362 +226313 +288382 +619949 +316611 +263604 +282789 +274032 +237497 +267233 +609574 +253992 +616551 +331030 +247091 +295981 +316665 +631558 +254619 +337753 +629213 +240978 +288959 +318984 +286975 +240962 +265229 +257639 +309649 +624910 +603410 +327219 +223678 +316265 +212854 +602423 +605474 +204727 +320924 +624318 +244709 +264465 +230640 +610737 +246450 +607332 +249239 +207727 +301873 +331866 +331602 +278084 +623240 +284338 +277463 +298904 +264895 +613286 +244151 +247730 +315704 +316020 +277728 +623874 +306457 +607690 +291778 +278065 +309874 +244164 +247590 +255377 +266198 +237492 +607963 +623426 +602616 +247556 +225669 +263148 +242598 +300355 +276407 +624204 +231753 +317006 +242193 +259638 +289706 +235437 +200231 +286695 +304048 +238490 +271787 +246651 +301424 +321846 +217979 +323719 +224012 +298284 +316610 +324432 +236741 +231549 +231467 +218849 +250164 +237109 +610853 +610928 +232241 +333790 +281573 +256695 +324178 +256458 +272669 +233312 +300384 +286803 +305397 +230291 +322117 +290227 +612053 +265482 +285098 +239525 +270891 +289442 +287404 +290431 +308943 +301840 +631203 +613868 +327916 +257662 +301650 +224369 +120011 +234920 +297918 +264361 +218130 +206705 +273817 +314679 +295817 +300036 +334259 +268109 +263623 +277889 +304239 +622738 +612517 +221125 +234124 +270410 +242079 +280032 +325953 +262887 +309596 +314227 +631812 +227507 +608711 +291820 +278169 +273923 +252278 +237890 +609129 +248587 +622122 +307523 +603378 +313950 +617196 +228217 +203734 +235285 +290911 +301855 +224395 +627999 +616811 +223518 +321745 +615688 +322790 +260067 +253032 +235106 +223059 +218522 +273039 +326644 +305483 +272808 +617777 +269553 +641503 +274985 +311784 +623216 +254331 +220291 +612619 +275045 +283204 +261459 +630979 +212578 +294959 +314294 +221573 +330090 +295223 +221466 +283062 +607019 +288513 +265413 +248959 +240812 +299771 +289923 +244099 +323466 +284722 +296127 +622959 +300078 +341036 +279617 +234409 +235041 +609023 +267382 +236484 +310829 +298114 +270773 +226273 +328075 +249247 +612236 +626890 +606149 +321720 +266605 +268253 +314304 +321758 +317731 +281322 +332404 +272156 +304248 +253949 +605292 +247836 +265097 +624519 +237097 +265057 +298226 +291206 +324425 +323849 +275456 +287725 +631599 +318024 +240603 +244592 +233597 +307370 +309742 +295136 +321610 +216420 +339365 +268419 +246663 +248123 +303631 +230019 +299985 +608736 +263890 +262473 +236137 +267234 +256440 +226521 +608041 +258967 +222121 +284895 +303652 +608768 +306504 +328787 +613247 +249146 +600641 +631653 +212175 +300534 +339206 +274323 +606108 +304249 +314678 +329576 +242048 +284340 +263557 +265212 +279881 +245012 +252266 +339152 +220518 +311394 +604715 +318218 +626544 +609966 +218472 +207362 +334200 +336643 +283700 +295036 +244983 +618597 +311846 +221811 +625714 +630758 +626283 +311956 +612590 +203934 +235873 +325917 +290567 +253072 +618316 +310397 +325608 +221059 +630089 +295143 +248495 +294196 +239870 +621413 +299767 +302151 +609823 +299710 +218335 +222179 +605348 +269157 +276062 +304081 +204742 +333592 +282625 +255508 +262503 +605544 +324249 +260801 +281884 +244994 +305821 +257110 +623473 +612431 +310837 +339880 +295372 +207916 +334497 +268194 +229328 +603121 +294061 +224821 +212014 +330008 +239196 +220212 +261809 +321582 +321772 +228943 +246554 +327937 +602422 +259893 +268135 +239378 +302452 +222943 +245233 +312495 +303074 +233682 +211602 +331985 +628603 +306927 +219605 +618560 +308439 +244913 +255724 +287367 +329014 +611014 +216025 +294214 +222006 +9822 +298415 +268585 +226442 +626511 +269788 +266638 +201031 +205887 +302158 +220638 +269909 +310913 +267528 +341076 +252231 +267557 +235433 +320977 +244301 +274301 +308292 +223024 +258482 +200188 +212111 +205777 +627838 +268513 +600803 +298910 +307224 +254115 +339176 +265264 +613908 +236568 +279973 +337665 +622620 +301365 +227017 +305600 +255732 +320737 +269160 +270194 +247995 +281659 +202230 +606549 +323899 +262853 +600376 +200915 +330598 +299495 +224751 +257126 +333859 +327494 +228674 +244942 +284731 +303069 +259711 +252860 +220178 +254078 +229677 +248805 +305240 +256984 +231761 +296096 +604286 +299240 +295010 +268330 +624930 +249257 +327160 +276915 +201279 +215212 +202008 +290257 +314345 +299286 +235474 +623524 +285598 +247579 +287526 +218462 +252967 +312165 +257886 +284833 +608826 +218815 +269179 +202886 +218345 +299169 +631710 +304111 +202772 +611909 +313610 +298998 +622413 +287813 +336343 +268155 +211712 +631440 +213633 +261382 +255909 +244988 +279408 +224535 +608756 +612551 +246479 +611104 +263035 +256595 +261552 +223866 +230239 +301550 +223226 +259744 +626014 +622906 +282887 +326408 +254077 +331800 +316779 +284881 +286146 +240449 +273851 +607401 +220701 +615203 +241334 +215843 +229599 +262318 +245143 +631718 +306576 +236281 +217997 +221768 +632229 +609412 +313015 +249321 +307161 +255500 +200636 +630914 +619603 +272072 +273786 +631070 +621173 +310987 +602901 +284981 +606568 +307948 +225408 +212881 +611259 +222263 +605621 +244898 +248659 +268688 +320303 +281180 +233666 +606798 +252035 +301440 +282998 +239173 +237547 +254486 +603663 +206943 +276324 +258338 +618418 +255739 +641463 +285875 +606446 +232359 +611288 +244521 +249777 +223758 +293572 +247935 +286875 +625760 +611218 +274580 +226424 +327100 +202591 +287682 +210947 +313664 +229823 +311903 +229205 +203481 +278511 +260233 +295303 +235895 +337637 +294218 +303507 +262071 +324055 +283366 +328675 +621970 +334949 +224957 +315874 +334983 +260963 +215453 +237646 +9718 +273739 +252950 +262552 +262183 +288819 +330582 +9816 +318990 +293678 +618097 +247305 +294929 +629556 +321865 +311469 +262507 +327101 +251271 +249393 +336301 +249390 +285908 +315421 +273372 +228180 +210896 +602222 +239920 +232217 +220686 +214364 +217488 +222220 +327361 +296043 +284585 +9890 +222773 +316404 +628876 +260103 +239204 +228841 +623593 +256378 +331432 +255711 +215618 +329245 +268107 +314463 +268219 +276750 +285556 +305814 +272351 +252508 +229732 +291667 +244405 +317185 +232551 +623287 +261679 +609203 +328001 +220511 +299232 +301635 +298009 +618783 +233541 +287519 +299141 +287677 +220680 +294435 +221852 +279405 +233204 +231077 +261441 +300572 +631102 +306664 +618232 +253584 +220049 +612118 +271829 +233111 +306793 +328613 +275911 +213110 +608679 +316194 +233942 +252520 +611714 +293734 +317085 +206104 +321738 +317058 +219110 +313355 +612620 +220842 +237373 +9862 +269977 +288734 +296090 +314910 +325348 +239235 +321971 +269198 +206119 +909377 +301688 +225579 +307023 +604846 +607457 +267492 +612538 +303861 +201187 +202063 +247634 +296277 +608517 +317184 +240518 +294880 +602645 +311377 +625840 +618123 +617312 +315327 +249337 +293704 +214030 +227197 +256413 +255625 +611299 +239341 +338865 +270086 +247375 +237849 +329088 +304930 +294324 +295211 +340025 +255141 +255183 +287654 +207430 +244999 +241608 +200403 +250342 +325780 +311637 +279622 +231093 +253359 +268630 +226628 +338265 +331081 +318722 +619093 +328969 +200749 +252273 +285505 +259530 +327194 +221897 +268362 +236013 +252179 +253631 +205537 +626664 +235694 +295642 +622043 +222590 +222999 +605371 +291585 +631806 +293564 +200327 +329399 +291772 +218697 +278516 +280595 +613732 +267692 +218859 +233883 +602150 +282046 +200873 +246200 +617485 +279593 +275543 +249816 +322093 +243344 +224798 +258334 +234167 +214249 +612580 +223411 +624887 +331196 +311292 +330925 +263073 +236392 +274258 +253971 +239304 +302515 +612367 +316232 +265352 +301147 +278148 +281654 +254195 +254171 +259751 +330879 +327206 +282512 +260729 +329207 +293714 +324616 +283638 +254985 +313034 +210781 +226487 +320666 +260463 +212508 +322459 +219895 +627591 +338660 +603131 +303153 +239206 +248819 +239251 +268250 +249211 +255635 +607585 +220444 +605826 +286819 +204034 +208259 +281844 +200733 +288487 +281419 +289058 +268290 +286022 +283292 +224042 +304243 +276785 +282345 +311780 +305410 +604032 +608597 +274952 +327008 +327999 +203953 +309966 +201671 +244068 +317354 +282095 +630937 +252761 +220461 +339096 +309403 +223804 +627816 +625923 +221155 +220947 +335410 +278855 +120001 +247840 +336159 +252247 +909901 +619249 +306141 +274059 +227747 +626128 +254820 +274333 +203475 +323318 +257993 +626525 +233226 +328783 +262371 +317957 +330354 +227549 +316527 +285718 +615216 +263522 +266486 +263829 +258461 +316558 +252702 +243179 +237001 +249648 +620220 +248219 +616787 +253554 +220383 +222468 +261591 +216777 +281987 +290657 +294702 +229520 +230675 +284741 +230195 +295736 +226589 +631910 +239831 +328103 +247286 +269177 +310250 +276199 +200176 +315452 +293829 +236712 +253578 +324475 +314822 +269954 +259209 +280890 +608553 +623332 +237170 +263958 +622943 +315049 +281579 +337673 +239451 +320223 +274515 +327561 +230763 +317172 +269904 +235230 +306571 +618258 +314395 +620093 +226852 +313941 +236156 +261747 +229239 +613754 +219971 +234341 +241301 +322060 +237521 +250219 +239271 +612624 +257756 +235880 +212957 +340784 +340371 +287020 +328897 +334443 +219950 +275977 +213939 +232146 +290752 +308391 +242417 +271753 +236435 +631997 +226062 +265772 +329492 +269807 +618188 +313010 +321945 +307338 +300401 +279190 +247597 +303428 +269196 +204279 +220639 +630726 +288262 +244426 +218819 +276894 +315382 +278023 +216239 +228684 +241759 +617071 +303745 +272146 +331859 +235673 +289447 +259218 +314562 +289932 +627781 +286285 +605802 +600074 +622156 +249867 +206912 +336474 +231868 +240186 +316825 +203175 +315679 +228335 +291574 +322495 +617156 +308024 +629950 +237346 +230290 +269672 +620253 +611516 +213803 +254498 +252600 +290805 +331192 +607886 +248726 +263599 +220201 +241504 +270571 +628319 +282060 +248366 +324629 +228504 +212766 +295368 +339248 +248752 +260871 +625278 +230724 +632198 +265710 +265396 +606227 +260686 +254644 +315250 +275813 +236977 +607880 +327667 +293538 +256410 +284366 +605190 +316537 +269716 +603939 +632857 +619040 +227243 +336479 +209622 +251531 +332255 +300052 +329818 +602030 +601827 +224320 +229625 +318652 +628549 +622344 +611621 +285408 +602077 +269831 +261081 +602300 +609081 +253022 +217213 +268226 +258789 +275999 +268519 +301938 +269826 +299382 +258909 +245266 +311881 +321871 +223154 +618099 +228512 +325999 +298434 +228652 +263385 +259295 +316755 +323485 +274559 +317348 +620094 +220431 +8780 +248730 +267888 +9798 +323295 +250348 +289278 +272805 +298916 +274946 +235960 +606100 +288322 +334486 +624453 +211393 +219312 +217257 +239220 +605876 +610916 +229132 +297407 +333810 +296192 +298743 +320378 +282977 +319116 +211326 +231527 +254979 +632161 +628450 +218541 +249081 +260753 +275584 +235039 +317338 +610516 +231111 +279174 +305940 +338040 +275622 +236079 +618308 +312902 +328853 +909923 +321957 +617473 +213037 +608224 +204116 +300545 +242212 +269139 +218075 +269186 +312292 +288578 +254648 +266642 +218952 +277026 +220563 +328826 +622653 +276912 +291740 +333680 +311781 +340297 +219770 +313164 +204509 +327193 +242521 +299455 +291839 +605426 +215863 +201249 +294936 +211400 +318013 +631311 +314743 +239160 +317923 +296689 +202218 +221145 +310465 +294055 +268420 +303419 +317964 +334019 +606618 +323423 +317387 +262337 +309612 +201667 +299333 +326666 +312783 +300094 +329286 +610603 +625700 +257575 +244701 +303744 +247390 +281027 +314408 +211166 +314544 +222654 +608806 +304653 +248020 +218037 +249791 +256428 +298507 +322005 +610427 +630038 +287562 +221854 +301610 +298995 +299998 +212218 +304167 +608734 +283763 +225272 +312701 +622439 +299011 +241421 +606167 +248352 +909208 +329098 +243847 +241630 +302477 +239499 +285808 +279925 +266710 +629785 +220634 +316656 +261712 +315568 +320501 +310637 +318971 +238362 +315157 +301076 +285320 +279559 +267116 +202804 +600730 +311542 +222313 +249176 +318529 +272410 +300373 +239372 +335146 +215890 +233552 +262608 +282672 +257280 +617280 +300637 +258060 +315479 +230834 +340362 +295421 +223524 +234061 +332311 +308794 +268289 +337039 +252086 +252377 +603016 +313781 +331154 +201668 +237727 +264672 +224802 +625937 +253071 +231965 +222343 +253339 +281524 +329370 +602080 +203690 +205768 +627481 +216641 +265676 +613671 +214412 +264722 +624972 +268323 +316705 +309672 +299954 +321463 +255376 +238551 +629498 +338531 +212298 +304760 +234146 +618589 +264699 +236154 +254111 +314427 +218512 +206872 +628649 +228516 +296116 +224857 +241383 +237806 +217239 +293604 +625403 +235121 +327226 +284566 +265411 +306877 +295251 +289327 +319130 +314039 +295280 +317013 +290559 +287088 +319210 +262820 +251785 +282873 +8668 +297639 +240483 +332201 +299934 +209704 +267399 +332280 +328577 +606963 +628116 +314262 +603521 +262044 +243285 +295517 +608092 +221427 +298480 +220863 +287391 +276017 +234394 +211760 +269264 +622358 +605740 +612275 +244618 +317700 +232942 +316853 +602478 +224122 +256507 +257740 +241384 +254451 +282785 +297518 +308897 +263584 +290500 +214157 +623667 +327088 +273643 +234092 +258685 +614199 +322194 +276804 +212459 +262017 +284932 +255391 +299857 +302281 +247774 +279447 +314805 +613931 +321899 +289397 +277762 +327434 +245288 +617462 +279944 +257931 +210642 +237794 +303500 +229061 +297470 +300026 +210520 +315488 +206883 +295733 +622633 +309858 +223819 +231168 +303602 +214895 +200238 +8776 +327726 +233066 +236469 +323390 +263179 +299385 +295843 +287257 +615517 +609662 +335866 +268180 +618921 +275880 +256524 +320879 +254639 +219475 +245737 +608813 +616052 +309451 +307119 +258058 +273143 +241742 +236379 +605512 +222079 +242949 +314037 +308045 +276976 +294542 +324613 +616075 +311769 +299519 +333747 +247641 +251839 +309776 +212782 +239339 +607881 +223383 +278208 +239467 +320401 +216023 +232823 +273431 +278593 +226306 +224328 +235731 +327954 +235980 +244265 +243450 +275709 +223158 +241557 +230842 +621218 +603482 +218351 +282220 +262291 +611057 +306502 +603429 +253604 +287658 +230667 +309657 +246351 +623826 +219625 +272284 +276923 +211384 +618910 +224841 +268544 +307593 +260742 +259285 +316723 +246274 +9820 +327227 +295673 +236386 +263223 +100036 +320422 +242699 +227057 +320593 +605178 +224609 +226207 +235173 +268463 +201222 +277201 +307998 +293825 +9870 +308530 +228773 +236530 +219460 +255187 +272437 +201418 +220959 +315630 +315115 +251174 +239193 +260328 +327760 +269294 +286903 +215224 +303114 +239470 +318508 +214467 +328541 +230279 +298489 +615545 +213414 +252044 +295224 +330833 +300197 +331122 +239463 +629304 +233973 +287510 +612536 +260048 +224525 +341531 +242189 +230550 +276004 +215918 +256533 +630853 +283554 +229337 +215868 +200889 +225544 +247022 +254562 +237425 +263422 +263760 +230884 +282797 +296102 +289911 +218282 +626461 +262387 +278763 +602706 +226017 +200620 +269273 +601205 +618536 +287129 +290853 +317521 +235498 +632272 +609942 +261748 +316426 +273014 +226563 +220401 +256393 +272549 +218053 +248294 +235923 +308535 +247075 +215068 +266549 +611085 +318035 +608174 +334213 +232125 +630033 +609543 +330432 +241536 +237505 +268355 +305522 +612671 +322153 +219424 +274950 +306994 +321642 +243195 +619687 +257210 +296585 +312118 +219966 +247542 +200253 +251382 +285586 +256555 +612547 +276186 +261504 +297921 +607786 +219453 +236858 +232062 +273840 +238242 +219268 +262200 +601166 +286105 +309560 +228032 +236122 +260431 +331184 +289642 +215040 +259256 +605460 +8718 +270579 +249283 +246289 +299374 +219357 +239230 +283449 +244380 +622033 +322844 +609878 +339223 +233896 +276645 +261593 +246362 +259454 +324351 +310190 +231137 +235931 +317250 +311149 +325381 +255375 +316086 +628439 +268430 +301703 +258830 +327047 +618834 +248155 +600954 +259426 +317820 +259205 +225654 +215271 +260204 +603098 +249223 +210675 +306610 +268287 +278173 +331145 +278402 +233876 +235834 +220974 +339237 +250590 +228619 +226744 +300390 +309688 +219667 +8697 +209050 +312078 +252768 +216217 +217980 +263575 +266604 +213706 +291482 +631104 +310510 +626633 +237116 +323626 +267571 +323264 +321926 +305266 +214678 +286683 +610389 +234214 +329341 +278277 +239529 +329996 +284984 +246542 +322276 +286978 +256573 +611143 +228583 +322856 +335205 +251677 +337122 +618074 +320007 +281408 +213010 +315398 +628644 +308914 +322006 +254478 +254782 +318988 +212214 +306021 +295983 +272965 +228770 +631786 +276425 +248304 +303601 +241822 +631962 +252088 +218004 +230474 +627521 +272388 +318782 +624767 +297903 +332402 +311920 +323743 +329284 +239292 +288754 +274085 +314583 +618229 +298369 +268813 +339747 +610453 +227749 +255779 +608991 +294949 +627329 +623714 +619627 +241114 +261469 +609057 +290864 +322114 +253925 +612076 +279347 +312314 +298094 +212423 +248438 +329741 +910608 +291166 +295194 +268421 +283706 +327405 +629541 +318763 +632295 +283050 +295187 +613500 +310944 +328146 +9707 +621256 +217755 +605172 +610256 +602820 +270490 +624943 +331472 +317898 +302299 +265327 +261453 +235552 +236641 +274375 +317079 +230957 +616960 +289262 +228330 +326879 +224954 +606952 +269804 +320081 +298314 +601126 +216248 +232932 +299920 +327975 +249217 +202033 +340063 +220852 +221062 +216404 +321702 +262060 +256423 +340956 +328731 +254907 +250189 +266090 +322797 +306445 +314129 +291728 +207182 +605825 +213009 +269892 +316394 +268170 +243593 +262733 +268189 +315241 +256562 +607607 +305309 +279976 +628722 +327336 +601810 +308333 +216499 +211252 +229459 +618641 +608623 +322162 +326361 +223759 +313002 +327398 +610416 +291521 +294943 +315217 +303877 +324631 +219292 +322551 +612257 +631840 +212458 +279967 +337591 +231519 +299075 +273518 +276862 +293514 +220434 +230274 +224053 +610598 +268259 +309820 +328637 +230456 +605442 +908350 +267143 +324139 +261342 +283404 +317882 +240556 +230891 +260918 +241683 +614347 +337906 +232914 +285417 +273569 +602666 +618578 +615300 +221238 +328037 +264286 +243860 +314244 +220357 +282105 +263447 +278364 +205905 +267679 +338527 +297474 +245280 +331486 +307754 +265650 +302473 +213850 +227950 +317019 +259462 +223151 +226783 +631517 +321186 +320821 +913482 +625509 +222323 +248801 +265473 +265455 +237143 +333709 +234344 +625455 +333644 +333847 +283610 +234974 +327740 +263903 +289219 +316517 +306630 +202445 +611223 +267552 +244947 +301689 +216048 +322099 +228821 +289694 +605879 +316940 +607153 +290002 +616803 +267258 +600826 +282991 +603386 +623620 +317442 +304999 +257646 +268504 +242352 +632688 +247642 +220492 +249675 +279153 +612296 +236183 +284389 +335004 +256513 +324186 +608346 +269180 +265966 +200405 +230618 +269893 +285991 +200808 +262649 +331042 +289672 +284678 +230875 +261718 +232362 +203134 +284551 +320339 +234209 +261566 +234705 +625742 +222936 +629510 +623392 +237580 +291593 +277481 +285162 +295208 +267224 +231073 +268479 +253720 +618289 +254105 +232155 +628974 +8551 +293847 +296050 +322749 +301369 +286141 +213998 +281093 +625774 +222444 +254667 +337965 +298187 +289311 +219752 +606691 +254839 +252695 +307315 +611074 +272520 +299042 +299372 +249468 +230492 +268476 +254637 +613237 +220323 +235720 +272348 +316592 +291092 +317436 +247328 +232188 +615882 +307209 +277570 +231020 +324605 +240271 +272783 +608509 +616358 +265540 +294464 +303921 +268701 +220948 +331815 +322725 +257891 +243071 +336080 +326466 +260073 +293502 +609228 +223590 +274523 +247671 +303833 +311255 +311194 +256465 +308513 +274743 +266636 +239158 +237840 +223424 +282085 +280581 +231913 +211108 +321798 +318287 +220894 +245216 +286608 +293712 +204730 +338421 +314922 +293434 +304603 +278410 +255254 +296503 +301213 +303713 +607453 +311972 +286580 +267081 +610889 +294099 +261178 +266200 +224789 +291782 +288124 +315213 +230709 +228625 +337705 +9810 +263466 +315298 +291763 +267042 +258926 +255180 +314219 +274716 +318121 +233458 +299136 +322144 +303313 +212036 +9891 +330805 +276106 +202162 +323901 +335122 +221902 +306536 +621394 +320404 +303586 +274324 +214402 +610534 +301130 +301731 +300924 +230807 +276682 +249930 +213824 +207122 +321339 +278276 +280168 +223581 +617432 +232675 +8710 +631612 +274133 +212781 +249253 +247977 +604347 +328741 +219688 +226352 +312605 +609757 +249533 +608885 +304078 +326385 +310275 +255150 +321693 +308372 +247512 +326788 +301909 +214395 +913576 +282957 +229639 +281257 +627856 +329526 +249209 +227497 +320725 +294183 +214777 +303845 +255243 +215995 +611826 +287110 +304001 +618610 +327545 +619168 +231075 +625585 +314066 +317446 +314506 +235425 +274268 +329070 +212206 +265434 +269263 +322088 +274387 +216211 +251972 +320649 +225193 +331687 +619069 +236493 +338274 +340045 +266474 +250209 +333242 +312609 +241718 +208173 +304221 +288531 +220419 +294182 +612212 +625528 +230661 +284562 +255406 +259668 +215821 +237614 +234823 +236342 +219913 +248023 +232294 +257906 +273900 +201144 +206966 +273339 +226375 +306474 +205941 +208986 +321735 +328381 +308432 +254053 +304023 +269022 +218440 +206275 +266320 +326060 +289300 +246574 +298672 +235491 +235117 +308610 +328531 +303502 +615117 +293581 +269243 +294408 +215893 +327195 +237238 +276201 +306589 +237252 +301171 +631339 +278832 +331751 +233348 +226371 +277742 +283121 +608528 +260916 +330530 +614847 +327165 +219547 +214859 +603993 +8479 +228346 +237010 +321748 +256766 +339950 +248001 +321915 +236012 +321580 +289092 +290056 +278195 +249254 +304948 +276190 +319956 +320209 +309849 +8446 +631265 +253080 +256783 +294901 +619132 +255579 +320377 +308438 +269830 +300353 +241924 +268396 +230843 +257340 +260056 +300528 +301362 +203590 +224793 +273551 +603577 +615170 +317950 +255190 +230088 +268205 +246850 +259419 +224860 +286520 +609709 +616966 +257258 +310360 +282131 +244035 +286485 +244165 +266401 +625377 +256808 +259398 +304073 +631884 +337752 +630772 +625920 +335260 +314567 +619555 +252921 +323861 +230978 +246797 +226316 +278535 +217223 +603805 +910123 +622617 +284898 +242332 +610917 +228436 +262111 +604603 +212230 +607737 +322305 +259056 +913847 +251992 +624973 +263905 +315324 +316490 +252351 +249329 +276749 +629485 +601857 +328793 +291349 +622915 +202204 +624598 +611606 +604472 +607652 +228573 +212942 +220280 +295088 +290201 +276920 +289536 +333374 +301010 +307737 +312833 +230654 +304201 +222918 +310930 +228403 +338517 +623984 +231063 +620278 +274161 +612569 +290042 +603396 +284838 +600196 +323734 +247831 +221812 +295152 +256324 +329704 +623293 +313096 +313341 +233801 +314135 +299550 +269670 +231962 +318367 +255588 +341131 +291760 +631316 +257041 +243837 +263790 +315114 +224259 +281591 +280584 +603608 +217651 +275735 +284602 +244012 +222239 +291058 +261323 +318603 +254408 +216592 +323410 +248864 +254006 +218414 +321787 +203479 +314468 +294042 +612337 +218643 +251589 +230636 +331163 +270318 +226973 +236134 +269128 +245038 +627270 +241958 +254162 +618444 +252974 +237091 +215749 +271929 +627579 +249697 +216289 +308497 +631178 +256572 +316808 +303741 +269058 +297857 +211288 +265865 +231014 +282540 +265706 +609553 +617656 +258723 +219406 +219597 +314254 +321172 +255533 +252320 +305207 +616140 +278273 +261585 +613678 +604770 +220861 +340324 +258365 +607405 +203324 +252917 +249429 +262482 +608950 +227192 +608396 +608843 +296164 +601003 +219773 +273224 +283663 +245460 +221721 +212147 +612663 +249060 +224889 +253104 +912061 +230849 +607596 +613369 +233467 +256873 +632284 +238756 +618358 +230367 +228882 +236214 +235334 +256515 +247735 +322208 +256290 +245163 +623605 +220177 +224381 +611650 +336540 +245843 +237225 +336642 +262451 +258677 +612763 +293544 +265919 +220443 +236370 +231665 +236457 +606982 +219452 +273525 +286745 +318353 +227055 +249396 +321670 +250154 +283018 +287609 +617162 +268428 +284369 +246434 +293479 +235482 +211363 +216072 +257453 +236628 +315586 +295114 +216815 +277126 +248488 +208702 +316655 +247945 +612699 +228971 +235210 +216049 +278948 +226156 +241679 +232648 +288238 +625821 +252883 +273290 +262470 +327441 +328666 +626805 +333605 +232527 +226454 +326961 +299973 +216104 +226600 +253407 +240467 +247559 +328334 +243544 +268337 +282280 +260559 +311477 +213999 +9941 +278268 +268248 +308395 +258724 +235403 +252147 +273654 +302113 +612231 +208971 +214538 +314765 +604677 +217639 +247866 +304815 +630923 +258203 +248064 +290843 +293891 +263067 +228780 +615767 +631543 +282374 +233640 +201502 +248484 +623352 +256451 +255776 +265409 +625892 +312100 +618935 +221706 +230815 +257638 +618303 +609172 +605399 +232156 +626336 +294740 +628366 +335545 +252305 +295367 +302806 +257831 +339147 +259521 +261925 +200699 +219161 +237773 +625671 +215952 +288945 +273107 +312642 +314515 +219412 +252207 +224796 +287487 +236923 +287100 +226409 +234996 +283775 +265176 +256974 +299522 +286573 +207292 +241873 +238803 +306559 +230838 +296013 +248231 +253825 +288307 +282101 +287424 +266587 +322013 +277047 +254064 +249216 +233484 +272974 +294682 +245136 +224091 +261527 +328794 +219380 +220181 +318516 +321760 +224755 +303446 +627524 +260777 +256850 +308680 +299639 +291049 +266262 +314396 +308019 +238258 +252872 +235076 +631246 +217335 +205773 +252019 +232411 +218416 +275548 +239453 +281830 +293430 +321295 +330505 +272286 +254794 +275988 +303735 +618764 +626764 +326672 +299676 +223799 +272431 +309255 +298935 +223254 +256755 +279396 +244374 +256435 +247223 +307679 +603418 +219036 +608575 +222719 +262336 +216682 +302309 +235038 +618202 +602812 +280221 +263525 +628757 +296003 +255412 +243473 +330352 +603885 +255222 +283080 +302255 +244114 +317497 +235456 +913055 +260920 +626976 +625253 +631057 +283291 +215134 +324333 +332366 +262023 +308371 +285647 +322694 +299251 +253666 +225503 +276771 +313398 +247503 +286265 +616346 +263239 +295968 +269136 +211536 +301398 +233270 +244982 +265972 +299777 +327586 +286079 +305495 +230052 +239781 +249303 +628563 +262948 +328480 +286834 +333821 +326903 +265514 +314335 +632071 +298841 +285243 +298740 +625160 +613295 +327563 +610578 +225929 +221834 +218814 +267401 +305137 +232145 +201379 +298283 +308997 +631041 +315423 +291383 +333851 +256560 +274083 +220489 +339374 +623425 +231199 +258868 +254866 +202213 +212825 +321938 +229099 +297173 +262072 +602437 +323992 +269334 +290775 +325883 +233543 +201936 +278510 +211906 +301119 +316647 +609355 +303445 +224933 +259015 +232216 +307184 +261860 +600411 +282276 +249891 +339778 +622879 +257493 +229441 +305499 +265608 +911616 +606229 +211696 +275082 +240910 +606583 +623836 +234841 +218076 +307465 +227952 +278538 +275902 +247912 +262160 +217951 +602391 +280126 +264517 +324150 +340279 +251427 +260153 +324345 +609073 +256602 +239310 +302684 +624739 +283876 +334260 +321278 +304150 +252470 +277200 +632508 +612338 +210538 +336460 +277755 +225913 +303449 +318235 +315469 +220978 +294376 +283771 +305912 +321489 +321933 +621269 +247669 +260039 +627476 +239459 +308350 +227431 +261101 +327051 +266331 +258655 +315963 +266045 +309589 +317228 +249997 +266737 +603986 +627206 +270519 +231013 +299768 +610671 +219343 +290771 +621958 +218802 +262746 +609585 +326812 +621278 +219493 +333177 +256426 +610350 +309028 +277018 +263325 +9628 +625372 +286366 +275703 +232141 +318355 +314241 +228644 +301157 +214728 +312785 +231854 +293444 +318994 +322110 +303710 +269271 +241295 +302181 +300393 +269905 +244327 +301008 +271671 +247852 +247996 +281920 +217589 +327446 +276684 +235973 +601700 +218432 +312763 +319014 +211583 +340046 +257974 +280161 +298449 +266887 +328664 +273759 +610897 +300907 +254455 +300411 +307494 +236295 +267436 +316502 +307535 +300672 +291795 +332144 +221004 +276827 +282739 +244961 +300859 +237517 +252822 +238176 +233433 +249552 +296642 +608777 +258806 +220957 +323606 +279765 +245016 +291815 +286551 +610404 +269065 +266833 +255760 +315067 +608608 +201029 +268515 +623499 +217049 +236127 +625883 +256868 +624520 +247948 +246918 +287624 +220586 +621894 +258098 +234999 +329816 +626158 +340527 +340964 +600929 +8431 +618081 +270716 +264816 +337568 +318228 +613977 +242187 +610436 +231648 +628643 +257024 +236320 +9631 +313038 +911177 +216408 +294371 +216537 +611132 +239512 +618086 +288704 +213302 +274984 +219923 +9927 +314560 +326425 +213068 +266080 +302421 +233596 +283873 +286706 +616180 +221359 +272470 +630974 +312168 +221198 +296540 +330057 +324612 +277767 +618562 +258654 +227420 +223105 +252935 +247794 +294780 +234148 +334216 +612207 +200805 +249096 +338720 +276810 +257483 +613600 +248085 +291321 +220682 +277796 +268319 +608774 +274406 +247485 +632200 +287563 +257403 +212120 +277059 +249671 +298513 +322875 +210584 +286179 +239999 +298319 +219976 +629982 +324400 +226956 +220545 +307755 +241595 +280117 +294200 +602152 +218041 +276487 +618598 +313522 +608311 +604646 +337603 +302811 +631202 +308674 +276153 +329513 +261948 +313000 +327065 +269204 +256534 +295977 +252496 +267171 +303461 +289995 +218636 +301982 +215368 +304932 +200800 +221533 +258351 +322821 +274684 +340438 +321033 +602450 +222240 +228686 +268343 +246193 +618471 +311775 +286205 +265825 +605664 +223533 +250197 +620069 +272402 +303577 +331835 +293445 +248728 +288377 +228853 +287613 +605777 +631738 +251527 +322106 +240763 +235996 +911550 +252173 +339379 +911660 +263076 +623775 +261359 +618571 +272717 +254780 +609000 +609284 +260427 +242311 +239195 +276589 +245122 +618128 +328214 +260435 +289085 +213390 +312111 +273086 +228035 +228536 +229635 +286770 +288315 +331989 +310457 +628020 +308082 +289257 +223784 +609696 +231940 +213095 +243387 +616622 +615040 +235952 +205079 +278890 +242958 +295345 +212659 +275522 +232052 +312463 +278804 +284859 +295810 +284845 +286772 +612309 +288691 +306992 +268336 +243633 +253075 +296250 +605598 +290000 +335936 +296010 +221484 +909806 +239749 +265144 +201634 +284498 +322425 +300354 +248583 +247938 +262798 +291776 +247614 +301015 +327143 +303780 +308549 +329349 +336439 +288042 +309433 +242141 +301637 +217411 +286497 +277092 +272611 +312424 +255049 +211956 +200346 +297520 +211488 +328102 +239426 +296307 +334544 +336736 +244147 +293786 +237900 +249206 +268427 +238726 +322809 +607861 +304875 +315436 +615604 +251950 +267579 +253662 +631630 +233758 +273403 +258883 +273758 +602012 +265240 +247574 +321816 +273790 +249297 +321630 +233335 +624740 +220512 +253873 +263859 +335489 +279239 +262741 +224232 +210373 +300259 +318023 +628028 +237223 +257822 +276303 +265629 +312788 +255075 +612669 +269245 +605429 +625970 +258580 +228023 +257377 +220079 +267223 +326345 +289193 +288308 +260607 +289800 +330562 +303527 +293660 +335263 +305938 +218529 +218086 +318944 +307062 +315435 +235766 +619682 +261658 +217173 +239931 +328911 +241745 +913473 +223007 +304301 +240602 +299194 +221069 +314458 +212631 +220021 +623413 +336748 +245437 +281661 +267862 +312938 +318496 +299674 +268806 +265851 +322185 +262028 +626959 +9999 +305485 +307061 +299263 +214250 +300371 +272945 +243845 +224768 +302135 +313082 +251172 +288769 +259770 +310357 +224318 +626828 +288565 +261302 +270028 +622608 +318910 +297435 +230765 +263510 +327763 +246256 +286998 +603266 +230874 +246802 +625204 +622806 +255216 +329729 +328163 +212345 +280778 +323183 +318205 +256497 +310421 +270612 +618633 +256492 +301474 +288048 +267348 +227756 +223075 +326107 +306090 +606988 +229650 +299666 +256574 +912205 +331241 +300013 +266181 +627474 +287607 +611667 +230922 +274680 +258299 +9736 +302637 +247525 +205294 +327146 +338756 +321822 +220080 +237488 +231864 +264873 +246536 +605867 +328746 +224800 +273316 +262505 +298491 +628855 +243626 +324514 +218694 +202239 +200583 +203831 +629051 +320078 +282378 +212723 +629482 +239603 +262840 +613468 +600707 +254897 +265132 +269693 +333802 +275964 +299621 +629579 +274842 +623038 +222635 +246549 +284536 +334303 +623128 +321040 +305341 +298012 +331065 +274882 +312764 +318901 +273021 +252830 +293770 +608771 +630756 +314411 +224607 +228589 +228130 +248735 +206546 +620148 +256456 +304884 +224790 +608163 +234199 +266360 +214685 +220822 +249025 +282922 +221310 +245563 +602624 +246026 +333171 +303633 +280658 +612958 +281517 +237555 +623072 +290255 +294604 +216436 +204582 +242220 +290494 +620130 +242809 +240168 +310898 +282825 +217728 +312445 +325335 +312013 +328378 +250172 +323419 +270539 +321029 +230822 +252949 +601062 +226593 +8566 +279307 +286822 +212011 +236020 +314015 +222174 +608185 +235741 +606091 +249624 +610591 +629018 +255662 +214547 +264694 +294810 +338944 +340988 +298596 +219305 +299685 +200216 +300388 +260699 +287733 +273309 +273629 +604997 +299862 +254701 +200758 +316964 +231554 +315604 +299026 +210389 +337187 +260644 +612471 +239511 +310820 +251897 +273648 +244103 +617173 +237486 +274821 +339306 +266051 +316479 +607452 +280879 +265155 +322708 +273524 +336204 +221135 +627111 +329689 +249375 +282106 +249685 +608540 +227490 +213734 +284906 +310052 +274039 +277203 +236031 +202967 +210011 +219008 +217972 +223965 +630897 +314704 +612747 +316352 +283302 +270138 +294033 +275808 +276699 +255742 +254819 +239343 +267589 +279980 +235329 +215387 +607080 +607669 +239844 +606017 +280840 +330033 +617629 +249711 +625198 +212939 +247142 +222291 +261752 +226144 +332057 +335011 +247298 +626616 +260018 +243813 +294667 +602547 +276973 +327965 +249678 +223975 +324495 +278588 +324602 +295260 +335949 +227610 +281493 +262600 +609492 +626424 +286601 +247594 +319067 +624073 +626234 +224844 +298276 +283130 +221152 +216105 +607577 +280371 +618756 +215507 +302490 +262806 +230911 +254827 +226455 +330271 +120209 +321592 +307311 +237110 +320197 +262954 +224312 +248311 +308117 +329463 +200641 +244499 +275096 +624861 +291319 +295129 +340328 +201865 +298208 +289067 +315723 +219908 +330716 +226571 +294666 +244364 +336078 +266213 +321755 +8711 +330458 +314609 +335010 +277144 +249689 +322253 +608382 +605630 +272204 +245128 +216741 +218030 +284544 +210999 +324349 +631289 +293763 +251759 +256292 +311122 +269906 +276122 +608028 +211388 +231646 +302799 +275047 +628585 +255368 +268458 +239456 +300150 +608100 +606839 +242129 +265299 +330100 +220094 +256434 +294232 +287435 +321980 +262289 +304013 +314311 +210092 +314348 +236011 +257669 +340451 +257401 +246682 +282664 +606643 +618240 +329945 +270212 +284415 +338965 +340233 +298735 +227020 +268229 +283595 +212117 +609491 +263044 +290154 +255877 +263647 +249156 +282865 +288295 +239232 +613844 +614733 +224815 +312430 +204083 +318903 +208499 +219672 +280873 +318178 +627715 +306086 +245200 +606953 +221456 +321104 +340087 +260141 +241653 +606831 +312274 +316390 +316419 +328416 +330789 +605467 +263206 +628010 +279508 +285106 +220537 +630058 +287431 +240356 +227700 +259684 +256395 +200787 +612267 +293531 +205007 +217050 +9735 +249543 +257943 +218454 +246633 +249892 +224884 +264508 +312071 +221187 +257080 +288516 +305208 +302639 +213609 +603091 +248268 +304132 +261584 +270526 +234333 +208471 +295283 +249740 +624396 +262443 +296024 +303682 +216068 +276808 +270434 +325278 +215280 +288717 +267841 +224982 +212008 +331932 +276982 +609736 +222509 +223404 +268398 +609020 +223882 +250170 +618269 +340975 +285311 +282312 +267763 +339939 +338936 +605847 +254376 +303981 +605200 +607155 +248197 +276887 +605814 +263210 +261391 +218516 +295050 +212414 +281156 +241401 +293999 +258457 +253529 +236779 +256281 +267191 +260820 +259286 +260872 +216585 +233146 +212331 +8690 +267686 +609894 +615265 +326115 +247491 +240826 +619024 +246553 +335592 +235258 +260572 +268318 +283177 +255110 +245405 +330255 +338402 +604984 +299335 +296691 +302425 +304033 +216751 +276990 +628361 +268464 +275519 +264687 +239743 +288914 +316616 +212859 +609556 +208019 +270593 +260100 +603509 +303813 +617553 +316919 +327606 +316662 +608014 +244367 +283300 +299000 +282746 +305815 +629725 +289161 +303537 diff --git a/interactive-mining-madoap/madoap/src/static/interactivemining.js b/interactive-mining-madoap/madoap/src/static/interactivemining.js new file mode 100644 index 0000000..0904a28 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/static/interactivemining.js @@ -0,0 +1,508 @@ +function handleLoadExampleFile() { + $("#file-input-operation").val('example'); + $("#file-title-text").html(''); + $('#file-input').val(''); + var formData = new FormData($("form#file-input-form")[0]); + $.ajax({ + url: "importing-controller", + type: 'POST', + data: formData, + async: false, + success: function (data) { + $('#file-upload-response').html(JSON.parse(data).respond) + // if (data.indexOf('successfully!') != -1) { + // $('#file-uploaded')[0].checked = true; + // } + }, + error: function (xhr, ajaxOptions, thrownError) { + $('#file-upload-response').html('File Failed to Upload!'+xhr.status) + // $('#file-uploaded')[0].checked = false; + }, + cache: false, + contentType: false, + processData: false + }); +} + +$( window ).resize(function() { + $("#file-input-label").width($(".file-upload-wrapper").width() - 250 +"px"); +}); + +(function(){ + + function getCookie(name) { + var value = "; " + document.cookie; + var parts = value.split("; " + name + "="); + if (parts.length == 2) return parts.pop().split(";").shift(); + } + +////////// UPLOAD FUNCTIONS + + $( '.inputfile' ).each( function() + { + var $input = $( this ), + $label = $input.next( 'label' ), + labelVal = $label.html(); + + $input.on( 'change', function( e ) + { + var fileName = ''; + + if( this.files && this.files.length > 1 ) + fileName = ( this.getAttribute( 'data-multiple-caption' ) || '' ).replace( '{count}', this.files.length ); + else if( e.target.value ) + fileName = e.target.value.split( '\\' ).pop(); + + if( fileName ) + $label.find( 'span' ).html( fileName ); + else + $label.html( labelVal ); + }); + + // Firefox bug fix + $input + .on( 'focus', function(){ $input.addClass( 'has-focus' ); }) + .on( 'blur', function(){ $input.removeClass( 'has-focus' ); }); + }); + + function handleFileUploadButton() { + $("form#file-input-form").submit(function(){ + if ($('#file-input')[0].value === "") { + window.alert("You must specify a data file to import."); + return false; + } + // $('#user-id').val(getCookie("madgikmining")); + $("#file-input-operation").val('normal'); + var formData = new FormData($(this)[0]); + $.ajax({ + url: "importing-controller", + type: 'POST', + data: formData, + async: false, + success: function (data) { + $('#file-upload-response').html(JSON.parse(data).respond) + // if (data.indexOf('successfully!') != -1) { + // $('#file-uploaded')[0].checked = true; + // } + }, + error: function (xhr, ajaxOptions, thrownError) { + $('#file-upload-response').html('File Failed to Upload!'+xhr.status) + // $('#file-uploaded')[0].checked = false; + }, + cache: false, + contentType: false, + processData: false + }); + + return false; + }); + } + + function handleZipFileUploadButton() { + $("form#zip-file-input-form").submit(function(){ + if ($('#zip-file-input')[0].value === "") { + window.alert("You must specify a data file to import."); + return false; + } + // $('#user-id').val(getCookie("madgikmining")); + var formData = new FormData($(this)[0]); + $.ajax({ + url: "importing-text-controller", + type: 'POST', + data: formData, + async: false, + success: function (data) { + $('#zip-file-upload-response').html(JSON.parse(data).respond) + if (data.indexOf('successfully!') != -1) { + $('#docs-file-uploaded')[0].checked = true; + } + }, + error: function (xhr, ajaxOptions, thrownError) { + $('#zip-file-upload-response').html('File Failed to Upload!'+xhr.status); + $('#docs-file-uploaded')[0].checked = false; + }, + cache: false, + contentType: false, + processData: false + }); + + return false; + }); + } + + function handleDocsUploadSelect() { + $('select#textUploadSelect').change(function(){ + $('#docs-file-uploaded')[0].checked = false; + if($(this).val()=="1") { + $('#docUploadText').show(); + $('#docUploadText').children(".title").html("Choose .PDF document file to upload"); + $('#docPasteExample').css('display', 'none'); + $('#docPasteText').html(""); + } + else if ($(this).val()=="2") { + $('#docUploadText').show(); + $('#docUploadText').children(".title").html("Choose .TXT document with JSON format file to upload"); + $('#docPasteExample').css('display', 'none'); + $('#docPasteText').html(""); + } + else { + $('#docUploadText').css('display', 'none'); + $('#docPasteExample').css('display', 'inline'); + $('#docPasteText').html(''); + } + }); + } + + +/////////// LIST FUNCTIONS + + var count_pos = 0, count_neg = 0; + + function updatetextereas(){ + // Create the positive and negative words input to send to the server with json format + $('#pos-words-text').html(''); + $('#neg-words-text').html(''); + pos_words_list = {}; + neg_words_list = {}; + for(var key in localStorage){ + if (key === null) + continue; + var json_string = localStorage.getItem(key); + data = JSON.parse(json_string); + if(key.indexOf('positive') === 0){ + pos_words_list[data.text] = data.weight; + } else if(key.indexOf('negative') === 0) { + neg_words_list[data.text] = data.weight; + } + } + $('#pos-words-text').html(JSON.stringify(pos_words_list)); + $('#neg-words-text').html(JSON.stringify(neg_words_list)); + } + + function updateCounter(is_pos){ + if (is_pos === 1) { + $('#count-pos').text(count_pos); + var deleteButton = $('#clear-all-pos'); + if(count_pos === 0){ + deleteButton.attr('disabled', 'disabled').addClass('disabled'); + } + else{ + deleteButton.removeAttr('disabled').removeClass('disabled'); + } + } else { + $('#count-neg').text(count_neg); + var deleteButton = $('#clear-all-neg'); + if(count_neg === 0){ + deleteButton.attr('disabled', 'disabled').addClass('disabled'); + } + else{ + deleteButton.removeAttr('disabled').removeClass('disabled'); + } + } + } + //generates a unique id + function generateId(is_pos){ + if (is_pos) { + return "positive-" + +new Date(); + } else { + return "negative-" + +new Date(); + } + } + //saves a text-weight pair in json format to localStorage + var saveWord = function(id, content_word, content_weight){ + var obj = {}; + obj["text"] = content_word; + obj["weight"] = content_weight; + localStorage.setItem(id, JSON.stringify(obj)); + }; + + // var editWord = function(is_pos, id){ + // var $this = $('#' + id); + // $this.focus() + // .append($(' + +
+ + {% if numOfGrants %} + {{numOfGrants}} Codes loaded successfully! + {% end %} + +
+ +
+ +
+

Add your positive words or phrases

+
+
+
+
Phrase
+
Weight
+
+
+ + + +
+
+
+
+
+
    +
+
+ + +
+
+
+ +
+

Add your negative words or phrases

+
+
+
+
Phrase
+
Weight
+
+
+
+ + + +
+
+
+
+
+
    +
+
+ + +
+
+
+ +
+ +

Insert your Text here:

+ + + +
+
+ +
+ +
+

Select the preprocessing steps to clean your text.

+ +

A filter that removes stop words from the token text.

+ + + +

A filter that normalizes token text to lower case.

+ + + +

A filter that splits the text into words on intra-word delimiters (all non alpha-numeric characters).

+ + +
+ + + + + +
+ +
+ +
+ + + +{% end %} \ No newline at end of file diff --git a/interactive-mining-madoap/madoap/src/templates/madappbar.html b/interactive-mining-madoap/madoap/src/templates/madappbar.html new file mode 100644 index 0000000..ebf650c --- /dev/null +++ b/interactive-mining-madoap/madoap/src/templates/madappbar.html @@ -0,0 +1,43 @@ +{% extends "base.html" %} +{% block profileclass %} class="current" {% end %} +{% block content %} + +Statistics + + +
+ {% block service %} +

Welcome to OpenAIRE statistics service

+ {% end %} +
+{% end %} diff --git a/interactive-mining-madoap/madoap/src/templates/madappview.html b/interactive-mining-madoap/madoap/src/templates/madappview.html new file mode 100644 index 0000000..4e4b29b --- /dev/null +++ b/interactive-mining-madoap/madoap/src/templates/madappview.html @@ -0,0 +1,403 @@ +{% autoescape None %} +{% extends "madappbar.html" %} +{% block jsimports %} +{{app['title']}} + + + + + +{% block loadfun %} + +{% end %} + +{% end %} + +{% block service %} + + +

{{app["title"]}}

+ {% if settings.DEBUG %} + Show query +

+ {% end %} + +

+ + + + + + + + + +
+

Set parameters

+ + + + + + + + + + + + +
+ + + + + + {% for param in app["params"] %} + + + + {% end %} + +
{{param["name"]}}: + + {% if 'values' in param %} + + {% else %} + + + {% end %} +
+
+ + + +
+ +
+

Visualisation


+ {% for vis in app["visualisations"] %} + +
+ {% end %} +
+ + + +
+ +

+
+

+

+ {% if 'template' in app %} + + {% else %} +
+ {% end %} + +{% end %} diff --git a/interactive-mining-madoap/madoap/src/tornado/__init__.py b/interactive-mining-madoap/madoap/src/tornado/__init__.py new file mode 100644 index 0000000..c975de7 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/__init__.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""The Tornado web server and tools.""" + +version = "2.1.1" +version_info = (2, 1, 1) diff --git a/interactive-mining-madoap/madoap/src/tornado/auth.py b/interactive-mining-madoap/madoap/src/tornado/auth.py new file mode 100644 index 0000000..b9f7f57 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/auth.py @@ -0,0 +1,1129 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Implementations of various third-party authentication schemes. + +All the classes in this file are class Mixins designed to be used with +web.py RequestHandler classes. The primary methods for each service are +authenticate_redirect(), authorize_redirect(), and get_authenticated_user(). +The former should be called to redirect the user to, e.g., the OpenID +authentication page on the third party service, and the latter should +be called upon return to get the user data from the data returned by +the third party service. + +They all take slightly different arguments due to the fact all these +services implement authentication and authorization slightly differently. +See the individual service classes below for complete documentation. + +Example usage for Google OpenID:: + + class GoogleHandler(tornado.web.RequestHandler, tornado.auth.GoogleMixin): + @tornado.web.asynchronous + def get(self): + if self.get_argument("openid.mode", None): + self.get_authenticated_user(self.async_callback(self._on_auth)) + return + self.authenticate_redirect() + + def _on_auth(self, user): + if not user: + raise tornado.web.HTTPError(500, "Google auth failed") + # Save the user with, e.g., set_secure_cookie() +""" + +import base64 +import binascii +import hashlib +import hmac +import logging +import time +import urllib +import urlparse +import uuid + +from tornado import httpclient +from tornado import escape +from tornado.httputil import url_concat +from tornado.util import bytes_type, b + +class OpenIdMixin(object): + """Abstract implementation of OpenID and Attribute Exchange. + + See GoogleMixin below for example implementations. + """ + def authenticate_redirect(self, callback_uri=None, + ax_attrs=["name","email","language","username"]): + """Returns the authentication URL for this service. + + After authentication, the service will redirect back to the given + callback URI. + + We request the given attributes for the authenticated user by + default (name, email, language, and username). If you don't need + all those attributes for your app, you can request fewer with + the ax_attrs keyword argument. + """ + callback_uri = callback_uri or self.request.uri + args = self._openid_args(callback_uri, ax_attrs=ax_attrs) + self.redirect(self._OPENID_ENDPOINT + "?" + urllib.urlencode(args)) + + def get_authenticated_user(self, callback, http_client=None): + """Fetches the authenticated user data upon redirect. + + This method should be called by the handler that receives the + redirect from the authenticate_redirect() or authorize_redirect() + methods. + """ + # Verify the OpenID response via direct request to the OP + args = dict((k, v[-1]) for k, v in self.request.arguments.iteritems()) + args["openid.mode"] = u"check_authentication" + url = self._OPENID_ENDPOINT + if http_client is None: http_client = httpclient.AsyncHTTPClient() + http_client.fetch(url, self.async_callback( + self._on_authentication_verified, callback), + method="POST", body=urllib.urlencode(args)) + + def _openid_args(self, callback_uri, ax_attrs=[], oauth_scope=None): + url = urlparse.urljoin(self.request.full_url(), callback_uri) + args = { + "openid.ns": "http://specs.openid.net/auth/2.0", + "openid.claimed_id": + "http://specs.openid.net/auth/2.0/identifier_select", + "openid.identity": + "http://specs.openid.net/auth/2.0/identifier_select", + "openid.return_to": url, + "openid.realm": urlparse.urljoin(url, '/'), + "openid.mode": "checkid_setup", + } + if ax_attrs: + args.update({ + "openid.ns.ax": "http://openid.net/srv/ax/1.0", + "openid.ax.mode": "fetch_request", + }) + ax_attrs = set(ax_attrs) + required = [] + if "name" in ax_attrs: + ax_attrs -= set(["name", "firstname", "fullname", "lastname"]) + required += ["firstname", "fullname", "lastname"] + args.update({ + "openid.ax.type.firstname": + "http://axschema.org/namePerson/first", + "openid.ax.type.fullname": + "http://axschema.org/namePerson", + "openid.ax.type.lastname": + "http://axschema.org/namePerson/last", + }) + known_attrs = { + "email": "http://axschema.org/contact/email", + "language": "http://axschema.org/pref/language", + "username": "http://axschema.org/namePerson/friendly", + } + for name in ax_attrs: + args["openid.ax.type." + name] = known_attrs[name] + required.append(name) + args["openid.ax.required"] = ",".join(required) + if oauth_scope: + args.update({ + "openid.ns.oauth": + "http://specs.openid.net/extensions/oauth/1.0", + "openid.oauth.consumer": self.request.host.split(":")[0], + "openid.oauth.scope": oauth_scope, + }) + return args + + def _on_authentication_verified(self, callback, response): + if response.error or b("is_valid:true") not in response.body: + logging.warning("Invalid OpenID response: %s", response.error or + response.body) + callback(None) + return + + # Make sure we got back at least an email from attribute exchange + ax_ns = None + for name in self.request.arguments.iterkeys(): + if name.startswith("openid.ns.") and \ + self.get_argument(name) == u"http://openid.net/srv/ax/1.0": + ax_ns = name[10:] + break + def get_ax_arg(uri): + if not ax_ns: return u"" + prefix = "openid." + ax_ns + ".type." + ax_name = None + for name in self.request.arguments.iterkeys(): + if self.get_argument(name) == uri and name.startswith(prefix): + part = name[len(prefix):] + ax_name = "openid." + ax_ns + ".value." + part + break + if not ax_name: return u"" + return self.get_argument(ax_name, u"") + + email = get_ax_arg("http://axschema.org/contact/email") + name = get_ax_arg("http://axschema.org/namePerson") + first_name = get_ax_arg("http://axschema.org/namePerson/first") + last_name = get_ax_arg("http://axschema.org/namePerson/last") + username = get_ax_arg("http://axschema.org/namePerson/friendly") + locale = get_ax_arg("http://axschema.org/pref/language").lower() + user = dict() + name_parts = [] + if first_name: + user["first_name"] = first_name + name_parts.append(first_name) + if last_name: + user["last_name"] = last_name + name_parts.append(last_name) + if name: + user["name"] = name + elif name_parts: + user["name"] = u" ".join(name_parts) + elif email: + user["name"] = email.split("@")[0] + if email: user["email"] = email + if locale: user["locale"] = locale + if username: user["username"] = username + callback(user) + + +class OAuthMixin(object): + """Abstract implementation of OAuth. + + See TwitterMixin and FriendFeedMixin below for example implementations. + """ + + def authorize_redirect(self, callback_uri=None, extra_params=None, + http_client=None): + """Redirects the user to obtain OAuth authorization for this service. + + Twitter and FriendFeed both require that you register a Callback + URL with your application. You should call this method to log the + user in, and then call get_authenticated_user() in the handler + you registered as your Callback URL to complete the authorization + process. + + This method sets a cookie called _oauth_request_token which is + subsequently used (and cleared) in get_authenticated_user for + security purposes. + """ + if callback_uri and getattr(self, "_OAUTH_NO_CALLBACKS", False): + raise Exception("This service does not support oauth_callback") + if http_client is None: + http_client = httpclient.AsyncHTTPClient() + if getattr(self, "_OAUTH_VERSION", "1.0a") == "1.0a": + http_client.fetch( + self._oauth_request_token_url(callback_uri=callback_uri, + extra_params=extra_params), + self.async_callback( + self._on_request_token, + self._OAUTH_AUTHORIZE_URL, + callback_uri)) + else: + http_client.fetch( + self._oauth_request_token_url(), + self.async_callback( + self._on_request_token, self._OAUTH_AUTHORIZE_URL, + callback_uri)) + + + def get_authenticated_user(self, callback, http_client=None): + """Gets the OAuth authorized user and access token on callback. + + This method should be called from the handler for your registered + OAuth Callback URL to complete the registration process. We call + callback with the authenticated user, which in addition to standard + attributes like 'name' includes the 'access_key' attribute, which + contains the OAuth access you can use to make authorized requests + to this service on behalf of the user. + + """ + request_key = escape.utf8(self.get_argument("oauth_token")) + oauth_verifier = self.get_argument("oauth_verifier", None) + request_cookie = self.get_cookie("_oauth_request_token") + if not request_cookie: + logging.warning("Missing OAuth request token cookie") + callback(None) + return + self.clear_cookie("_oauth_request_token") + cookie_key, cookie_secret = [base64.b64decode(escape.utf8(i)) for i in request_cookie.split("|")] + if cookie_key != request_key: + logging.info((cookie_key, request_key, request_cookie)) + logging.warning("Request token does not match cookie") + callback(None) + return + token = dict(key=cookie_key, secret=cookie_secret) + if oauth_verifier: + token["verifier"] = oauth_verifier + if http_client is None: + http_client = httpclient.AsyncHTTPClient() + http_client.fetch(self._oauth_access_token_url(token), + self.async_callback(self._on_access_token, callback)) + + def _oauth_request_token_url(self, callback_uri= None, extra_params=None): + consumer_token = self._oauth_consumer_token() + url = self._OAUTH_REQUEST_TOKEN_URL + args = dict( + oauth_consumer_key=consumer_token["key"], + oauth_signature_method="HMAC-SHA1", + oauth_timestamp=str(int(time.time())), + oauth_nonce=binascii.b2a_hex(uuid.uuid4().bytes), + oauth_version=getattr(self, "_OAUTH_VERSION", "1.0a"), + ) + if getattr(self, "_OAUTH_VERSION", "1.0a") == "1.0a": + if callback_uri: + args["oauth_callback"] = urlparse.urljoin( + self.request.full_url(), callback_uri) + if extra_params: args.update(extra_params) + signature = _oauth10a_signature(consumer_token, "GET", url, args) + else: + signature = _oauth_signature(consumer_token, "GET", url, args) + + args["oauth_signature"] = signature + return url + "?" + urllib.urlencode(args) + + def _on_request_token(self, authorize_url, callback_uri, response): + if response.error: + raise Exception("Could not get request token") + request_token = _oauth_parse_response(response.body) + data = (base64.b64encode(request_token["key"]) + b("|") + + base64.b64encode(request_token["secret"])) + self.set_cookie("_oauth_request_token", data) + args = dict(oauth_token=request_token["key"]) + if callback_uri: + args["oauth_callback"] = urlparse.urljoin( + self.request.full_url(), callback_uri) + self.redirect(authorize_url + "?" + urllib.urlencode(args)) + + def _oauth_access_token_url(self, request_token): + consumer_token = self._oauth_consumer_token() + url = self._OAUTH_ACCESS_TOKEN_URL + args = dict( + oauth_consumer_key=consumer_token["key"], + oauth_token=request_token["key"], + oauth_signature_method="HMAC-SHA1", + oauth_timestamp=str(int(time.time())), + oauth_nonce=binascii.b2a_hex(uuid.uuid4().bytes), + oauth_version=getattr(self, "_OAUTH_VERSION", "1.0a"), + ) + if "verifier" in request_token: + args["oauth_verifier"]=request_token["verifier"] + + if getattr(self, "_OAUTH_VERSION", "1.0a") == "1.0a": + signature = _oauth10a_signature(consumer_token, "GET", url, args, + request_token) + else: + signature = _oauth_signature(consumer_token, "GET", url, args, + request_token) + + args["oauth_signature"] = signature + return url + "?" + urllib.urlencode(args) + + def _on_access_token(self, callback, response): + if response.error: + logging.warning("Could not fetch access token") + callback(None) + return + + access_token = _oauth_parse_response(response.body) + self._oauth_get_user(access_token, self.async_callback( + self._on_oauth_get_user, access_token, callback)) + + def _oauth_get_user(self, access_token, callback): + raise NotImplementedError() + + def _on_oauth_get_user(self, access_token, callback, user): + if not user: + callback(None) + return + user["access_token"] = access_token + callback(user) + + def _oauth_request_parameters(self, url, access_token, parameters={}, + method="GET"): + """Returns the OAuth parameters as a dict for the given request. + + parameters should include all POST arguments and query string arguments + that will be sent with the request. + """ + consumer_token = self._oauth_consumer_token() + base_args = dict( + oauth_consumer_key=consumer_token["key"], + oauth_token=access_token["key"], + oauth_signature_method="HMAC-SHA1", + oauth_timestamp=str(int(time.time())), + oauth_nonce=binascii.b2a_hex(uuid.uuid4().bytes), + oauth_version=getattr(self, "_OAUTH_VERSION", "1.0a"), + ) + args = {} + args.update(base_args) + args.update(parameters) + if getattr(self, "_OAUTH_VERSION", "1.0a") == "1.0a": + signature = _oauth10a_signature(consumer_token, method, url, args, + access_token) + else: + signature = _oauth_signature(consumer_token, method, url, args, + access_token) + base_args["oauth_signature"] = signature + return base_args + +class OAuth2Mixin(object): + """Abstract implementation of OAuth v 2.""" + + def authorize_redirect(self, redirect_uri=None, client_id=None, + client_secret=None, extra_params=None ): + """Redirects the user to obtain OAuth authorization for this service. + + Some providers require that you register a Callback + URL with your application. You should call this method to log the + user in, and then call get_authenticated_user() in the handler + you registered as your Callback URL to complete the authorization + process. + """ + args = { + "redirect_uri": redirect_uri, + "client_id": client_id + } + if extra_params: args.update(extra_params) + self.redirect( + url_concat(self._OAUTH_AUTHORIZE_URL, args)) + + def _oauth_request_token_url(self, redirect_uri= None, client_id = None, + client_secret=None, code=None, + extra_params=None): + url = self._OAUTH_ACCESS_TOKEN_URL + args = dict( + redirect_uri=redirect_uri, + code=code, + client_id=client_id, + client_secret=client_secret, + ) + if extra_params: args.update(extra_params) + return url_concat(url, args) + +class TwitterMixin(OAuthMixin): + """Twitter OAuth authentication. + + To authenticate with Twitter, register your application with + Twitter at http://twitter.com/apps. Then copy your Consumer Key and + Consumer Secret to the application settings 'twitter_consumer_key' and + 'twitter_consumer_secret'. Use this Mixin on the handler for the URL + you registered as your application's Callback URL. + + When your application is set up, you can use this Mixin like this + to authenticate the user with Twitter and get access to their stream:: + + class TwitterHandler(tornado.web.RequestHandler, + tornado.auth.TwitterMixin): + @tornado.web.asynchronous + def get(self): + if self.get_argument("oauth_token", None): + self.get_authenticated_user(self.async_callback(self._on_auth)) + return + self.authorize_redirect() + + def _on_auth(self, user): + if not user: + raise tornado.web.HTTPError(500, "Twitter auth failed") + # Save the user using, e.g., set_secure_cookie() + + The user object returned by get_authenticated_user() includes the + attributes 'username', 'name', and all of the custom Twitter user + attributes describe at + http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-users%C2%A0show + in addition to 'access_token'. You should save the access token with + the user; it is required to make requests on behalf of the user later + with twitter_request(). + """ + _OAUTH_REQUEST_TOKEN_URL = "http://api.twitter.com/oauth/request_token" + _OAUTH_ACCESS_TOKEN_URL = "http://api.twitter.com/oauth/access_token" + _OAUTH_AUTHORIZE_URL = "http://api.twitter.com/oauth/authorize" + _OAUTH_AUTHENTICATE_URL = "http://api.twitter.com/oauth/authenticate" + _OAUTH_NO_CALLBACKS = False + + + def authenticate_redirect(self): + """Just like authorize_redirect(), but auto-redirects if authorized. + + This is generally the right interface to use if you are using + Twitter for single-sign on. + """ + http = httpclient.AsyncHTTPClient() + http.fetch(self._oauth_request_token_url(), self.async_callback( + self._on_request_token, self._OAUTH_AUTHENTICATE_URL, None)) + + def twitter_request(self, path, callback, access_token=None, + post_args=None, **args): + """Fetches the given API path, e.g., "/statuses/user_timeline/btaylor" + + The path should not include the format (we automatically append + ".json" and parse the JSON output). + + If the request is a POST, post_args should be provided. Query + string arguments should be given as keyword arguments. + + All the Twitter methods are documented at + http://apiwiki.twitter.com/Twitter-API-Documentation. + + Many methods require an OAuth access token which you can obtain + through authorize_redirect() and get_authenticated_user(). The + user returned through that process includes an 'access_token' + attribute that can be used to make authenticated requests via + this method. Example usage:: + + class MainHandler(tornado.web.RequestHandler, + tornado.auth.TwitterMixin): + @tornado.web.authenticated + @tornado.web.asynchronous + def get(self): + self.twitter_request( + "/statuses/update", + post_args={"status": "Testing Tornado Web Server"}, + access_token=user["access_token"], + callback=self.async_callback(self._on_post)) + + def _on_post(self, new_entry): + if not new_entry: + # Call failed; perhaps missing permission? + self.authorize_redirect() + return + self.finish("Posted a message!") + + """ + # Add the OAuth resource request signature if we have credentials + url = "http://api.twitter.com/1" + path + ".json" + if access_token: + all_args = {} + all_args.update(args) + all_args.update(post_args or {}) + method = "POST" if post_args is not None else "GET" + oauth = self._oauth_request_parameters( + url, access_token, all_args, method=method) + args.update(oauth) + if args: url += "?" + urllib.urlencode(args) + callback = self.async_callback(self._on_twitter_request, callback) + http = httpclient.AsyncHTTPClient() + if post_args is not None: + http.fetch(url, method="POST", body=urllib.urlencode(post_args), + callback=callback) + else: + http.fetch(url, callback=callback) + + def _on_twitter_request(self, callback, response): + if response.error: + logging.warning("Error response %s fetching %s", response.error, + response.request.url) + callback(None) + return + callback(escape.json_decode(response.body)) + + def _oauth_consumer_token(self): + self.require_setting("twitter_consumer_key", "Twitter OAuth") + self.require_setting("twitter_consumer_secret", "Twitter OAuth") + return dict( + key=self.settings["twitter_consumer_key"], + secret=self.settings["twitter_consumer_secret"]) + + def _oauth_get_user(self, access_token, callback): + callback = self.async_callback(self._parse_user_response, callback) + self.twitter_request( + "/users/show/" + access_token["screen_name"], + access_token=access_token, callback=callback) + + def _parse_user_response(self, callback, user): + if user: + user["username"] = user["screen_name"] + callback(user) + + +class FriendFeedMixin(OAuthMixin): + """FriendFeed OAuth authentication. + + To authenticate with FriendFeed, register your application with + FriendFeed at http://friendfeed.com/api/applications. Then + copy your Consumer Key and Consumer Secret to the application settings + 'friendfeed_consumer_key' and 'friendfeed_consumer_secret'. Use + this Mixin on the handler for the URL you registered as your + application's Callback URL. + + When your application is set up, you can use this Mixin like this + to authenticate the user with FriendFeed and get access to their feed:: + + class FriendFeedHandler(tornado.web.RequestHandler, + tornado.auth.FriendFeedMixin): + @tornado.web.asynchronous + def get(self): + if self.get_argument("oauth_token", None): + self.get_authenticated_user(self.async_callback(self._on_auth)) + return + self.authorize_redirect() + + def _on_auth(self, user): + if not user: + raise tornado.web.HTTPError(500, "FriendFeed auth failed") + # Save the user using, e.g., set_secure_cookie() + + The user object returned by get_authenticated_user() includes the + attributes 'username', 'name', and 'description' in addition to + 'access_token'. You should save the access token with the user; + it is required to make requests on behalf of the user later with + friendfeed_request(). + """ + _OAUTH_VERSION = "1.0" + _OAUTH_REQUEST_TOKEN_URL = "https://friendfeed.com/account/oauth/request_token" + _OAUTH_ACCESS_TOKEN_URL = "https://friendfeed.com/account/oauth/access_token" + _OAUTH_AUTHORIZE_URL = "https://friendfeed.com/account/oauth/authorize" + _OAUTH_NO_CALLBACKS = True + _OAUTH_VERSION = "1.0" + + + def friendfeed_request(self, path, callback, access_token=None, + post_args=None, **args): + """Fetches the given relative API path, e.g., "/bret/friends" + + If the request is a POST, post_args should be provided. Query + string arguments should be given as keyword arguments. + + All the FriendFeed methods are documented at + http://friendfeed.com/api/documentation. + + Many methods require an OAuth access token which you can obtain + through authorize_redirect() and get_authenticated_user(). The + user returned through that process includes an 'access_token' + attribute that can be used to make authenticated requests via + this method. Example usage:: + + class MainHandler(tornado.web.RequestHandler, + tornado.auth.FriendFeedMixin): + @tornado.web.authenticated + @tornado.web.asynchronous + def get(self): + self.friendfeed_request( + "/entry", + post_args={"body": "Testing Tornado Web Server"}, + access_token=self.current_user["access_token"], + callback=self.async_callback(self._on_post)) + + def _on_post(self, new_entry): + if not new_entry: + # Call failed; perhaps missing permission? + self.authorize_redirect() + return + self.finish("Posted a message!") + + """ + # Add the OAuth resource request signature if we have credentials + url = "http://friendfeed-api.com/v2" + path + if access_token: + all_args = {} + all_args.update(args) + all_args.update(post_args or {}) + method = "POST" if post_args is not None else "GET" + oauth = self._oauth_request_parameters( + url, access_token, all_args, method=method) + args.update(oauth) + if args: url += "?" + urllib.urlencode(args) + callback = self.async_callback(self._on_friendfeed_request, callback) + http = httpclient.AsyncHTTPClient() + if post_args is not None: + http.fetch(url, method="POST", body=urllib.urlencode(post_args), + callback=callback) + else: + http.fetch(url, callback=callback) + + def _on_friendfeed_request(self, callback, response): + if response.error: + logging.warning("Error response %s fetching %s", response.error, + response.request.url) + callback(None) + return + callback(escape.json_decode(response.body)) + + def _oauth_consumer_token(self): + self.require_setting("friendfeed_consumer_key", "FriendFeed OAuth") + self.require_setting("friendfeed_consumer_secret", "FriendFeed OAuth") + return dict( + key=self.settings["friendfeed_consumer_key"], + secret=self.settings["friendfeed_consumer_secret"]) + + def _oauth_get_user(self, access_token, callback): + callback = self.async_callback(self._parse_user_response, callback) + self.friendfeed_request( + "/feedinfo/" + access_token["username"], + include="id,name,description", access_token=access_token, + callback=callback) + + def _parse_user_response(self, callback, user): + if user: + user["username"] = user["id"] + callback(user) + + +class GoogleMixin(OpenIdMixin, OAuthMixin): + """Google Open ID / OAuth authentication. + + No application registration is necessary to use Google for authentication + or to access Google resources on behalf of a user. To authenticate with + Google, redirect with authenticate_redirect(). On return, parse the + response with get_authenticated_user(). We send a dict containing the + values for the user, including 'email', 'name', and 'locale'. + Example usage:: + + class GoogleHandler(tornado.web.RequestHandler, tornado.auth.GoogleMixin): + @tornado.web.asynchronous + def get(self): + if self.get_argument("openid.mode", None): + self.get_authenticated_user(self.async_callback(self._on_auth)) + return + self.authenticate_redirect() + + def _on_auth(self, user): + if not user: + raise tornado.web.HTTPError(500, "Google auth failed") + # Save the user with, e.g., set_secure_cookie() + + """ + _OPENID_ENDPOINT = "https://www.google.com/accounts/o8/ud" + _OAUTH_ACCESS_TOKEN_URL = "https://www.google.com/accounts/OAuthGetAccessToken" + + def authorize_redirect(self, oauth_scope, callback_uri=None, + ax_attrs=["name","email","language","username"]): + """Authenticates and authorizes for the given Google resource. + + Some of the available resources are: + + * Gmail Contacts - http://www.google.com/m8/feeds/ + * Calendar - http://www.google.com/calendar/feeds/ + * Finance - http://finance.google.com/finance/feeds/ + + You can authorize multiple resources by separating the resource + URLs with a space. + """ + callback_uri = callback_uri or self.request.uri + args = self._openid_args(callback_uri, ax_attrs=ax_attrs, + oauth_scope=oauth_scope) + self.redirect(self._OPENID_ENDPOINT + "?" + urllib.urlencode(args)) + + def get_authenticated_user(self, callback): + """Fetches the authenticated user data upon redirect.""" + # Look to see if we are doing combined OpenID/OAuth + oauth_ns = "" + for name, values in self.request.arguments.iteritems(): + if name.startswith("openid.ns.") and \ + values[-1] == u"http://specs.openid.net/extensions/oauth/1.0": + oauth_ns = name[10:] + break + token = self.get_argument("openid." + oauth_ns + ".request_token", "") + if token: + http = httpclient.AsyncHTTPClient() + token = dict(key=token, secret="") + http.fetch(self._oauth_access_token_url(token), + self.async_callback(self._on_access_token, callback)) + else: + OpenIdMixin.get_authenticated_user(self, callback) + + def _oauth_consumer_token(self): + self.require_setting("google_consumer_key", "Google OAuth") + self.require_setting("google_consumer_secret", "Google OAuth") + return dict( + key=self.settings["google_consumer_key"], + secret=self.settings["google_consumer_secret"]) + + def _oauth_get_user(self, access_token, callback): + OpenIdMixin.get_authenticated_user(self, callback) + +class FacebookMixin(object): + """Facebook Connect authentication. + + New applications should consider using `FacebookGraphMixin` below instead + of this class. + + To authenticate with Facebook, register your application with + Facebook at http://www.facebook.com/developers/apps.php. Then + copy your API Key and Application Secret to the application settings + 'facebook_api_key' and 'facebook_secret'. + + When your application is set up, you can use this Mixin like this + to authenticate the user with Facebook:: + + class FacebookHandler(tornado.web.RequestHandler, + tornado.auth.FacebookMixin): + @tornado.web.asynchronous + def get(self): + if self.get_argument("session", None): + self.get_authenticated_user(self.async_callback(self._on_auth)) + return + self.authenticate_redirect() + + def _on_auth(self, user): + if not user: + raise tornado.web.HTTPError(500, "Facebook auth failed") + # Save the user using, e.g., set_secure_cookie() + + The user object returned by get_authenticated_user() includes the + attributes 'facebook_uid' and 'name' in addition to session attributes + like 'session_key'. You should save the session key with the user; it is + required to make requests on behalf of the user later with + facebook_request(). + """ + def authenticate_redirect(self, callback_uri=None, cancel_uri=None, + extended_permissions=None): + """Authenticates/installs this app for the current user.""" + self.require_setting("facebook_api_key", "Facebook Connect") + callback_uri = callback_uri or self.request.uri + args = { + "api_key": self.settings["facebook_api_key"], + "v": "1.0", + "fbconnect": "true", + "display": "page", + "next": urlparse.urljoin(self.request.full_url(), callback_uri), + "return_session": "true", + } + if cancel_uri: + args["cancel_url"] = urlparse.urljoin( + self.request.full_url(), cancel_uri) + if extended_permissions: + if isinstance(extended_permissions, (unicode, bytes_type)): + extended_permissions = [extended_permissions] + args["req_perms"] = ",".join(extended_permissions) + self.redirect("http://www.facebook.com/login.php?" + + urllib.urlencode(args)) + + def authorize_redirect(self, extended_permissions, callback_uri=None, + cancel_uri=None): + """Redirects to an authorization request for the given FB resource. + + The available resource names are listed at + http://wiki.developers.facebook.com/index.php/Extended_permission. + The most common resource types include: + + * publish_stream + * read_stream + * email + * sms + + extended_permissions can be a single permission name or a list of + names. To get the session secret and session key, call + get_authenticated_user() just as you would with + authenticate_redirect(). + """ + self.authenticate_redirect(callback_uri, cancel_uri, + extended_permissions) + + def get_authenticated_user(self, callback): + """Fetches the authenticated Facebook user. + + The authenticated user includes the special Facebook attributes + 'session_key' and 'facebook_uid' in addition to the standard + user attributes like 'name'. + """ + self.require_setting("facebook_api_key", "Facebook Connect") + session = escape.json_decode(self.get_argument("session")) + self.facebook_request( + method="facebook.users.getInfo", + callback=self.async_callback( + self._on_get_user_info, callback, session), + session_key=session["session_key"], + uids=session["uid"], + fields="uid,first_name,last_name,name,locale,pic_square," \ + "profile_url,username") + + def facebook_request(self, method, callback, **args): + """Makes a Facebook API REST request. + + We automatically include the Facebook API key and signature, but + it is the callers responsibility to include 'session_key' and any + other required arguments to the method. + + The available Facebook methods are documented here: + http://wiki.developers.facebook.com/index.php/API + + Here is an example for the stream.get() method:: + + class MainHandler(tornado.web.RequestHandler, + tornado.auth.FacebookMixin): + @tornado.web.authenticated + @tornado.web.asynchronous + def get(self): + self.facebook_request( + method="stream.get", + callback=self.async_callback(self._on_stream), + session_key=self.current_user["session_key"]) + + def _on_stream(self, stream): + if stream is None: + # Not authorized to read the stream yet? + self.redirect(self.authorize_redirect("read_stream")) + return + self.render("stream.html", stream=stream) + + """ + self.require_setting("facebook_api_key", "Facebook Connect") + self.require_setting("facebook_secret", "Facebook Connect") + if not method.startswith("facebook."): + method = "facebook." + method + args["api_key"] = self.settings["facebook_api_key"] + args["v"] = "1.0" + args["method"] = method + args["call_id"] = str(long(time.time() * 1e6)) + args["format"] = "json" + args["sig"] = self._signature(args) + url = "http://api.facebook.com/restserver.php?" + \ + urllib.urlencode(args) + http = httpclient.AsyncHTTPClient() + http.fetch(url, callback=self.async_callback( + self._parse_response, callback)) + + def _on_get_user_info(self, callback, session, users): + if users is None: + callback(None) + return + callback({ + "name": users[0]["name"], + "first_name": users[0]["first_name"], + "last_name": users[0]["last_name"], + "uid": users[0]["uid"], + "locale": users[0]["locale"], + "pic_square": users[0]["pic_square"], + "profile_url": users[0]["profile_url"], + "username": users[0].get("username"), + "session_key": session["session_key"], + "session_expires": session.get("expires"), + }) + + def _parse_response(self, callback, response): + if response.error: + logging.warning("HTTP error from Facebook: %s", response.error) + callback(None) + return + try: + json = escape.json_decode(response.body) + except Exception: + logging.warning("Invalid JSON from Facebook: %r", response.body) + callback(None) + return + if isinstance(json, dict) and json.get("error_code"): + logging.warning("Facebook error: %d: %r", json["error_code"], + json.get("error_msg")) + callback(None) + return + callback(json) + + def _signature(self, args): + parts = ["%s=%s" % (n, args[n]) for n in sorted(args.keys())] + body = "".join(parts) + self.settings["facebook_secret"] + if isinstance(body, unicode): body = body.encode("utf-8") + return hashlib.md5(body).hexdigest() + +class FacebookGraphMixin(OAuth2Mixin): + """Facebook authentication using the new Graph API and OAuth2.""" + _OAUTH_ACCESS_TOKEN_URL = "https://graph.facebook.com/oauth/access_token?" + _OAUTH_AUTHORIZE_URL = "https://graph.facebook.com/oauth/authorize?" + _OAUTH_NO_CALLBACKS = False + + def get_authenticated_user(self, redirect_uri, client_id, client_secret, + code, callback, extra_fields=None): + """Handles the login for the Facebook user, returning a user object. + + Example usage:: + + class FacebookGraphLoginHandler(LoginHandler, tornado.auth.FacebookGraphMixin): + @tornado.web.asynchronous + def get(self): + if self.get_argument("code", False): + self.get_authenticated_user( + redirect_uri='/auth/facebookgraph/', + client_id=self.settings["facebook_api_key"], + client_secret=self.settings["facebook_secret"], + code=self.get_argument("code"), + callback=self.async_callback( + self._on_login)) + return + self.authorize_redirect(redirect_uri='/auth/facebookgraph/', + client_id=self.settings["facebook_api_key"], + extra_params={"scope": "read_stream,offline_access"}) + + def _on_login(self, user): + logging.error(user) + self.finish() + + """ + http = httpclient.AsyncHTTPClient() + args = { + "redirect_uri": redirect_uri, + "code": code, + "client_id": client_id, + "client_secret": client_secret, + } + + fields = set(['id', 'name', 'first_name', 'last_name', + 'locale', 'picture', 'link']) + if extra_fields: fields.update(extra_fields) + + http.fetch(self._oauth_request_token_url(**args), + self.async_callback(self._on_access_token, redirect_uri, client_id, + client_secret, callback, fields)) + + def _on_access_token(self, redirect_uri, client_id, client_secret, + callback, fields, response): + if response.error: + logging.warning('Facebook auth error: %s' % str(response)) + callback(None) + return + + args = escape.parse_qs_bytes(escape.native_str(response.body)) + session = { + "access_token": args["access_token"][-1], + "expires": args.get("expires") + } + + self.facebook_request( + path="/me", + callback=self.async_callback( + self._on_get_user_info, callback, session, fields), + access_token=session["access_token"], + fields=",".join(fields) + ) + + + def _on_get_user_info(self, callback, session, fields, user): + if user is None: + callback(None) + return + + fieldmap = {} + for field in fields: + fieldmap[field] = user.get(field) + + fieldmap.update({"access_token": session["access_token"], "session_expires": session.get("expires")}) + callback(fieldmap) + + def facebook_request(self, path, callback, access_token=None, + post_args=None, **args): + """Fetches the given relative API path, e.g., "/btaylor/picture" + + If the request is a POST, post_args should be provided. Query + string arguments should be given as keyword arguments. + + An introduction to the Facebook Graph API can be found at + http://developers.facebook.com/docs/api + + Many methods require an OAuth access token which you can obtain + through authorize_redirect() and get_authenticated_user(). The + user returned through that process includes an 'access_token' + attribute that can be used to make authenticated requests via + this method. Example usage:: + + class MainHandler(tornado.web.RequestHandler, + tornado.auth.FacebookGraphMixin): + @tornado.web.authenticated + @tornado.web.asynchronous + def get(self): + self.facebook_request( + "/me/feed", + post_args={"message": "I am posting from my Tornado application!"}, + access_token=self.current_user["access_token"], + callback=self.async_callback(self._on_post)) + + def _on_post(self, new_entry): + if not new_entry: + # Call failed; perhaps missing permission? + self.authorize_redirect() + return + self.finish("Posted a message!") + + """ + url = "https://graph.facebook.com" + path + all_args = {} + if access_token: + all_args["access_token"] = access_token + all_args.update(args) + all_args.update(post_args or {}) + if all_args: url += "?" + urllib.urlencode(all_args) + callback = self.async_callback(self._on_facebook_request, callback) + http = httpclient.AsyncHTTPClient() + if post_args is not None: + http.fetch(url, method="POST", body=urllib.urlencode(post_args), + callback=callback) + else: + http.fetch(url, callback=callback) + + def _on_facebook_request(self, callback, response): + if response.error: + logging.warning("Error response %s fetching %s", response.error, + response.request.url) + callback(None) + return + callback(escape.json_decode(response.body)) + +def _oauth_signature(consumer_token, method, url, parameters={}, token=None): + """Calculates the HMAC-SHA1 OAuth signature for the given request. + + See http://oauth.net/core/1.0/#signing_process + """ + parts = urlparse.urlparse(url) + scheme, netloc, path = parts[:3] + normalized_url = scheme.lower() + "://" + netloc.lower() + path + + base_elems = [] + base_elems.append(method.upper()) + base_elems.append(normalized_url) + base_elems.append("&".join("%s=%s" % (k, _oauth_escape(str(v))) + for k, v in sorted(parameters.items()))) + base_string = "&".join(_oauth_escape(e) for e in base_elems) + + key_elems = [escape.utf8(consumer_token["secret"])] + key_elems.append(escape.utf8(token["secret"] if token else "")) + key = b("&").join(key_elems) + + hash = hmac.new(key, escape.utf8(base_string), hashlib.sha1) + return binascii.b2a_base64(hash.digest())[:-1] + +def _oauth10a_signature(consumer_token, method, url, parameters={}, token=None): + """Calculates the HMAC-SHA1 OAuth 1.0a signature for the given request. + + See http://oauth.net/core/1.0a/#signing_process + """ + parts = urlparse.urlparse(url) + scheme, netloc, path = parts[:3] + normalized_url = scheme.lower() + "://" + netloc.lower() + path + + base_elems = [] + base_elems.append(method.upper()) + base_elems.append(normalized_url) + base_elems.append("&".join("%s=%s" % (k, _oauth_escape(str(v))) + for k, v in sorted(parameters.items()))) + + base_string = "&".join(_oauth_escape(e) for e in base_elems) + key_elems = [escape.utf8(urllib.quote(consumer_token["secret"], safe='~'))] + key_elems.append(escape.utf8(urllib.quote(token["secret"], safe='~') if token else "")) + key = b("&").join(key_elems) + + hash = hmac.new(key, escape.utf8(base_string), hashlib.sha1) + return binascii.b2a_base64(hash.digest())[:-1] + +def _oauth_escape(val): + if isinstance(val, unicode): + val = val.encode("utf-8") + return urllib.quote(val, safe="~") + + +def _oauth_parse_response(body): + p = escape.parse_qs(body, keep_blank_values=False) + token = dict(key=p[b("oauth_token")][0], secret=p[b("oauth_token_secret")][0]) + + # Add the extra parameters the Provider included to the token + special = (b("oauth_token"), b("oauth_token_secret")) + token.update((k, p[k][0]) for k in p if k not in special) + return token + + diff --git a/interactive-mining-madoap/madoap/src/tornado/autoreload.py b/interactive-mining-madoap/madoap/src/tornado/autoreload.py new file mode 100644 index 0000000..7e3a3d7 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/autoreload.py @@ -0,0 +1,250 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""A module to automatically restart the server when a module is modified. + +Most applications should not call this module directly. Instead, pass the +keyword argument ``debug=True`` to the `tornado.web.Application` constructor. +This will enable autoreload mode as well as checking for changes to templates +and static resources. + +This module depends on IOLoop, so it will not work in WSGI applications +and Google AppEngine. It also will not work correctly when HTTPServer's +multi-process mode is used. +""" + +from __future__ import with_statement + +import functools +import logging +import os +import pkgutil +import sys +import types +import subprocess + +from tornado import ioloop +from tornado import process + +try: + import signal +except ImportError: + signal = None + +def start(io_loop=None, check_time=500): + """Restarts the process automatically when a module is modified. + + We run on the I/O loop, and restarting is a destructive operation, + so will terminate any pending requests. + """ + io_loop = io_loop or ioloop.IOLoop.instance() + add_reload_hook(functools.partial(_close_all_fds, io_loop)) + modify_times = {} + callback = functools.partial(_reload_on_update, modify_times) + scheduler = ioloop.PeriodicCallback(callback, check_time, io_loop=io_loop) + scheduler.start() + +def wait(): + """Wait for a watched file to change, then restart the process. + + Intended to be used at the end of scripts like unit test runners, + to run the tests again after any source file changes (but see also + the command-line interface in `main`) + """ + io_loop = ioloop.IOLoop() + start(io_loop) + io_loop.start() + +_watched_files = set() + +def watch(filename): + """Add a file to the watch list. + + All imported modules are watched by default. + """ + _watched_files.add(filename) + +_reload_hooks = [] + +def add_reload_hook(fn): + """Add a function to be called before reloading the process. + + Note that for open file and socket handles it is generally + preferable to set the ``FD_CLOEXEC`` flag (using `fcntl` or + `tornado.platform.auto.set_close_exec`) instead of using a reload + hook to close them. + """ + _reload_hooks.append(fn) + +def _close_all_fds(io_loop): + for fd in io_loop._handlers.keys(): + try: + os.close(fd) + except Exception: + pass + +_reload_attempted = False + +def _reload_on_update(modify_times): + if _reload_attempted: + # We already tried to reload and it didn't work, so don't try again. + return + if process.task_id() is not None: + # We're in a child process created by fork_processes. If child + # processes restarted themselves, they'd all restart and then + # all call fork_processes again. + return + for module in sys.modules.values(): + # Some modules play games with sys.modules (e.g. email/__init__.py + # in the standard library), and occasionally this can cause strange + # failures in getattr. Just ignore anything that's not an ordinary + # module. + if not isinstance(module, types.ModuleType): continue + path = getattr(module, "__file__", None) + if not path: continue + if path.endswith(".pyc") or path.endswith(".pyo"): + path = path[:-1] + _check_file(modify_times, path) + for path in _watched_files: + _check_file(modify_times, path) + +def _check_file(modify_times, path): + try: + modified = os.stat(path).st_mtime + except Exception: + return + if path not in modify_times: + modify_times[path] = modified + return + if modify_times[path] != modified: + logging.info("%s modified; restarting server", path) + _reload() + +def _reload(): + global _reload_attempted + _reload_attempted = True + for fn in _reload_hooks: + fn() + if hasattr(signal, "setitimer"): + # Clear the alarm signal set by + # ioloop.set_blocking_log_threshold so it doesn't fire + # after the exec. + signal.setitimer(signal.ITIMER_REAL, 0, 0) + if sys.platform == 'win32': + # os.execv is broken on Windows and can't properly parse command line + # arguments and executable name if they contain whitespaces. subprocess + # fixes that behavior. + subprocess.Popen([sys.executable] + sys.argv) + sys.exit(0) + else: + try: + os.execv(sys.executable, [sys.executable] + sys.argv) + except OSError: + # Mac OS X versions prior to 10.6 do not support execv in + # a process that contains multiple threads. Instead of + # re-executing in the current process, start a new one + # and cause the current process to exit. This isn't + # ideal since the new process is detached from the parent + # terminal and thus cannot easily be killed with ctrl-C, + # but it's better than not being able to autoreload at + # all. + # Unfortunately the errno returned in this case does not + # appear to be consistent, so we can't easily check for + # this error specifically. + os.spawnv(os.P_NOWAIT, sys.executable, + [sys.executable] + sys.argv) + sys.exit(0) + +_USAGE = """\ +Usage: + python -m tornado.autoreload -m module.to.run [args...] + python -m tornado.autoreload path/to/script.py [args...] +""" +def main(): + """Command-line wrapper to re-run a script whenever its source changes. + + Scripts may be specified by filename or module name:: + + python -m tornado.autoreload -m tornado.test.runtests + python -m tornado.autoreload tornado/test/runtests.py + + Running a script with this wrapper is similar to calling + `tornado.autoreload.wait` at the end of the script, but this wrapper + can catch import-time problems like syntax errors that would otherwise + prevent the script from reaching its call to `wait`. + """ + original_argv = sys.argv + sys.argv = sys.argv[:] + if len(sys.argv) >= 3 and sys.argv[1] == "-m": + mode = "module" + module = sys.argv[2] + del sys.argv[1:3] + elif len(sys.argv) >= 2: + mode = "script" + script = sys.argv[1] + sys.argv = sys.argv[1:] + else: + print >>sys.stderr, _USAGE + sys.exit(1) + + try: + if mode == "module": + import runpy + runpy.run_module(module, run_name="__main__", alter_sys=True) + elif mode == "script": + with open(script) as f: + global __file__ + __file__ = script + # Use globals as our "locals" dictionary so that + # something that tries to import __main__ (e.g. the unittest + # module) will see the right things. + exec f.read() in globals(), globals() + except SystemExit, e: + logging.info("Script exited with status %s", e.code) + except Exception, e: + logging.warning("Script exited with uncaught exception", exc_info=True) + if isinstance(e, SyntaxError): + watch(e.filename) + else: + logging.info("Script exited normally") + # restore sys.argv so subsequent executions will include autoreload + sys.argv = original_argv + + if mode == 'module': + # runpy did a fake import of the module as __main__, but now it's + # no longer in sys.modules. Figure out where it is and watch it. + watch(pkgutil.get_loader(module).get_filename()) + + wait() + + +if __name__ == "__main__": + # If this module is run with "python -m tornado.autoreload", the current + # directory is automatically prepended to sys.path, but not if it is + # run as "path/to/tornado/autoreload.py". The processing for "-m" rewrites + # the former to the latter, so subsequent executions won't have the same + # path as the original. Modify os.environ here to ensure that the + # re-executed process will have the same path. + # Conversely, when run as path/to/tornado/autoreload.py, the directory + # containing autoreload.py gets added to the path, but we don't want + # tornado modules importable at top level, so remove it. + path_prefix = '.' + os.pathsep + if (sys.path[0] == '' and + not os.environ.get("PYTHONPATH", "").startswith(path_prefix)): + os.environ["PYTHONPATH"] = path_prefix + os.environ.get("PYTHONPATH", "") + elif sys.path[0] == os.path.dirname(__file__): + del sys.path[0] + main() diff --git a/interactive-mining-madoap/madoap/src/tornado/ca-certificates.crt b/interactive-mining-madoap/madoap/src/tornado/ca-certificates.crt new file mode 100644 index 0000000..26971c8 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/ca-certificates.crt @@ -0,0 +1,3576 @@ +# This file contains certificates of known certificate authorities +# for use with SimpleAsyncHTTPClient. +# +# It was copied from /etc/ssl/certs/ca-certificates.crt +# on a stock install of Ubuntu 11.04 (ca-certificates package +# version 20090814+nmu2ubuntu0.1). This data file is licensed +# under the MPL/GPL. +-----BEGIN CERTIFICATE----- +MIIEuDCCA6CgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBtDELMAkGA1UEBhMCQlIx +EzARBgNVBAoTCklDUC1CcmFzaWwxPTA7BgNVBAsTNEluc3RpdHV0byBOYWNpb25h +bCBkZSBUZWNub2xvZ2lhIGRhIEluZm9ybWFjYW8gLSBJVEkxETAPBgNVBAcTCEJy +YXNpbGlhMQswCQYDVQQIEwJERjExMC8GA1UEAxMoQXV0b3JpZGFkZSBDZXJ0aWZp +Y2Fkb3JhIFJhaXogQnJhc2lsZWlyYTAeFw0wMTExMzAxMjU4MDBaFw0xMTExMzAy +MzU5MDBaMIG0MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE9MDsG +A1UECxM0SW5zdGl0dXRvIE5hY2lvbmFsIGRlIFRlY25vbG9naWEgZGEgSW5mb3Jt +YWNhbyAtIElUSTERMA8GA1UEBxMIQnJhc2lsaWExCzAJBgNVBAgTAkRGMTEwLwYD +VQQDEyhBdXRvcmlkYWRlIENlcnRpZmljYWRvcmEgUmFpeiBCcmFzaWxlaXJhMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwPMudwX/hvm+Uh2b/lQAcHVA +isamaLkWdkwP9/S/tOKIgRrL6Oy+ZIGlOUdd6uYtk9Ma/3pUpgcfNAj0vYm5gsyj +Qo9emsc+x6m4VWwk9iqMZSCK5EQkAq/Ut4n7KuLE1+gdftwdIgxfUsPt4CyNrY50 +QV57KM2UT8x5rrmzEjr7TICGpSUAl2gVqe6xaii+bmYR1QrmWaBSAG59LrkrjrYt +bRhFboUDe1DK+6T8s5L6k8c8okpbHpa9veMztDVC9sPJ60MWXh6anVKo1UcLcbUR +yEeNvZneVRKAAU6ouwdjDvwlsaKydFKwed0ToQ47bmUKgcm+wV3eTRk36UOnTwID +AQABo4HSMIHPME4GA1UdIARHMEUwQwYFYEwBAQAwOjA4BggrBgEFBQcCARYsaHR0 +cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0RQQ2FjcmFpei5wZGYwPQYDVR0f +BDYwNDAyoDCgLoYsaHR0cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0xDUmFj +cmFpei5jcmwwHQYDVR0OBBYEFIr68VeEERM1kEL6V0lUaQ2kxPA3MA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAZA5c1 +U/hgIh6OcgLAfiJgFWpvmDZWqlV30/bHFpj8iBobJSm5uDpt7TirYh1Uxe3fQaGl +YjJe+9zd+izPRbBqXPVQA34EXcwk4qpWuf1hHriWfdrx8AcqSqr6CuQFwSr75Fos +SzlwDADa70mT7wZjAmQhnZx2xJ6wfWlT9VQfS//JYeIc7Fue2JNLd00UOSMMaiK/ +t79enKNHEA2fupH3vEigf5Eh4bVAN5VohrTm6MY53x7XQZZr1ME7a55lFEnSeT0u +mlOAjR2mAbvSM5X5oSZNrmetdzyTj2flCM8CC7MLab0kkdngRIlUBGHF1/S5nmPb +K+9A46sd33oqK8n8 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 +IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB +IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA +Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO +BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi +MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ +ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ +8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6 +zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y +fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7 +w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc +G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k +epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q +laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ +QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU +fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826 +YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w +ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY +gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe +MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0 +IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy +dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw +czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0 +dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl +aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC +AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg +b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB +ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc +nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg +18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c +gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl +Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY +sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T +SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF +CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum +GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk +zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW +omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGCDCCA/CgAwIBAgIBATANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 +IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB +IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA +Y2FjZXJ0Lm9yZzAeFw0wNTEwMTQwNzM2NTVaFw0zMzAzMjgwNzM2NTVaMFQxFDAS +BgNVBAoTC0NBY2VydCBJbmMuMR4wHAYDVQQLExVodHRwOi8vd3d3LkNBY2VydC5v +cmcxHDAaBgNVBAMTE0NBY2VydCBDbGFzcyAzIFJvb3QwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCrSTURSHzSJn5TlM9Dqd0o10Iqi/OHeBlYfA+e2ol9 +4fvrcpANdKGWZKufoCSZc9riVXbHF3v1BKxGuMO+f2SNEGwk82GcwPKQ+lHm9WkB +Y8MPVuJKQs/iRIwlKKjFeQl9RrmK8+nzNCkIReQcn8uUBByBqBSzmGXEQ+xOgo0J +0b2qW42S0OzekMV/CsLj6+YxWl50PpczWejDAz1gM7/30W9HxM3uYoNSbi4ImqTZ +FRiRpoWSR7CuSOtttyHshRpocjWr//AQXcD0lKdq1TuSfkyQBX6TwSyLpI5idBVx +bgtxA+qvFTia1NIFcm+M+SvrWnIl+TlG43IbPgTDZCciECqKT1inA62+tC4T7V2q +SNfVfdQqe1z6RgRQ5MwOQluM7dvyz/yWk+DbETZUYjQ4jwxgmzuXVjit89Jbi6Bb +6k6WuHzX1aCGcEDTkSm3ojyt9Yy7zxqSiuQ0e8DYbF/pCsLDpyCaWt8sXVJcukfV +m+8kKHA4IC/VfynAskEDaJLM4JzMl0tF7zoQCqtwOpiVcK01seqFK6QcgCExqa5g +eoAmSAC4AcCTY1UikTxW56/bOiXzjzFU6iaLgVn5odFTEcV7nQP2dBHgbbEsPyyG +kZlxmqZ3izRg0RS0LKydr4wQ05/EavhvE/xzWfdmQnQeiuP43NJvmJzLR5iVQAX7 +6QIDAQABo4G/MIG8MA8GA1UdEwEB/wQFMAMBAf8wXQYIKwYBBQUHAQEEUTBPMCMG +CCsGAQUFBzABhhdodHRwOi8vb2NzcC5DQWNlcnQub3JnLzAoBggrBgEFBQcwAoYc +aHR0cDovL3d3dy5DQWNlcnQub3JnL2NhLmNydDBKBgNVHSAEQzBBMD8GCCsGAQQB +gZBKMDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93d3cuQ0FjZXJ0Lm9yZy9pbmRleC5w +aHA/aWQ9MTAwDQYJKoZIhvcNAQEEBQADggIBAH8IiKHaGlBJ2on7oQhy84r3HsQ6 +tHlbIDCxRd7CXdNlafHCXVRUPIVfuXtCkcKZ/RtRm6tGpaEQU55tiKxzbiwzpvD0 +nuB1wT6IRanhZkP+VlrRekF490DaSjrxC1uluxYG5sLnk7mFTZdPsR44Q4Dvmw2M +77inYACHV30eRBzLI++bPJmdr7UpHEV5FpZNJ23xHGzDwlVks7wU4vOkHx4y/CcV +Bc/dLq4+gmF78CEQGPZE6lM5+dzQmiDgxrvgu1pPxJnIB721vaLbLmINQjRBvP+L +ivVRIqqIMADisNS8vmW61QNXeZvo3MhN+FDtkaVSKKKs+zZYPumUK5FQhxvWXtaM +zPcPEAxSTtAWYeXlCmy/F8dyRlecmPVsYGN6b165Ti/Iubm7aoW8mA3t+T6XhDSU +rgCvoeXnkm5OvfPi2RSLXNLrAWygF6UtEOucekq9ve7O/e0iQKtwOIj1CodqwqsF +YMlIBdpTwd5Ed2qz8zw87YC8pjhKKSRf/lk7myV6VmMAZLldpGJ9VzZPrYPvH5JT +oI53V93lYRE9IwCQTDz6o2CTBKOvNfYOao9PSmCnhQVsRqGP9Md246FZV/dxssRu +FFxtbUFm3xuTsdQAw+7Lzzw9IYCpX2Nl/N3gX6T0K/CFcUHUZyX7GrGXrtaZghNB +0m6lG5kngOcLqagA +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIESzCCAzOgAwIBAgIJAJigUTEEXRQpMA0GCSqGSIb3DQEBBQUAMHYxCzAJBgNV +BAYTAkRFMQ8wDQYDVQQIEwZIZXNzZW4xDjAMBgNVBAcTBUZ1bGRhMRAwDgYDVQQK +EwdEZWJjb25mMRMwEQYDVQQDEwpEZWJjb25mIENBMR8wHQYJKoZIhvcNAQkBFhBq +b2VyZ0BkZWJpYW4ub3JnMB4XDTA1MTEwNTE3NTUxNFoXDTE1MTEwMzE3NTUxNFow +djELMAkGA1UEBhMCREUxDzANBgNVBAgTBkhlc3NlbjEOMAwGA1UEBxMFRnVsZGEx +EDAOBgNVBAoTB0RlYmNvbmYxEzARBgNVBAMTCkRlYmNvbmYgQ0ExHzAdBgkqhkiG +9w0BCQEWEGpvZXJnQGRlYmlhbi5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCvbOo0SrIwI5IMlsshH8WF3dHB9r9JlSKhMPaybawa1EyvZspMQ3wa +F5qxNf3Sj+NElEmjseEqvCZiIIzqwerHu0Qw62cDYCdCd2+Wb5m0bPYB5CGHiyU1 +eNP0je42O0YeXG2BvUujN8AviocVo39X2YwNQ0ryy4OaqYgm2pRlbtT2ESbF+SfV +Y2iqQj/f8ymF+lHo/pz8tbAqxWcqaSiHFAVQJrdqtFhtoodoNiE3q76zJoUkZTXB +k60Yc3MJSnatZCpnsSBr/D7zpntl0THrUjjtdRWCjQVhqfhM1yZJV+ApbLdheFh0 +ZWlSxdnp25p0q0XYw/7G92ELyFDfBUUNAgMBAAGjgdswgdgwHQYDVR0OBBYEFMuV +dFNb4mCWUFbcP5LOtxFLrEVTMIGoBgNVHSMEgaAwgZ2AFMuVdFNb4mCWUFbcP5LO +txFLrEVToXqkeDB2MQswCQYDVQQGEwJERTEPMA0GA1UECBMGSGVzc2VuMQ4wDAYD +VQQHEwVGdWxkYTEQMA4GA1UEChMHRGViY29uZjETMBEGA1UEAxMKRGViY29uZiBD +QTEfMB0GCSqGSIb3DQEJARYQam9lcmdAZGViaWFuLm9yZ4IJAJigUTEEXRQpMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGZXxHg4mnkvilRIM1EQfGdY +S5b/WcyF2MYSTeTvK4aIB6VHwpZoZCnDGj2m2D3CkHT0upAD9o0zM1tdsfncLzV+ +mDT/jNmBtYo4QXx5vEPwvEIcgrWjwk7SyaEUhZjtolTkHB7ACl0oD0r71St4iEPR +qTUCEXk2E47bg1Fz58wNt/yo2+4iqiRjg1XCH4evkQuhpW+dTZnDyFNqwSYZapOE +TBA+9zBb6xD1KM2DdY7r4GiyYItN0BKLfuWbh9LXGbl1C+f4P11g+m2MPiavIeCe +1iazG5pcS3KoTLACsYlEX24TINtg4kcuS81XdllcnsV3Kdts0nIqPj6uhTTZD0k= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDvjCCA3ygAwIBAgIFJQaThoEwCwYHKoZIzjgEAwUAMIGFMQswCQYDVQQGEwJG +UjEPMA0GA1UECBMGRnJhbmNlMQ4wDAYDVQQHEwVQYXJpczEQMA4GA1UEChMHUE0v +U0dETjEOMAwGA1UECxMFRENTU0kxDjAMBgNVBAMTBUlHQy9BMSMwIQYJKoZIhvcN +AQkBFhRpZ2NhQHNnZG4ucG0uZ291di5mcjAeFw0wMjEyMTMxNDM5MTVaFw0yMDEw +MTcxNDM5MTRaMIGFMQswCQYDVQQGEwJGUjEPMA0GA1UECBMGRnJhbmNlMQ4wDAYD +VQQHEwVQYXJpczEQMA4GA1UEChMHUE0vU0dETjEOMAwGA1UECxMFRENTU0kxDjAM +BgNVBAMTBUlHQy9BMSMwIQYJKoZIhvcNAQkBFhRpZ2NhQHNnZG4ucG0uZ291di5m +cjCCAbYwggErBgcqhkjOOAQBMIIBHgKBgQCFkMImdk9zDzJfTO4XPdAAmLbAdWws +ZiEMZh19RyTo3CyhFqO77OIXrwY6vc1pcc3MgWJ0dgQpAgrDMtmFFxpUu4gmjVsx +8GpxQC+4VOgLY8Cvmcd/UDzYg07EIRto8BwCpPJ/JfUxwzV2V3N713aAX+cEoKZ/ +s+kgxC6nZCA7oQIVALME/JYjkdW2uKIGngsEPbXAjdhDAoGADh/uqWJx94UBm31c +9d8ZTBfRGRnmSSRVFDgPWgA69JD4BR5da8tKz+1HjfMhDXljbMH86ixpD5Ka1Z0V +pRYUPbyAoB37tsmXMJY7kjyD19d5VdaZboUjVvhH6UJy5lpNNNGSvFl4fqkxyvw+ +pq1QV0N5RcvK120hlXdfHUX+YKYDgYQAAoGAQGr7IuKJcYIvJRMjxwl43KxXY2xC +aoCiM/bv117MfI94aNf1UusGhp7CbYAY9CXuL60P0oPMAajbaTE5Z34AuITeHq3Y +CNMHwxalip8BHqSSGmGiQsXeK7T+r1rPXsccZ1c5ikGDZ4xn5gUaCyy2rCmb+fOJ +6VAfCbAbAjmNKwejdzB1MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgFGMBUG +A1UdIAQOMAwwCgYIKoF6AXkBAQEwHQYDVR0OBBYEFPkeNRcUf8idzpKblYbLNxs0 +MQhSMB8GA1UdIwQYMBaAFPkeNRcUf8idzpKblYbLNxs0MQhSMAsGByqGSM44BAMF +AAMvADAsAhRVh+CJA5eVyEYU5AO9Tm7GxX0rmQIUBCqsU5u1WxoZ5lEXicDX5/Ob +sRQ= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYT +AkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQ +TS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG +9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMB4XDTAyMTIxMzE0MjkyM1oXDTIw +MTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAM +BgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEO +MAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2 +LmZyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaI +s9z4iPf930Pfeo2aSVz2TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2 +xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCWSo7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4 +u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYyHF2fYPepraX/z9E0+X1b +F8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNdfrGoRpAx +Vs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGd +PDPQtQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNV +HSAEDjAMMAoGCCqBegF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAx +NjAfBgNVHSMEGDAWgBSjBS8YYFDCiQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUF +AAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RKq89toB9RlPhJy3Q2FLwV3duJ +L92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3QMZsyK10XZZOY +YLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg +Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2a +NjSaTFR+FwNIlQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R +0982gaEbeC9xs/FZTEYYKKuF0mBWWg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIRANAeQJAAAEZSAAAAAQAAAAQwDQYJKoZIhvcNAQEFBQAw +gYkxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJEQzETMBEGA1UEBxMKV2FzaGluZ3Rv +bjEXMBUGA1UEChMOQUJBLkVDT00sIElOQy4xGTAXBgNVBAMTEEFCQS5FQ09NIFJv +b3QgQ0ExJDAiBgkqhkiG9w0BCQEWFWFkbWluQGRpZ3NpZ3RydXN0LmNvbTAeFw05 +OTA3MTIxNzMzNTNaFw0wOTA3MDkxNzMzNTNaMIGJMQswCQYDVQQGEwJVUzELMAkG +A1UECBMCREMxEzARBgNVBAcTCldhc2hpbmd0b24xFzAVBgNVBAoTDkFCQS5FQ09N +LCBJTkMuMRkwFwYDVQQDExBBQkEuRUNPTSBSb290IENBMSQwIgYJKoZIhvcNAQkB +FhVhZG1pbkBkaWdzaWd0cnVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCx0xHgeVVDBwhMywVCAOINg0Y95JO6tgbTDVm9PsHOQ2cBiiGo77zM +0KLMsFWWU4RmBQDaREmA2FQKpSWGlO1jVv9wbKOhGdJ4vmgqRF4vz8wYXke8OrFG +PR7wuSw0X4x8TAgpnUBV6zx9g9618PeKgw6hTLQ6pbNfWiKX7BmbwQVo/ea3qZGU +LOR4SCQaJRk665WcOQqKz0Ky8BzVX/tr7WhWezkscjiw7pOp03t3POtxA6k4ShZs +iSrK2jMTecJVjO2cu/LLWxD4LmE1xilMKtAqY9FlWbT4zfn0AIS2V0KFnTKo+SpU ++/94Qby9cSj0u5C8/5Y0BONFnqFGKECBAgMBAAGjFjAUMBIGA1UdEwEB/wQIMAYB +Af8CAQgwDQYJKoZIhvcNAQEFBQADggEBAARvJYbk5pYntNlCwNDJALF/VD6Hsm0k +qS8Kfv2kRLD4VAe9G52dyntQJHsRW0mjpr8SdNWJt7cvmGQlFLdh6X9ggGvTZOir +vRrWUfrAtF13Gn9kCF55xgVM8XrdTX3O5kh7VNJhkoHWG9YA8A6eKHegTYjHInYZ +w8eeG6Z3ePhfm1bR8PIXrI6dWeYf/le22V7hXZ9F7GFoGUHhsiAm/lowdiT/QHI8 +eZ98IkirRs3bs4Ysj78FQdPB4xTjQRcm0HyncUwZ6EoPclgxfexgeqMiKL0ZJGA/ +O4dzwGvky663qyVDslUte6sGDnVdNOVdc22esnVApVnJTzFxiNmIf1Q= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs +IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 +MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h +bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt +H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 +uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX +mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX +a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN +E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 +WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD +VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 +Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU +cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx +IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN +AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH +YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC +Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX +c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a +mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 +b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw +MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD +VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul +CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n +tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl +dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch +PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC ++Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O +BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl +MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk +ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB +IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X +7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz +43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY +eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl +pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA +WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 +b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx +MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB +ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV +BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV +6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX +GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP +dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH +1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF +62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW +BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL +MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU +cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv +b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6 +IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/ +iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao +GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh +4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm +XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 +b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1 +MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK +EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh +BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq +xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G +87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i +2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U +WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1 +0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G +A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr +pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL +ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm +aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv +hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm +hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X +dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3 +P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y +iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no +xqE= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP +bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2 +MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft +ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lk +hsmj76CGv2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym +1BW32J/X3HGrfpq/m44zDyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsW +OqMFf6Dch9Wc/HKpoH145LcxVR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb +2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQko +O3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAU +AK3Zo/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB +BQUAA4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkF +Zu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAb +LjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTIdGcL+oir +oQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43gKd8hdIaC2y+C +MMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds +sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP +bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2 +MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft +ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC +206B89enfHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFci +KtZHgVdEglZTvYYUAQv8f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2 +JxhP7JsowtS013wMPgwr38oE18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9 +BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7e +Xz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8B +PeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67 +Xnfn6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEq +Z8A9W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZ +o2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3 ++L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124HhnAgMBAAGj +YzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3OpaaEg5+31IqEj +FNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmn +xPBUlgtk87FYT15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2 +LHo1YGwRgJfMqZJS5ivmae2p+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzccc +obGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8 +CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//ZoyzH1kUQ7rVyZ2OuMe +IjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgOZtMA +DjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2F +AjgQ5ANh1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUX +Om/9riW99XJZZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPb +AZO1XB4Y3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQl +Zvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAaw +RY8mkaKO/qk= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCVVMx +HTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNBbWVyaWNh +IE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyOTA2MDAwMFoXDTM3MTEyMDE1 +MDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBT0wgVGltZSBXYXJuZXIg +SW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUgSW5jLjE3MDUGA1UEAxMuQU9M +IFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnej8Mlo2k06AX3dLm/WpcZuS+U +0pPlLYnKhHw/EEMbjIt8hFj4JHxIzyr9wBXZGH6EGhfT257XyuTZ16pYUYfw8ItI +TuLCxFlpMGK2MKKMCxGZYTVtfu/FsRkGIBKOQuHfD5YQUqjPnF+VFNivO3ULMSAf +RC+iYkGzuxgh28pxPIzstrkNn+9R7017EvILDOGsQI93f7DKeHEMXRZxcKLXwjqF +zQ6axOAAsNUl6twr5JQtOJyJQVdkKGUZHLZEtMgxa44Be3ZZJX8VHIQIfHNlIAqh +BC4aMqiaILGcLCFZ5/vP7nAtCMpjPiybkxlqpMKX/7eGV4iFbJ4VFitNLLMCAwEA +AaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoTYwFsuGkABFgFOxj8jY +PXy+XxIwHwYDVR0jBBgwFoAUoTYwFsuGkABFgFOxj8jYPXy+XxIwDgYDVR0PAQH/ +BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQCKIBilvrMvtKaEAEAwKfq0FHNMeUWn +9nDg6H5kHgqVfGphwu9OH77/yZkfB2FK4V1Mza3u0FIy2VkyvNp5ctZ7CegCgTXT +Ct8RHcl5oIBN/lrXVtbtDyqvpxh1MwzqwWEFT2qaifKNuZ8u77BfWgDrvq2g+EQF +Z7zLBO+eZMXpyD8Fv8YvBxzDNnGGyjhmSs3WuEvGbKeXO/oTLW4jYYehY0KswsuX +n2Fozy1MBJ3XJU8KDk2QixhWqJNIV9xvrr2eZ1d3iVCzvhGbRWeDhhmH05i9CBoW +H1iCC+GWaQVLjuyDUTEH1dSf/1l7qG6Fz9NLqUmwX7A5KGgOc90lmt4S +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIF5jCCA86gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCVVMx +HTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNBbWVyaWNh +IE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyOTA2MDAwMFoXDTM3MDkyODIz +NDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBT0wgVGltZSBXYXJuZXIg +SW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUgSW5jLjE3MDUGA1UEAxMuQU9M +IFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALQ3WggWmRToVbEbJGv8x4vmh6mJ +7ouZzU9AhqS2TcnZsdw8TQ2FTBVsRotSeJ/4I/1n9SQ6aF3Q92RhQVSji6UI0ilb +m2BPJoPRYxJWSXakFsKlnUWsi4SVqBax7J/qJBrvuVdcmiQhLE0OcR+mrF1FdAOY +xFSMFkpBd4aVdQxHAWZg/BXxD+r1FHjHDtdugRxev17nOirYlxcwfACtCJ0zr7iZ +YYCLqJV+FNwSbKTQ2O9ASQI2+W6p1h2WVgSysy0WVoaP2SBXgM1nEG2wTPDaRrbq +JS5Gr42whTg0ixQmgiusrpkLjhTXUr2eacOGAgvqdnUxCc4zGSGFQ+aJLZ8lN2fx +I2rSAG2X+Z/nKcrdH9cG6rjJuQkhn8g/BsXS6RJGAE57COtCPStIbp1n3UsC5ETz +kxmlJ85per5n0/xQpCyrw2u544BMzwVhSyvcG7mm0tCq9Stz+86QNZ8MUhy/XCFh +EVsVS6kkUfykXPcXnbDS+gfpj1bkGoxoigTTfFrjnqKhynFbotSg5ymFXQNoKk/S +Btc9+cMDLz9l+WceR0DTYw/j1Y75hauXTLPXJuuWCpTehTacyH+BCQJJKg71ZDIM +gtG6aoIbs0t0EfOMd9afv9w3pKdVBC/UMejTRrkDfNoSTllkt1ExMVCgyhwn2RAu +rda9EGYrw7AiShJbAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FE9pbQN+nZ8HGEO8txBO1b+pxCAoMB8GA1UdIwQYMBaAFE9pbQN+nZ8HGEO8txBO +1b+pxCAoMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAO/Ouyugu +h4X7ZVnnrREUpVe8WJ8kEle7+z802u6teio0cnAxa8cZmIDJgt43d15Ui47y6mdP +yXSEkVYJ1eV6moG2gcKtNuTxVBFT8zRFASbI5Rq8NEQh3q0l/HYWdyGQgJhXnU7q +7C+qPBR7V8F+GBRn7iTGvboVsNIYvbdVgaxTwOjdaRITQrcCtQVBynlQboIOcXKT +RuidDV29rs4prWPVVRaAMCf/drr3uNZK49m1+VLQTkCpx+XCMseqdiThawVQ68W/ +ClTluUI8JPu3B5wwn3la5uBAUhX0/Kr0VvlEl4ftDmVyXr4m+02kLQgH3thcoNyB +M5kYJRF3p+v9WAksmWsbivNSPxpNSGDxoPYzAlOL7SUJuA0t7Zdz7NeWH45gDtoQ +my8YJPamTQr5O8t1wswvziRpyQoijlmn94IM19drNZxDAGrElWe6nEXLuA4399xO +AU++CrYD062KRffaJ00psUjf5BHklka9bAI+1lHIlRcBFanyqqryvy9lG2/QuRqT +9Y41xICHPpQvZuTpqP9BnHAqTyo5GJUefvthATxRCC4oGKQWDzH9OmwjkyB24f0H +hdFbP9IcczLd+rn4jM8Ch3qaluTtT4mNU0OrDhPAARW0eTjb/G49nlG2uBOLZ8/5 +fNkiHfZdxRwBL5joeiQYvITX+txyW/fBOmg= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFajCCBFKgAwIBAgIEPLU9RjANBgkqhkiG9w0BAQUFADBmMRIwEAYDVQQKEwli +ZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENBczEzMDEGA1UEAxMq +YmVUUlVTVGVkIFJvb3QgQ0EtQmFsdGltb3JlIEltcGxlbWVudGF0aW9uMB4XDTAy +MDQxMTA3Mzg1MVoXDTIyMDQxMTA3Mzg1MVowZjESMBAGA1UEChMJYmVUUlVTVGVk +MRswGQYDVQQLExJiZVRSVVNUZWQgUm9vdCBDQXMxMzAxBgNVBAMTKmJlVFJVU1Rl +ZCBSb290IENBLUJhbHRpbW9yZSBJbXBsZW1lbnRhdGlvbjCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBALx+xDmcjOPWHIb/ymKt4H8wRXqOGrO4x/nRNv8i +805qX4QQ+2aBw5R5MdKR4XeOGCrDFN5R9U+jK7wYFuK13XneIviCfsuBH/0nLI/6 +l2Qijvj/YaOcGx6Sj8CoCd8JEey3fTGaGuqDIQY8n7pc/5TqarjDa1U0Tz0yH92B +FODEPM2dMPgwqZfT7syj0B9fHBOB1BirlNFjw55/NZKeX0Tq7PQiXLfoPX2k+Ymp +kbIq2eszh+6l/ePazIjmiSZuxyuC0F6dWdsU7JGDBcNeDsYq0ATdcT0gTlgn/FP7 +eHgZFLL8kFKJOGJgB7Sg7KxrUNb9uShr71ItOrL/8QFArDcCAwEAAaOCAh4wggIa +MA8GA1UdEwEB/wQFMAMBAf8wggG1BgNVHSAEggGsMIIBqDCCAaQGDysGAQQBsT4A +AAEJKIORMTCCAY8wggFIBggrBgEFBQcCAjCCAToaggE2UmVsaWFuY2Ugb24gb3Ig +dXNlIG9mIHRoaXMgQ2VydGlmaWNhdGUgY3JlYXRlcyBhbiBhY2tub3dsZWRnbWVu +dCBhbmQgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJk +IHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVzZSwgdGhlIENlcnRpZmljYXRpb24g +UHJhY3RpY2UgU3RhdGVtZW50IGFuZCB0aGUgUmVseWluZyBQYXJ0eSBBZ3JlZW1l +bnQsIHdoaWNoIGNhbiBiZSBmb3VuZCBhdCB0aGUgYmVUUlVTVGVkIHdlYiBzaXRl +LCBodHRwOi8vd3d3LmJldHJ1c3RlZC5jb20vcHJvZHVjdHNfc2VydmljZXMvaW5k +ZXguaHRtbDBBBggrBgEFBQcCARY1aHR0cDovL3d3dy5iZXRydXN0ZWQuY29tL3By +b2R1Y3RzX3NlcnZpY2VzL2luZGV4Lmh0bWwwHQYDVR0OBBYEFEU9w6nR3D8kVpgc +cxiIav+DR+22MB8GA1UdIwQYMBaAFEU9w6nR3D8kVpgccxiIav+DR+22MA4GA1Ud +DwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEASZK8o+6svfoNyYt5hhwjdrCA +WXf82n+0S9/DZEtqTg6t8n1ZdwWtColzsPq8y9yNAIiPpqCy6qxSJ7+hSHyXEHu6 +7RMdmgduyzFiEuhjA6p9beP4G3YheBufS0OM00mG9htc9i5gFdPp43t1P9ACg9AY +gkHNZTfqjjJ+vWuZXTARyNtIVBw74acT02pIk/c9jH8F6M7ziCpjBLjqflh8AXtb +4cV97yHgjQ5dUX2xZ/2jvTg2xvI4hocalmhgRvsoFEdV4aeADGvi6t9NfJBIoDa9 +CReJf8Py05yc493EG931t3GzUwWJBtDLSoDByFOQtTwxiBdQn8nEDovYqAJjDQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFLDCCBBSgAwIBAgIEOU99hzANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJX +VzESMBAGA1UEChMJYmVUUlVTVGVkMRswGQYDVQQDExJiZVRSVVNUZWQgUm9vdCBD +QXMxGjAYBgNVBAMTEWJlVFJVU1RlZCBSb290IENBMB4XDTAwMDYyMDE0MjEwNFoX +DTEwMDYyMDEzMjEwNFowWjELMAkGA1UEBhMCV1cxEjAQBgNVBAoTCWJlVFJVU1Rl +ZDEbMBkGA1UEAxMSYmVUUlVTVGVkIFJvb3QgQ0FzMRowGAYDVQQDExFiZVRSVVNU +ZWQgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANS0c3oT +CjhVAb6JVuGUntS+WutKNHUbYSnE4a0IYCF4SP+00PpeQY1hRIfo7clY+vyTmt9P +6j41ffgzeubx181vSUs9Ty1uDoM6GHh3o8/n9E1z2Jo7Gh2+lVPPIJfCzz4kUmwM +jmVZxXH/YgmPqsWPzGCgc0rXOD8Vcr+il7dw6K/ifhYGTPWqZCZyByWtNfwYsSbX +2P8ZDoMbjNx4RWc0PfSvHI3kbWvtILNnmrRhyxdviTX/507AMhLn7uzf/5cwdO2N +R47rtMNE5qdMf1ZD6Li8tr76g5fmu/vEtpO+GRg+jIG5c4gW9JZDnGdzF5DYCW5j +rEq2I8QBoa2k5MUCAwEAAaOCAfgwggH0MA8GA1UdEwEB/wQFMAMBAf8wggFZBgNV +HSAEggFQMIIBTDCCAUgGCisGAQQBsT4BAAAwggE4MIIBAQYIKwYBBQUHAgIwgfQa +gfFSZWxpYW5jZSBvbiB0aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1 +bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0 +ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGFuZCBjZXJ0aWZpY2F0aW9uIHBy +YWN0aWNlIHN0YXRlbWVudCwgd2hpY2ggY2FuIGJlIGZvdW5kIGF0IGJlVFJVU1Rl +ZCdzIHdlYiBzaXRlLCBodHRwczovL3d3dy5iZVRSVVNUZWQuY29tL3ZhdWx0L3Rl +cm1zMDEGCCsGAQUFBwIBFiVodHRwczovL3d3dy5iZVRSVVNUZWQuY29tL3ZhdWx0 +L3Rlcm1zMDQGA1UdHwQtMCswKaAnoCWkIzAhMRIwEAYDVQQKEwliZVRSVVNUZWQx +CzAJBgNVBAYTAldXMB0GA1UdDgQWBBQquZtpLjub2M3eKjEENGvKBxirZzAfBgNV +HSMEGDAWgBQquZtpLjub2M3eKjEENGvKBxirZzAOBgNVHQ8BAf8EBAMCAf4wDQYJ +KoZIhvcNAQEFBQADggEBAHlh26Nebhax6nZR+csVm8tpvuaBa58oH2U+3RGFktTo +Qb9+M70j5/Egv6S0phkBxoyNNXxlpE8JpNbYIxUFE6dDea/bow6be3ga8wSGWsb2 +jCBHOElQBp1yZzrwmAOtlmdE/D8QDYZN5AA7KXvOOzuZhmElQITcE2K3+spZ1gMe +1lMBzW1MaFVA4e5rxyoAAEiCswoBw2AqDPeCNe5IhpbkdNQ96gFxugR1QKepfzk5 +mlWXKWWuGVUlBXJH0+gY3Ljpr0NzARJ0o+FcXxVdJPP55PS2Z2cS52QiivalQaYc +tmBjRYoQtLpGEK5BV2VsPyMQPyEQWbfkQN0mDCP2qq4= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGUTCCBTmgAwIBAgIEPLVPQDANBgkqhkiG9w0BAQUFADBmMRIwEAYDVQQKEwli +ZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENBczEzMDEGA1UEAxMq +YmVUUlVTVGVkIFJvb3QgQ0EgLSBFbnRydXN0IEltcGxlbWVudGF0aW9uMB4XDTAy +MDQxMTA4MjQyN1oXDTIyMDQxMTA4NTQyN1owZjESMBAGA1UEChMJYmVUUlVTVGVk +MRswGQYDVQQLExJiZVRSVVNUZWQgUm9vdCBDQXMxMzAxBgNVBAMTKmJlVFJVU1Rl +ZCBSb290IENBIC0gRW50cnVzdCBJbXBsZW1lbnRhdGlvbjCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBALr0RAOqEmq1Q+xVkrYwfTVXDNvzDSduTPdQqJtO +K2/b9a0cS12zqcH+e0TrW6MFDR/FNCswACnxeECypP869AGIF37m1CbTukzqMvtD +d5eHI8XbQ6P1KqNRXuE70mVpflUVm3rnafdE4Fe1FehmYA8NA/uCjqPoEXtsvsdj +DheT389Lrm5zdeDzqrmkwAkbhepxKYhBMvnwKg5sCfJ0a2ZsUhMfGLzUPvfYbiCe +yv78IZTuEyhL11xeDGbu6bsPwTSxfwh28z0mcMmLJR1iJAzqHHVOwBLkuhMdMCkt +VjMFu5dZfsZJT4nXLySotohAtWSSU1Yk5KKghbNekLQSM80CAwEAAaOCAwUwggMB +MIIBtwYDVR0gBIIBrjCCAaowggGmBg8rBgEEAbE+AAACCSiDkTEwggGRMIIBSQYI +KwYBBQUHAgIwggE7GoIBN1JlbGlhbmNlIG9uIG9yIHVzZSBvZiB0aGlzIENlcnRp +ZmljYXRlIGNyZWF0ZXMgYW4gYWNrbm93bGVkZ21lbnQgYW5kIGFjY2VwdGFuY2Ug +b2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0 +aW9ucyBvZiB1c2UsIHRoZSBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu +dCBhbmQgdGhlIFJlbHlpbmcgUGFydHkgQWdyZWVtZW50LCB3aGljaCBjYW4gYmUg +Zm91bmQgYXQgdGhlIGJlVFJVU1RlZCB3ZWIgc2l0ZSwgaHR0cHM6Ly93d3cuYmV0 +cnVzdGVkLmNvbS9wcm9kdWN0c19zZXJ2aWNlcy9pbmRleC5odG1sMEIGCCsGAQUF +BwIBFjZodHRwczovL3d3dy5iZXRydXN0ZWQuY29tL3Byb2R1Y3RzX3NlcnZpY2Vz +L2luZGV4Lmh0bWwwEQYJYIZIAYb4QgEBBAQDAgAHMIGJBgNVHR8EgYEwfzB9oHug +eaR3MHUxEjAQBgNVBAoTCWJlVFJVU1RlZDEbMBkGA1UECxMSYmVUUlVTVGVkIFJv +b3QgQ0FzMTMwMQYDVQQDEypiZVRSVVNUZWQgUm9vdCBDQSAtIEVudHJ1c3QgSW1w +bGVtZW50YXRpb24xDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMjAwMjA0MTEw +ODI0MjdagQ8yMDIyMDQxMTA4NTQyN1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaA +FH1w5a44iwY/qhwaj/nPJDCqhIQWMB0GA1UdDgQWBBR9cOWuOIsGP6ocGo/5zyQw +qoSEFjAMBgNVHRMEBTADAQH/MB0GCSqGSIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIE +kDANBgkqhkiG9w0BAQUFAAOCAQEAKrgXzh8QlOu4mre5X+za95IkrNySO8cgjfKZ +5V04ocI07cUTWVwFtStPYZuR+0H8/NU8TZh2BvWBfevdkObRVlTa4y0MnxEylCIB +evZsLHRnBMylj44ss0O1lKLQfelifwa+JwGDnjr9iu6YQ0pr17WXOzq/T220Y/oz +ADQuLW2WyXvKmWO6vvT2MKAtmJbpVkQFqUSjYRDrgqFnXbxdJ3Wqiig2KjiS2d2k +XgClzMx8KSreKJCrt+G2/30lC0DYqjSjLd4H61/OCt3Kfjp9JsFiaDrmLzfzgYYh +xKlkqu9FNtEaZnz46TfW1mG+oq1I59/mdP7TbX3SJdysYlep9w== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFaDCCBFCgAwIBAgIQO1nHe81bV569N1KsdrSqGjANBgkqhkiG9w0BAQUFADBi +MRIwEAYDVQQKEwliZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENB +czEvMC0GA1UEAxMmYmVUUlVTVGVkIFJvb3QgQ0EgLSBSU0EgSW1wbGVtZW50YXRp +b24wHhcNMDIwNDExMTExODEzWhcNMjIwNDEyMTEwNzI1WjBiMRIwEAYDVQQKEwli +ZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENBczEvMC0GA1UEAxMm +YmVUUlVTVGVkIFJvb3QgQ0EgLSBSU0EgSW1wbGVtZW50YXRpb24wggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkujQwCY5X0LkGLG9uJIAiv11DpvpPrILn +HGhwhRujbrWqeNluB0s/6d/16uhUoWGKDi9pdRi3DOUUjXFumLhV/AyV0Jtu4S2I +1DpAa5LxmZZk3tv/ePTulh1HiXzUvrmIdyM6CeYEnm2qXtLIvZpOGd+J6lsOfsPk +tPDgaTuID0GQ+NRxQyTBjyZLO1bp/4xsN+lFrYWMU8NghpBKlsmzVLC7F/AcRdnU +GxlkVgoZ98zh/4avflherHqQH8koOUV7orbHnB/ahdQhhlkwk75TMzf270HPM8er +cmsl9fNTGwxMLvF1S++gh/f+ihXQbNXL+WhTuXAVE8L1LvtDNXUtAgMBAAGjggIY +MIICFDAMBgNVHRMEBTADAQH/MIIBtQYDVR0gBIIBrDCCAagwggGkBg8rBgEEAbE+ +AAADCSiDkTEwggGPMEEGCCsGAQUFBwIBFjVodHRwOi8vd3d3LmJldHJ1c3RlZC5j +b20vcHJvZHVjdHNfc2VydmljZXMvaW5kZXguaHRtbDCCAUgGCCsGAQUFBwICMIIB +OhqCATZSZWxpYW5jZSBvbiBvciB1c2Ugb2YgdGhpcyBDZXJ0aWZpY2F0ZSBjcmVh +dGVzIGFuIGFja25vd2xlZGdtZW50IGFuZCBhY2NlcHRhbmNlIG9mIHRoZSB0aGVu +IGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdXNl +LCB0aGUgQ2VydGlmaWNhdGlvbiBQcmFjdGljZSBTdGF0ZW1lbnQgYW5kIHRoZSBS +ZWx5aW5nIFBhcnR5IEFncmVlbWVudCwgd2hpY2ggY2FuIGJlIGZvdW5kIGF0IHRo +ZSBiZVRSVVNUZWQgd2ViIHNpdGUsIGh0dHA6Ly93d3cuYmV0cnVzdGVkLmNvbS9w +cm9kdWN0c19zZXJ2aWNlcy9pbmRleC5odG1sMAsGA1UdDwQEAwIBBjAfBgNVHSME +GDAWgBSp7BR++dlDzFMrFK3P9/BZiUHNGTAdBgNVHQ4EFgQUqewUfvnZQ8xTKxSt +z/fwWYlBzRkwDQYJKoZIhvcNAQEFBQADggEBANuXsHXqDMTBmMpWBcCorSZIry0g +6IHHtt9DwSwddUvUQo3neqh03GZCWYez9Wlt2ames30cMcH1VOJZJEnl7r05pmuK +mET7m9cqg5c0Lcd9NUwtNLg+DcTsiCevnpL9UGGCqGAHFFPMZRPB9kdEadIxyKbd +LrML3kqNWz2rDcI1UqJWN8wyiyiFQpyRQHpwKzg21eFzGh/l+n5f3NacOzDq28Bb +J1zTcwfBwvNMm2+fG8oeqqg4MwlYsq78B+g23FW6L09A/nq9BqaBwZMifIYRCgZ3 +SK41ty8ymmFei74pnykkiFY5LKjSq5YDWtRIn7lAhAuYaPsBQ9Yb4gmxlxw= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn +MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL +ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg +b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa +MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB +ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw +IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B +AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb +unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d +BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq +7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 +0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX +roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG +A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j +aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p +26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA +BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud +EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN +BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz +aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB +AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd +p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi +1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc +XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 +eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu +tGWaIZDgqtCYvDi1czyL+Nw= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn +MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL +ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo +YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9 +MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy +NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G +A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA +A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0 +Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s +QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV +eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795 +B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh +z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T +AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i +ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w +TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH +MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD +VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE +VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh +bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B +AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM +bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi +ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG +VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c +ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/ +AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw +PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz +cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9 +MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz +IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ +ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR +VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL +kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd +EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas +H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0 +HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud +DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4 +QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu +Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/ +AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8 +yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR +FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA +ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB +kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 +l7+ijrRU +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBM +MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD +QTAeFw0wMjA2MTExMDQ2MzlaFw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBM +MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD +QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6xwS7TT3zNJc4YPk/E +jG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdLkKWo +ePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GI +ULdtlkIJ89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapu +Ob7kky/ZR6By6/qmW6/KUz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUg +AKpoC6EahQGcxEZjgoi2IrHu/qpGWX7PNSzVttpd90gzFFS269lvzs2I1qsb2pY7 +HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA +uI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+GXYkHAQa +TOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTg +xSvgGrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1q +CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x +O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs +6GAqm4VKQPNriiTsBhYscw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj +YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM +GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua +BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe +3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 +YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR +rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm +ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU +oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v +QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t +b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF +AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q +GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 +G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi +l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 +smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB +gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV +BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw +MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl +YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P +RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 +UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI +2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 +Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp ++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ +DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O +nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW +/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g +PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u +QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY +SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv +IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 +zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd +BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB +ZQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT +IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw +MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy +ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N +T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR +FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J +cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW +BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm +fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv +GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp +ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow +fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV +BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM +cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S +HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996 +CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk +3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz +6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV +HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud +EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv +Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw +Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww +DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0 +5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj +Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI +gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ +aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl +izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0 +aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla +MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO +BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD +VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW +fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt +TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL +fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW +1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7 +kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G +A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v +ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo +dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu +Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/ +HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 +pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS +jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+ +xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn +dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c +JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP +mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ +wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 +VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ +AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB +AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun +pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC +dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf +fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm +NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx +H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm ++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW +PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM +xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB +Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 +hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg +EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA +FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec +nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z +eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF +hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 +Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep ++OkuE6N36B9K +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV +UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL +EwhEU1RDQSBFMTAeFw05ODEyMTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJ +BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x +ETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCg +bIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJENySZ +j9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlV +Sn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCG +SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx +JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI +RFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMTAxODEw +MjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFGp5 +fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i ++DAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG +SIb3DQEBBQUAA4GBACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lN +QseSJqBcNJo4cvj9axY+IO6CizEqkzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+ +gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4RbyhkwS7hp86W0N6w4pl +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2DCCAsACEQDQHkCLAAACfAAAAAIAAAABMA0GCSqGSIb3DQEBBQUAMIGpMQsw +CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp +dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UE +CxMIRFNUQ0EgWDExFjAUBgNVBAMTDURTVCBSb290Q0EgWDExITAfBgkqhkiG9w0B +CQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05ODEyMDExODE4NTVaFw0wODExMjgx +ODE4NTVaMIGpMQswCQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMO +U2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0 +IENvLjERMA8GA1UECxMIRFNUQ0EgWDExFjAUBgNVBAMTDURTVCBSb290Q0EgWDEx +ITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBANLGJrbnpT3BxGjVUG9TxW9JEwm4ryxIjRRqoxdf +WvnTLnUv2Chi0ZMv/E3Uq4flCMeZ55I/db3rJbQVwZsZPdJEjdd0IG03Ao9pk1uK +xBmd9LIO/BZsubEFkoPRhSxglD5FVaDZqwgh5mDoO3TymVBRaNADLbGAvqPYUrBE +zUNKcI5YhZXhTizWLUFv1oTnyJhEykfbLCSlaSbPa7gnYsP0yXqSI+0TZ4KuRS5F +5X5yP4WdlGIQ5jyRoa13AOAV7POEgHJ6jm5gl8ckWRA0g1vhpaRptlc1HHhZxtMv +OnNn7pTKBBMFYgZwI7P0fO5F2WQLW0mqpEPOJsREEmy43XkCAwEAATANBgkqhkiG +9w0BAQUFAAOCAQEAojeyP2n714Z5VEkxlTMr89EJFEliYIalsBHiUMIdBlc+Legz +ZL6bqq1fG03UmZWii5rJYnK1aerZWKs17RWiQ9a2vAd5ZWRzfdd5ynvVWlHG4VME +lo04z6MXrDlxawHDi1M8Y+nuecDkvpIyZHqzH5eUYr3qsiAVlfuX8ngvYzZAOONG +Dx3drJXK50uQe7FLqdTF65raqtWjlBRGjS0f8zrWkzr2Pnn86Oawde3uPclwx12q +gUtGJRzHbBXjlU4PqjI3lAoXJJIThFjSY28r9+ZbYgsTF7ANUkz+/m9c4pFuHf2k +Ytdo+o56T9II2pPc8JIRetDccpMMc5NihWjQ9A== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV +UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL +EwhEU1RDQSBFMjAeFw05ODEyMDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJ +BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x +ETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/ +k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvso +LeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3o +TQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCG +SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx +JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI +RFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxOTE3 +MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFB6C +TShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5 +WzAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG +SIb3DQEBBQUAA4GBAEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHR +xdf0CiUPPXiBng+xZ8SQTGPdXqfiup/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVL +B3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1mPnHfxsb1gYgAlihw6ID +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2DCCAsACEQDQHkCLAAB3bQAAAAEAAAAEMA0GCSqGSIb3DQEBBQUAMIGpMQsw +CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp +dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UE +CxMIRFNUQ0EgWDIxFjAUBgNVBAMTDURTVCBSb290Q0EgWDIxITAfBgkqhkiG9w0B +CQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05ODExMzAyMjQ2MTZaFw0wODExMjcy +MjQ2MTZaMIGpMQswCQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMO +U2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0 +IENvLjERMA8GA1UECxMIRFNUQ0EgWDIxFjAUBgNVBAMTDURTVCBSb290Q0EgWDIx +ITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBANx18IzAdZaawGIfJvfE4Zrq4FZzW5nNAUSoCLbV +p9oaBBg5kkp4o4HC9Xd6ULRw/5qrxsfKboNPQpj7Jgva3G3WqZlVUmfpKAOS3OWw +BZoPFflrWXJW8vo5/Kpo7g8fEIMv/J36F5bdguPmRX3AS4BEH+0s4IT9kVySVGkl +5WJp3OXuAFK9MwutdQKFp2RQLcUZGTDAJtvJ0/0uma1ZtQtN1EGuhUhDWdy3qOKi +3sOP17ihYqZoUFLkzzGnlIXan0YyF1bl8utmPRL/Q9uY73fPy4GNNLHGUEom0eQ+ +QVCvbK4iNC7Va26Dunm4dmVI2gkpZGMiuftHdoWMhkTLCdsCAwEAATANBgkqhkiG +9w0BAQUFAAOCAQEAtTYOXeFhKFoRZcA/gwN5Tb4opgsHAlKFzfiR0BBstWogWxyQ +2TA8xkieil5k+aFxd+8EJx8H6+Qm93N0yUQYGmbT4EOvkTvRyyzYdFQ6HE3K1GjN +I3wdEJ5F6fYAbqbNGf9PLCmPV03Ed5K+4EwJ+11EhmYhqLkyolbV6YyDfFk/xPEL +553snr2cGA4+wjl5KLcDDQjLxufZATdQEOzMYRZA1K8xdHv8PzGn0EdzMzkbzE5q +10mDEQb+64JYMzJM8FasHpwvVpp7wUocpf1VNs78lk30sPDst2yC7S8xmUJMqbIN +uBVd8d+6ybVK1GSYsyapMMj9puyrliGtf8J4tg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBb +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3Qx +ETAPBgNVBAsTCERTVCBBQ0VTMRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0w +MzExMjAyMTE5NThaFw0xNzExMjAyMTE5NThaMFsxCzAJBgNVBAYTAlVTMSAwHgYD +VQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UECxMIRFNUIEFDRVMx +FzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPu +ktKe1jzIDZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7 +gLFViYsx+tC3dr5BPTCapCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZH +fAjIgrrep4c9oW24MFbCswKBXy314powGCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4a +ahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPyMjwmR/onJALJfh1biEIT +ajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rk +c3QuY29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjto +dHRwOi8vd3d3LnRydXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMt +aW5kZXguaHRtbDAdBgNVHQ4EFgQUCXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZI +hvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V25FYrnJmQ6AgwbN99Pe7lv7Uk +QIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6tFr8hlxCBPeP/ +h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq +nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpR +rscL9yuwNwXsvFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf2 +9w4LTJxoeHtxMcfrHuBnQfO3oKfN5XozNmr6mis= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEgzCCA+ygAwIBAgIEOJ725DANBgkqhkiG9w0BAQQFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9HQ0NBX0NQUyBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAyMDAw +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENsaWVu +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMDAyMDcxNjE2NDBaFw0yMDAy +MDcxNjQ2NDBaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0dDQ0FfQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDIwMDAgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCTdLS25MVL1qFof2LV7PdRV7Ny +Spj10InJrWPNTTVRaoTUrcloeW+46xHbh65cJFET8VQlhK8pK5/jgOLZy93GRUk0 +iJBeAZfv6lOm3fzB3ksqJeTpNfpVBQbliXrqpBFXO/x8PTbNZzVtpKklWb1m9fkn +5JVn1j+SgF7yNH0rhQIDAQABo4IBnjCCAZowEQYJYIZIAYb4QgEBBAQDAgAHMIHd +BgNVHR8EgdUwgdIwgc+ggcyggcmkgcYwgcMxFDASBgNVBAoTC0VudHJ1c3QubmV0 +MUAwPgYDVQQLFDd3d3cuZW50cnVzdC5uZXQvR0NDQV9DUFMgaW5jb3JwLiBieSBy +ZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMjAwMCBFbnRydXN0Lm5l +dCBMaW1pdGVkMTMwMQYDVQQDEypFbnRydXN0Lm5ldCBDbGllbnQgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMjAwMDAy +MDcxNjE2NDBagQ8yMDIwMDIwNzE2NDY0MFowCwYDVR0PBAQDAgEGMB8GA1UdIwQY +MBaAFISLdP3FjcD/J20gN0V8/i3OutN9MB0GA1UdDgQWBBSEi3T9xY3A/ydtIDdF +fP4tzrrTfTAMBgNVHRMEBTADAQH/MB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4w +AwIEkDANBgkqhkiG9w0BAQQFAAOBgQBObzWAO9GK9Q6nIMstZVXQkvTnhLUGJoMS +hAusO7JE7r3PQNsgDrpuFOow4DtifH+La3xKp9U1PL6oXOpLu5OOgGarDyn9TS2/ +GpsKkMWr2tGzhtQvJFJcem3G8v7lTRowjJDyutdKPkN+1MhQGof4T4HHdguEOnKd +zmVml64mXg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIElTCCA/6gAwIBAgIEOJsRPDANBgkqhkiG9w0BAQQFADCBujEUMBIGA1UEChML +RW50cnVzdC5uZXQxPzA9BgNVBAsUNnd3dy5lbnRydXN0Lm5ldC9TU0xfQ1BTIGlu +Y29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDIwMDAg +RW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJl +IFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMDAyMDQxNzIwMDBa +Fw0yMDAyMDQxNzUwMDBaMIG6MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDE/MD0GA1UE +CxQ2d3d3LmVudHJ1c3QubmV0L1NTTF9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p +dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMjAwMCBFbnRydXN0Lm5ldCBMaW1pdGVk +MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp +b24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHwV9OcfHO +8GCGD9JYf9Mzly0XonUwtZZkJi9ow0SrqHXmAGc0V55lxyKbc+bT3QgON1WqJUaB +bL3+qPZ1V1eMkGxKwz6LS0MKyRFWmponIpnPVZ5h2QLifLZ8OAfc439PmrkDQYC2 +dWcTC5/oVzbIXQA23mYU2m52H083jIITiQIDAQABo4IBpDCCAaAwEQYJYIZIAYb4 +QgEBBAQDAgAHMIHjBgNVHR8EgdswgdgwgdWggdKggc+kgcwwgckxFDASBgNVBAoT +C0VudHJ1c3QubmV0MT8wPQYDVQQLFDZ3d3cuZW50cnVzdC5uZXQvU1NMX0NQUyBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAyMDAw +IEVudHJ1c3QubmV0IExpbWl0ZWQxOjA4BgNVBAMTMUVudHJ1c3QubmV0IFNlY3Vy +ZSBTZXJ2ZXIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEw +KwYDVR0QBCQwIoAPMjAwMDAyMDQxNzIwMDBagQ8yMDIwMDIwNDE3NTAwMFowCwYD +VR0PBAQDAgEGMB8GA1UdIwQYMBaAFMtswGvjuz7L/CKc/vuLkpyw8m4iMB0GA1Ud +DgQWBBTLbMBr47s+y/winP77i5KcsPJuIjAMBgNVHRMEBTADAQH/MB0GCSqGSIb2 +fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQQFAAOBgQBi24GRzsia +d0Iv7L0no1MPUBvqTpLwqa+poLpIYcvvyQbvH9X07t9WLebKahlzqlO+krNQAraF +JnJj2HVQYnUUt7NQGj/KEQALhUVpbbalrlHhStyCP2yMNLJ3a9kC9n8O6mUE8c1U +yrrJzOCE98g+EZfTYAkYvAX/bIkz8OwVDw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy +MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA +vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G +CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA +WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo +oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ +h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18 +f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN +B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy +vUxFnmG6v4SBkgPR0ml8xQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50cnVzdC5u +ZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBsaW1pdHMgbGlh +Yi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBaMIHJMQswCQYDVQQGEwJVUzEU +MBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9D +bGllbnRfQ0FfSW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMq +RW50cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0G +CSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo +6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux +5zDeg7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zm +AqTmT173iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSC +ARkwggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50 +cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5m +by9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMp +IDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQg +Q2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCyg +KqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9DbGllbnQxLmNybDArBgNV +HRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkxMDEyMTkyNDMwWjALBgNVHQ8E +BAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW/O5bs8qZdIuV6kwwHQYDVR0OBBYE +FMT7nCl7l81MlvzuW7PKmXSLlepMMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA +BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7 +pFuPeJoSSJn59DXeDDYHAmsQOokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzz +wy5E97BnRqqS5TvaHBkUODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/a +EkP/TOYGJqibGapEPHayXOw= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u +ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc +KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u +ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 +MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE +ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j +b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF +bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg +U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ +I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 +wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC +AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb +oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 +BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p +dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk +MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp +b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu +dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 +MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi +E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa +MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI +hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN +95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd +2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 +Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW +KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw +NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw +NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy +ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV +BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo +Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 +4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 +KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI +rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi +94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB +sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi +gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo +kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE +vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t +O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua +AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP +9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ +eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m +0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV +UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy +dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 +MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx +dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f +BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A +cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC +AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm +aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw +ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj +IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF +MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA +A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y +7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh +1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT +ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw +MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j +LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ +KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo +RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu +WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw +Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD +AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK +eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM +zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+ +WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN +/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj +dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0 +NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD +VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G +vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/ +BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C +AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX +MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl +IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw +NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq +y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF +MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA +A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy +0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1 +E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT +ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw +MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj +dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l +c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC +UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc +58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/ +o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH +MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr +aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA +A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA +Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv +8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMx +IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1 +dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w +HhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTELMAkGA1UEBhMCRVMx +IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1 +dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5u +Cp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5Vj1H5WuretXDE7aTt/6MNbg9kUDGvASdY +rv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJHlShbz++AbOCQl4oBPB3z +hxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf3H5idPay +BQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcL +iam8NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcb +AgMBAAGjgZ8wgZwwKgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lv +bmFsLmNvbTASBgNVHRMBAf8ECDAGAQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0 +MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E +FgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQADggEBAEdz/o0n +VPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq +u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36m +hoEyIwOdyPdfwUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzfl +ZKG+TQyTmAyX9odtsz/ny4Cm7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBp +QWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YGVM+h4k0460tQtcsm9MracEpqoeJ5 +quGnM/b9Sh/22WA= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs +IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg +R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A +PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8 +Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL +TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL +5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7 +S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe +2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap +EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td +EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv +/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN +A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0 +abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF +I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz +4iIprn2DQKi6bA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg +R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 +9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq +fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv +iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU +1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ +bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW +MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA +ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l +uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn +Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS +tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF +PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un +hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV +5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY +MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo +R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx +MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK +Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 +AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA +ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 +7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W +kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI +mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ +KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 +6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl +4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K +oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj +UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU +AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy +c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD +VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 +c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 +WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG +FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq +XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL +se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb +KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd +IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 +y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt +hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc +QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 +Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV +HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ +KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z +dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ +L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr +Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo +ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY +T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz +GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m +1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV +OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH +6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX +QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy +c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE +BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 +IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV +VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 +cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT +QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh +F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v +c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w +mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd +VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX +teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ +f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe +Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ +nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB +/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY +MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG +9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc +aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX +IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn +ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z +uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN +Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja +QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW +koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 +ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt +DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm +bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh +MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE +YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 +MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo +ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg +MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN +ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA +PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w +wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi +EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY +avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ +YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE +sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h +/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 +IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy +OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P +TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER +dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf +ReYNnyicsbkqWletNw+vHX/bvZ8= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv +b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds +b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH +iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS +r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 +04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r +GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 +3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P +lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIB+jCCAWMCAgGjMA0GCSqGSIb3DQEBBAUAMEUxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xHDAaBgNVBAMTE0dURSBDeWJlclRydXN0IFJv +b3QwHhcNOTYwMjIzMjMwMTAwWhcNMDYwMjIzMjM1OTAwWjBFMQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMRwwGgYDVQQDExNHVEUgQ3liZXJU +cnVzdCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC45k+625h8cXyv +RLfTD0bZZOWTwUKOx7pJjTUteueLveUFMVnGsS8KDPufpz+iCWaEVh43KRuH6X4M +ypqfpX/1FZSj1aJGgthoTNE3FQZor734sLPwKfWVWgkWYXcKIiXUT0Wqx73llt/5 +1KiOQswkwB6RJ0q1bQaAYznEol44AwIDAQABMA0GCSqGSIb3DQEBBAUAA4GBABKz +dcZfHeFhVYAA1IFLezEPI2PnPfMD+fQ2qLvZ46WXTeorKeDWanOB5sCJo9Px4KWl +IjeaY8JIILTbcuPI9tl8vrGvU9oUtCG41tWW4/5ODFlitppK+ULdjG+BqXH/9Apy +bW1EDp3zdHSo1TRJ6V6e6bR64eVaH4QwnNOfpSXY +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIH9zCCB2CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARwxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEzMDEGA1UECxMq +SVBTIENBIENoYWluZWQgQ0FzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTMwMQYD +VQQDEypJUFMgQ0EgQ2hhaW5lZCBDQXMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx +HjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczAeFw0wMTEyMjkwMDUzNTha +Fw0yNTEyMjcwMDUzNThaMIIBHDELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNl +bG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQg +cHVibGlzaGluZyBTZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMu +ZXMgQy5JLkYuICBCLTYwOTI5NDUyMTMwMQYDVQQLEypJUFMgQ0EgQ2hhaW5lZCBD +QXMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMzAxBgNVBAMTKklQUyBDQSBDaGFp +bmVkIENBcyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3DQEJARYP +aXBzQG1haWwuaXBzLmVzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcVpJJ +spQgvJhPUOtopKdJC7/SMejHT8KGC/po/UNaivNgkjWZOLtNA1IhW/A3mTXhQSCB +hYEFcYGdtJUZqV92NC5jNzVXjrQfQj8VXOF6wV8TGDIxya2+o8eDZh65nAQTy2nB +Bt4wBrszo7Uf8I9vzv+W6FS+ZoCua9tBhDaiPQIDAQABo4IEQzCCBD8wHQYDVR0O +BBYEFKGtMbH5PuEXpsirNPxShwkeYlJBMIIBTgYDVR0jBIIBRTCCAUGAFKGtMbH5 +PuEXpsirNPxShwkeYlJBoYIBJKSCASAwggEcMQswCQYDVQQGEwJFUzESMBAGA1UE +CBMJQmFyY2Vsb25hMRIwEAYDVQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJ +bnRlcm5ldCBwdWJsaXNoaW5nIFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0Bt +YWlsLmlwcy5lcyBDLkkuRi4gIEItNjA5Mjk0NTIxMzAxBgNVBAsTKklQUyBDQSBD +aGFpbmVkIENBcyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEzMDEGA1UEAxMqSVBT +IENBIENoYWluZWQgQ0FzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI +hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8E +BQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMG +CCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYB +BAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMw +EYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGBD2lwc0BtYWlsLmlwcy5lczBC +BglghkgBhvhCAQ0ENRYzQ2hhaW5lZCBDQSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkg +aHR0cDovL3d3dy5pcHMuZXMvMCkGCWCGSAGG+EIBAgQcFhpodHRwOi8vd3d3Lmlw +cy5lcy9pcHMyMDAyLzA3BglghkgBhvhCAQQEKhYoaHR0cDovL3d3dy5pcHMuZXMv +aXBzMjAwMi9pcHMyMDAyQ0FDLmNybDA8BglghkgBhvhCAQMELxYtaHR0cDovL3d3 +dy5pcHMuZXMvaXBzMjAwMi9yZXZvY2F0aW9uQ0FDLmh0bWw/MDkGCWCGSAGG+EIB +BwQsFipodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3JlbmV3YWxDQUMuaHRtbD8w +NwYJYIZIAYb4QgEIBCoWKGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5 +Q0FDLmh0bWwwbQYDVR0fBGYwZDAuoCygKoYoaHR0cDovL3d3dy5pcHMuZXMvaXBz +MjAwMi9pcHMyMDAyQ0FDLmNybDAyoDCgLoYsaHR0cDovL3d3d2JhY2suaXBzLmVz +L2lwczIwMDIvaXBzMjAwMkNBQy5jcmwwLwYIKwYBBQUHAQEEIzAhMB8GCCsGAQUF +BzABhhNodHRwOi8vb2NzcC5pcHMuZXMvMA0GCSqGSIb3DQEBBQUAA4GBAERyMJ1W +WKJBGyi3leGmGpVfp3hAK+/blkr8THFj2XOVvQLiogbHvpcqk4A0hgP63Ng9HgfN +HnNDJGD1HWHc3JagvPsd4+cSACczAsDAK1M92GsDgaPb1pOVIO/Tln4mkImcJpvN +b2ar7QMiRDjMWb2f2/YHogF/JsRj9SVCXmK9 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIH6jCCB1OgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl +SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl +SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 +DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIyOTAwNTkzOFoXDTI1MTIyNzAw +NTkzOFowggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD +VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n +IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g +IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4FEnpwvdr9G5Q1uCN0VWcu+atsIS7ywS +zHb5BlmvXSHU0lq4oNTzav3KaY1mSPd05u42veiWkXWmcSjK5yISMmmwPh5r9FBS +YmL9Yzt9fuzuOOpi9GyocY3h6YvJP8a1zZRCb92CRTzo3wno7wpVqVZHYUxJZHMQ +KD/Kvwn/xi8CAwEAAaOCBEowggRGMB0GA1UdDgQWBBTrsxl588GlHKzcuh9morKb +adB4CDCCAUQGA1UdIwSCATswggE3gBTrsxl588GlHKzcuh9morKbadB4CKGCARqk +ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE +BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT +ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC +LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD +VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr +BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB +FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC +AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB +D2lwc0BtYWlsLmlwcy5lczBBBglghkgBhvhCAQ0ENBYyQ0xBU0UxIENBIENlcnRp +ZmljYXRlIGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgEC +BBwWGmh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDoGCWCGSAGG+EIBBAQtFito +dHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTEuY3JsMD8GCWCG +SAGG+EIBAwQyFjBodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3Jldm9jYXRpb25D +TEFTRTEuaHRtbD8wPAYJYIZIAYb4QgEHBC8WLWh0dHA6Ly93d3cuaXBzLmVzL2lw +czIwMDIvcmVuZXdhbENMQVNFMS5odG1sPzA6BglghkgBhvhCAQgELRYraHR0cDov +L3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTEuaHRtbDBzBgNVHR8EbDBq +MDGgL6AthitodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTEu +Y3JsMDWgM6Axhi9odHRwOi8vd3d3YmFjay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy +Q0xBU0UxLmNybDAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9v +Y3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQADgYEAK9Dr/drIyllq2tPMMi7JVBuK +Yn4VLenZMdMu9Ccj/1urxUq2ckCuU3T0vAW0xtnIyXf7t/k0f3gA+Nak5FI/LEpj +V4F1Wo7ojPsCwJTGKbqz3Bzosq/SLmJbGqmODszFV0VRFOlOHIilkfSj945RyKm+ +hjM+5i9Ibq9UkE6tsSU= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIH6jCCB1OgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl +SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl +SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 +DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIyOTAxMDE0NFoXDTI1MTIyNzAx +MDE0NFowggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD +VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n +IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g +IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqxf+DrDGaBtT8FK+n/ra+osTBLsBjzLZ +H49NzjaY2uQARIwo2BNEKqRrThckQpzTiKRBgtYj+4vJhuW5qYIF3PHeH+AMmVWY +8jjsbJ0gA8DvqqPGZARRLXgNo9KoOtYkTOmWehisEyMiG3zoMRGzXwmqMHBxRiVr +SXGAK5UBsh8CAwEAAaOCBEowggRGMB0GA1UdDgQWBBS4k/8uy9wsjqLnev42USGj +mFsMNDCCAUQGA1UdIwSCATswggE3gBS4k/8uy9wsjqLnev42USGjmFsMNKGCARqk +ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE +BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT +ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC +LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD +VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr +BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB +FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC +AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB +D2lwc0BtYWlsLmlwcy5lczBBBglghkgBhvhCAQ0ENBYyQ0xBU0UzIENBIENlcnRp +ZmljYXRlIGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgEC +BBwWGmh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDoGCWCGSAGG+EIBBAQtFito +dHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTMuY3JsMD8GCWCG +SAGG+EIBAwQyFjBodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3Jldm9jYXRpb25D +TEFTRTMuaHRtbD8wPAYJYIZIAYb4QgEHBC8WLWh0dHA6Ly93d3cuaXBzLmVzL2lw +czIwMDIvcmVuZXdhbENMQVNFMy5odG1sPzA6BglghkgBhvhCAQgELRYraHR0cDov +L3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTMuaHRtbDBzBgNVHR8EbDBq +MDGgL6AthitodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTMu +Y3JsMDWgM6Axhi9odHRwOi8vd3d3YmFjay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy +Q0xBU0UzLmNybDAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9v +Y3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQADgYEAF2VcmZVDAyevJuXr0LMXI/dD +qsfwfewPxqmurpYPdikc4gYtfibFPPqhwYHOU7BC0ZdXGhd+pFFhxu7pXu8Fuuu9 +D6eSb9ijBmgpjnn1/7/5p6/ksc7C0YBCJwUENPjDfxZ4IwwHJPJGR607VNCv1TGy +r33I6unUVtkOE7LFRVA= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIH9zCCB2CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm +SVBTIENBIENMQVNFQTEgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT +JklQUyBDQSBDTEFTRUExIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI +hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjI5MDEwNTMyWhcNMjUxMjI3 +MDEwNTMyWjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALsw19zQVL01Tp/FTILq0VA8R5j8 +m2mdd81u4D/u6zJfX5/S0HnllXNEITLgCtud186Nq1KLK3jgm1t99P1tCeWu4Wwd +ByOgF9H5fahGRpEiqLJpxq339fWUoTCUvQDMRH/uxJ7JweaPCjbB/SQ9AaD1e+J8 +eGZDi09Z8pvZ+kmzAgMBAAGjggRTMIIETzAdBgNVHQ4EFgQUZyaW56G/2LUDnf47 +3P7yiuYV3TAwggFGBgNVHSMEggE9MIIBOYAUZyaW56G/2LUDnf473P7yiuYV3TCh +ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC +AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF +BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB +BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg +hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud +EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0VBMSBD +QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cDovL3d3dy5pcHMuZXMvMCkGCWCG +SAGG+EIBAgQcFhpodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyLzA7BglghkgBhvhC +AQQELhYsaHR0cDovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VBMS5j +cmwwQAYJYIZIAYb4QgEDBDMWMWh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcmV2 +b2NhdGlvbkNMQVNFQTEuaHRtbD8wPQYJYIZIAYb4QgEHBDAWLmh0dHA6Ly93d3cu +aXBzLmVzL2lwczIwMDIvcmVuZXdhbENMQVNFQTEuaHRtbD8wOwYJYIZIAYb4QgEI +BC4WLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VBMS5odG1s +MHUGA1UdHwRuMGwwMqAwoC6GLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvaXBz +MjAwMkNMQVNFQTEuY3JsMDagNKAyhjBodHRwOi8vd3d3YmFjay5pcHMuZXMvaXBz +MjAwMi9pcHMyMDAyQ0xBU0VBMS5jcmwwLwYIKwYBBQUHAQEEIzAhMB8GCCsGAQUF +BzABhhNodHRwOi8vb2NzcC5pcHMuZXMvMA0GCSqGSIb3DQEBBQUAA4GBAH66iqyA +AIQVCtWYUQxkxZwCWINmyq0eB81+atqAB98DNEock8RLWCA1NnHtogo1EqWmZaeF +aQoO42Hu6r4okzPV7Oi+xNtff6j5YzHIa5biKcJboOeXNp13XjFr/tOn2yrb25aL +H2betgPAK7N41lUH5Y85UN4HI3LmvSAUS7SG +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIH9zCCB2CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm +SVBTIENBIENMQVNFQTMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT +JklQUyBDQSBDTEFTRUEzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI +hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjI5MDEwNzUwWhcNMjUxMjI3 +MDEwNzUwWjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAO6AAPYaZC6tasiDsYun7o/ZttvN +G7uGBiJ2MwwSbUhWYdLcgiViL5/SaTBlA0IjWLxH3GvWdV0XPOH/8lhneaDBgbHU +VqLyjRGZ/fZ98cfEXgIqmuJKtROKAP2Md4bm15T1IHUuDky/dMQ/gT6DtKM4Ninn +6Cr1jIhBqoCm42zvAgMBAAGjggRTMIIETzAdBgNVHQ4EFgQUHp9XUEe2YZM50yz8 +2l09BXW3mQIwggFGBgNVHSMEggE9MIIBOYAUHp9XUEe2YZM50yz82l09BXW3mQKh +ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC +AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF +BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB +BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg +hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud +EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0VBMyBD +QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cDovL3d3dy5pcHMuZXMvMCkGCWCG +SAGG+EIBAgQcFhpodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyLzA7BglghkgBhvhC +AQQELhYsaHR0cDovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VBMy5j +cmwwQAYJYIZIAYb4QgEDBDMWMWh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcmV2 +b2NhdGlvbkNMQVNFQTMuaHRtbD8wPQYJYIZIAYb4QgEHBDAWLmh0dHA6Ly93d3cu +aXBzLmVzL2lwczIwMDIvcmVuZXdhbENMQVNFQTMuaHRtbD8wOwYJYIZIAYb4QgEI +BC4WLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VBMy5odG1s +MHUGA1UdHwRuMGwwMqAwoC6GLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvaXBz +MjAwMkNMQVNFQTMuY3JsMDagNKAyhjBodHRwOi8vd3d3YmFjay5pcHMuZXMvaXBz +MjAwMi9pcHMyMDAyQ0xBU0VBMy5jcmwwLwYIKwYBBQUHAQEEIzAhMB8GCCsGAQUF +BzABhhNodHRwOi8vb2NzcC5pcHMuZXMvMA0GCSqGSIb3DQEBBQUAA4GBAEo9IEca +2on0eisxeewBwMwB9dbB/MjD81ACUZBYKp/nNQlbMAqBACVHr9QPDp5gJqiVp4MI +3y2s6Q73nMify5NF8bpqxmdRSmlPa/59Cy9SKcJQrSRE7SOzSMtEQMEDlQwKeAYS +AfWRMS1Jjbs/RU4s4OjNtckUFQzjB4ObJnXv +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICtzCCAiACAQAwDQYJKoZIhvcNAQEEBQAwgaMxCzAJBgNVBAYTAkVTMRIwEAYD +VQQIEwlCQVJDRUxPTkExEjAQBgNVBAcTCUJBUkNFTE9OQTEZMBcGA1UEChMQSVBT +IFNlZ3VyaWRhZCBDQTEYMBYGA1UECxMPQ2VydGlmaWNhY2lvbmVzMRcwFQYDVQQD +Ew5JUFMgU0VSVklET1JFUzEeMBwGCSqGSIb3DQEJARYPaXBzQG1haWwuaXBzLmVz +MB4XDTk4MDEwMTIzMjEwN1oXDTA5MTIyOTIzMjEwN1owgaMxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCQVJDRUxPTkExEjAQBgNVBAcTCUJBUkNFTE9OQTEZMBcGA1UE +ChMQSVBTIFNlZ3VyaWRhZCBDQTEYMBYGA1UECxMPQ2VydGlmaWNhY2lvbmVzMRcw +FQYDVQQDEw5JUFMgU0VSVklET1JFUzEeMBwGCSqGSIb3DQEJARYPaXBzQG1haWwu +aXBzLmVzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsT1J0nznqjtwlxLyY +XZhkJAk8IbPMGbWOlI6H0fg3PqHILVikgDVboXVsHUUMH2Fjal5vmwpMwci4YSM1 +gf/+rHhwLWjhOgeYlQJU3c0jt4BT18g3RXIGJBK6E2Ehim51KODFDzT9NthFf+G4 +Nu+z4cYgjui0OLzhPvYR3oydAQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBACzzw3lY +JN7GO9HgQmm47mSzPWIBubOE3yN93ZjPEKn+ANgilgUTB1RXxafey9m4iEL2mdsU +dx+2/iU94aI+A6mB0i1sR/WWRowiq8jMDQ6XXotBtDvECgZAHd1G9AHduoIuPD14 +cJ58GNCr+Lh3B0Zx8coLY1xq+XKU1QFPoNtC +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIIODCCB6GgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCAR4xCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjE0MDIGA1UECxMr +SVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE0MDIG +A1UEAxMrSVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eTEeMBwGCSqGSIb3DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIyOTAxMTAx +OFoXDTI1MTIyNzAxMTAxOFowggEeMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFy +Y2Vsb25hMRIwEAYDVQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5l +dCBwdWJsaXNoaW5nIFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlw +cy5lcyBDLkkuRi4gIEItNjA5Mjk0NTIxNDAyBgNVBAsTK0lQUyBDQSBUaW1lc3Rh +bXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxNDAyBgNVBAMTK0lQUyBDQSBU +aW1lc3RhbXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHjAcBgkqhkiG9w0B +CQEWD2lwc0BtYWlsLmlwcy5lczCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA +vLjuVqWajOY2ycJioGaBjRrVetJznw6EZLqVtJCneK/K/lRhW86yIFcBrkSSQxA4 +Efdo/BdApWgnMjvEp+ZCccWZ73b/K5Uk9UmSGGjKALWkWi9uy9YbLA1UZ2t6KaFY +q6JaANZbuxjC3/YeE1Z2m6Vo4pjOxgOKNNtMg0GmqaMCAwEAAaOCBIAwggR8MB0G +A1UdDgQWBBSL0BBQCYHynQnVDmB4AyKiP8jKZjCCAVAGA1UdIwSCAUcwggFDgBSL +0BBQCYHynQnVDmB4AyKiP8jKZqGCASakggEiMIIBHjELMAkGA1UEBhMCRVMxEjAQ +BgNVBAgTCUJhcmNlbG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJ +UFMgSW50ZXJuZXQgcHVibGlzaGluZyBTZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJp +cHNAbWFpbC5pcHMuZXMgQy5JLkYuICBCLTYwOTI5NDUyMTQwMgYDVQQLEytJUFMg +Q0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTQwMgYDVQQD +EytJUFMgQ0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4w +HAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYDVR0TBAUwAwEB/zAM +BgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYB +BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIB +FgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAAcwGgYD +VR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGBD2lwc0BtYWlsLmlw +cy5lczBHBglghkgBhvhCAQ0EOhY4VGltZXN0YW1waW5nIENBIENlcnRpZmljYXRl +IGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgECBBwWGmh0 +dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMEAGCWCGSAGG+EIBBAQzFjFodHRwOi8v +d3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJUaW1lc3RhbXBpbmcuY3JsMEUGCWCG +SAGG+EIBAwQ4FjZodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3Jldm9jYXRpb25U +aW1lc3RhbXBpbmcuaHRtbD8wQgYJYIZIAYb4QgEHBDUWM2h0dHA6Ly93d3cuaXBz +LmVzL2lwczIwMDIvcmVuZXdhbFRpbWVzdGFtcGluZy5odG1sPzBABglghkgBhvhC +AQgEMxYxaHR0cDovL3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lUaW1lc3RhbXBp +bmcuaHRtbDB/BgNVHR8EeDB2MDegNaAzhjFodHRwOi8vd3d3Lmlwcy5lcy9pcHMy +MDAyL2lwczIwMDJUaW1lc3RhbXBpbmcuY3JsMDugOaA3hjVodHRwOi8vd3d3YmFj +ay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyVGltZXN0YW1waW5nLmNybDAvBggrBgEF +BQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5lcy8wDQYJKoZI +hvcNAQEFBQADgYEAZbrBzAAalZHK6Ww6vzoeFAh8+4Pua2JR0zORtWB5fgTYXXk3 +6MNbsMRnLWhasl8OCvrNPzpFoeo2zyYepxEoxZSPhExTCMWTs/zif/WN87GphV+I +3pGW7hdbrqXqcGV4LCFkAZXOzkw+UPS2Wctjjba9GNSHSl/c7+lW8AoM6HU= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUx +ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 +b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQD +EylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikgVGFudXNpdHZhbnlraWFkbzAeFw05 +OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYDVQQGEwJIVTERMA8G +A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh +Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5l +dExvY2sgVXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xK +gZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX +iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvc +Q7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8E +BAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1G +SUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFu +b3MgU3pvbGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBh +bGFwamFuIGtlc3p1bHQuIEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExv +Y2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGln +aXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0 +IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh +c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGph +biBhIGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJo +ZXRvIGF6IGVsbGVub3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBP +UlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmlj +YXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBo +dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNA +bmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06 +sPgzTEdM43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXa +n3BukxowOR0w2y7jfLKRstE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKS +NitjrFgBazMpUIaD8QFI +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUx +ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 +b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQD +EytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBDKSBUYW51c2l0dmFueWtpYWRvMB4X +DTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJBgNVBAYTAkhVMREw +DwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9u +c2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMr +TmV0TG9jayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNA +OoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3ZW3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC +2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63euyucYT2BDMIJTLrdKwW +RMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQwDgYDVR0P +AQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEW +ggJNRklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0 +YWxhbm9zIFN6b2xnYWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFz +b2sgYWxhcGphbiBrZXN6dWx0LiBBIGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBO +ZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1iaXp0b3NpdGFzYSB2ZWRpLiBB +IGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0ZWxlIGF6IGVs +b2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs +ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25s +YXBqYW4gYSBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kg +a2VyaGV0byBheiBlbGxlbm9yemVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4g +SU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5kIHRoZSB1c2Ugb2YgdGhpcyBjZXJ0 +aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQUyBhdmFpbGFibGUg +YXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwgYXQg +Y3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmY +ta3UzbM2xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2g +pO0u9f38vf5NNwgMvOOWgyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4 +Fp1hBWeAyNDYpQcCNJgEjTME1A== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhV +MRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMe +TmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0 +dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFzcyBB +KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oXDTE5MDIxOTIzMTQ0 +N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhC +dWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQu +MRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBL +b3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeLVu0ThEDaiD +zl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX9EUi +3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8 +WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LY +Oph7tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2Esi +NCubMvJIH5+hCoR64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCC +ApswDgYDVR0PAQH/BAQDAgAGMBIGA1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4 +QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZRUxFTSEgRXplbiB0 +YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRhdGFz +aSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu +IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtm +ZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMg +ZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVs +amFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJhc2EgbWVndGFsYWxoYXRv +IGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBzOi8vd3d3 +Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6 +ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1 +YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3Qg +dG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRs +b2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNAbmV0bG9jay5uZXQuMA0G +CSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5ayZrU3/b39/zcT0mwBQO +xmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjPytoUMaFP +0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQ +QeJBCWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxk +f1qbFFgBJ34TUMdrKuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK +8CtmdWOMovsEPoMOmzbwGOQmIMOM8CgHrTwXZoi1/baI +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIG0TCCBbmgAwIBAgIBezANBgkqhkiG9w0BAQUFADCByTELMAkGA1UEBhMCSFUx +ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 +b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMUIwQAYDVQQD +EzlOZXRMb2NrIE1pbm9zaXRldHQgS296amVneXpvaSAoQ2xhc3MgUUEpIFRhbnVz +aXR2YW55a2lhZG8xHjAcBgkqhkiG9w0BCQEWD2luZm9AbmV0bG9jay5odTAeFw0w +MzAzMzAwMTQ3MTFaFw0yMjEyMTUwMTQ3MTFaMIHJMQswCQYDVQQGEwJIVTERMA8G +A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh +Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxQjBABgNVBAMTOU5l +dExvY2sgTWlub3NpdGV0dCBLb3pqZWd5em9pIChDbGFzcyBRQSkgVGFudXNpdHZh +bnlraWFkbzEeMBwGCSqGSIb3DQEJARYPaW5mb0BuZXRsb2NrLmh1MIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx1Ilstg91IRVCacbvWy5FPSKAtt2/Goq +eKvld/Bu4IwjZ9ulZJm53QE+b+8tmjwi8F3JV6BVQX/yQ15YglMxZc4e8ia6AFQe +r7C8HORSjKAyr7c3sVNnaHRnUPYtLmTeriZ539+Zhqurf4XsoPuAzPS4DB6TRWO5 +3Lhbm+1bOdRfYrCnjnxmOCyqsQhjF2d9zL2z8cM/z1A57dEZgxXbhxInlrfa6uWd +vLrqOU+L73Sa58XQ0uqGURzk/mQIKAR5BevKxXEOC++r6uwSEaEYBTJp0QwsGj0l +mT+1fMptsK6ZmfoIYOcZwvK9UdPM0wKswREMgM6r3JSda6M5UzrWhQIDAMV9o4IC +wDCCArwwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8EBAMCAQYwggJ1Bglg +hkgBhvhCAQ0EggJmFoICYkZJR1lFTEVNISBFemVuIHRhbnVzaXR2YW55IGEgTmV0 +TG9jayBLZnQuIE1pbm9zaXRldHQgU3pvbGdhbHRhdGFzaSBTemFiYWx5emF0YWJh +biBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBBIG1pbm9zaXRldHQg +ZWxla3Ryb25pa3VzIGFsYWlyYXMgam9naGF0YXMgZXJ2ZW55ZXN1bGVzZW5laywg +dmFsYW1pbnQgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYSBNaW5vc2l0ZXR0IFN6 +b2xnYWx0YXRhc2kgU3phYmFseXphdGJhbiwgYXogQWx0YWxhbm9zIFN6ZXJ6b2Rl +c2kgRmVsdGV0ZWxla2JlbiBlbG9pcnQgZWxsZW5vcnplc2kgZWxqYXJhcyBtZWd0 +ZXRlbGUuIEEgZG9rdW1lbnR1bW9rIG1lZ3RhbGFsaGF0b2sgYSBodHRwczovL3d3 +dy5uZXRsb2NrLmh1L2RvY3MvIGNpbWVuIHZhZ3kga2VyaGV0b2sgYXogaW5mb0Bu +ZXRsb2NrLm5ldCBlLW1haWwgY2ltZW4uIFdBUk5JTkchIFRoZSBpc3N1YW5jZSBh +bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGFyZSBzdWJqZWN0IHRvIHRo +ZSBOZXRMb2NrIFF1YWxpZmllZCBDUFMgYXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3 +Lm5ldGxvY2suaHUvZG9jcy8gb3IgYnkgZS1tYWlsIGF0IGluZm9AbmV0bG9jay5u +ZXQwHQYDVR0OBBYEFAlqYhaSsFq7VQ7LdTI6MuWyIckoMA0GCSqGSIb3DQEBBQUA +A4IBAQCRalCc23iBmz+LQuM7/KbD7kPgz/PigDVJRXYC4uMvBcXxKufAQTPGtpvQ +MznNwNuhrWw3AkxYQTvyl5LGSKjN5Yo5iWH5Upfpvfb5lHTocQ68d4bDBsxafEp+ +NFAwLvt/MpqNPfMgW/hqyobzMUwsWYACff44yTB1HLdV47yfuqhthCgFdbOLDcCR +VCHnpgu0mfVRQdzNo0ci2ccBgcTcR08m6h/t280NmPSjnLRzMkqWmf68f8glWPhY +83ZmiVSkpj7EUFy6iRiCdUgh0k8T6GB+B3bbELVR5qq5aKrN9p2QdRLqOBrKROi3 +macqaJVmlaut74nLYKkGEsaUR+ko +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi +MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV +UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO +ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz +c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP +OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl +mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF +BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 +qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw +gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu +bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp +dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 +6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ +h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH +/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN +pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa +GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg +Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J +WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB +rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp ++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 +ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i +Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz +PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og +/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH +oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI +yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud +EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 +A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL +MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f +BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn +g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl +fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K +WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha +B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc +hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR +TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD +mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z +ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y +4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza +8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM +V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB +4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr +H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd +8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv +vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT +mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe +btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc +T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt +WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ +c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A +4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD +VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG +CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 +aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu +dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw +czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G +A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg +Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 +7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem +d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd ++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B +4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN +t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x +DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 +k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s +zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j +Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT +mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK +4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz +MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw +IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR +dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp +li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D +rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ +WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug +F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU +xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC +Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv +dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw +ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl +IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh +c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy +ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI +KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T +KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq +y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p +dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD +VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL +MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk +fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 +7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R +cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y +mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW +xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK +SnQ2+Q== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy +NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD +cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs +2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY +JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE +Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ +n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A +PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICXDCCAcWgAwIBAgIQCgEBAQAAAnwAAAALAAAAAjANBgkqhkiG9w0BAQUFADA6 +MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp +dHkgMTAyNCBWMzAeFw0wMTAyMjIyMTAxNDlaFw0yNjAyMjIyMDAxNDlaMDoxGTAX +BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAx +MDI0IFYzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDV3f5mCc8kPD6ugU5O +isRpgFtZO9+5TUzKtS3DJy08rwBCbbwoppbPf9dYrIMKo1W1exeQFYRMiu4mmdxY +78c4pqqv0I5CyGLXq6yp+0p9v+r+Ek3d/yYtbzZUaMjShFbuklNhCbM/OZuoyZu9 +zp9+1BlqFikYvtc6adwlWzMaUQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBTEwBykB5T9zU0B1FTapQxf3q4FWjAd +BgNVHQ4EFgQUxMAcpAeU/c1NAdRU2qUMX96uBVowDQYJKoZIhvcNAQEFBQADgYEA +Py1q4yZDlX2Jl2X7deRyHUZXxGFraZ8SmyzVWujAovBDleMf6XbN3Ou8k6BlCsdN +T1+nr6JGFLkM88y9am63nd4lQtBU/55oc2PcJOsiv6hy8l4A4Q1OOkNumU4/iXgD +mMrzVcydro7BqkWY+o8aoI2II/EVQQ2lRj6RP4vr93E= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6 +MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp +dHkgMjA0OCBWMzAeFw0wMTAyMjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAX +BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAy +MDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt49VcdKA3Xtp +eafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7Jylg +/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGl +wSMiuLgbWhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnh +AMFRD0xS+ARaqn1y07iHKrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2 +PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpu +AWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4EFgQUB8NR +MKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYc +HnmYv/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/ +Zb5gEydxiKRz44Rj0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+ +f00/FGj1EVDVwfSQpQgdMWD/YIwjVAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVO +rSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395nzIlQnQFgCi/vcEkllgVsRch +6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kApKnXwiJPZ9d3 +7CAFYd4= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx +MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg +Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ +iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa +/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ +jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI +HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 +sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w +gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw +KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG +AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L +URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO +H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm +I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY +iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz +MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv +cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz +Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO +0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao +wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj +7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS +8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT +BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg +JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 +6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ +3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm +D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS +CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY +MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t +dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 +WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD +VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 +9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ +DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 +Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N +QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ +xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G +A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG +kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr +Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 +Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU +JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot +RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBJDANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP +MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MxIENBMB4XDTAx +MDQwNjEwNDkxM1oXDTIxMDQwNjEwNDkxM1owOTELMAkGA1UEBhMCRkkxDzANBgNV +BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMSBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBALWJHytPZwp5/8Ue+H887dF+2rDNbS82rDTG +29lkFwhjMDMiikzujrsPDUJVyZ0upe/3p4zDq7mXy47vPxVnqIJyY1MPQYx9EJUk +oVqlBvqSV536pQHydekfvFYmUk54GWVYVQNYwBSujHxVX3BbdyMGNpfzJLWaRpXk +3w0LBUXl0fIdgrvGE+D+qnr9aTCU89JFhfzyMlsy3uhsXR/LpCJ0sICOXZT3BgBL +qdReLjVQCfOAl/QMF6452F/NM8EcyonCIvdFEu1eEpOdY6uCLrnrQkFEy0oaAIIN +nvmLVz5MxxftLItyM19yejhW1ebZrgUaHXVFsculJRwSVzb9IjcCAwEAAaMzMDEw +DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQIR+IMi/ZTiFIwCwYDVR0PBAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQCLGrLJXWG04bkruVPRsoWdd44W7hE928Jj2VuX +ZfsSZ9gqXLar5V7DtxYvyOirHYr9qxp81V9jz9yw3Xe5qObSIjiHBxTZ/75Wtf0H +DjxVyhbMp6Z3N/vbXB9OWQaHowND9Rart4S9Tu+fMTfwRvFAttEMpWT4Y14h21VO +TzF2nBBhjrZTOqMRvq9tfB69ri3iDGnHhVNoomG6xT60eVR4ngrHAr5i0RGCS2Uv +kVrCqIexVmiUefkl98HVrhq4uz2PqYo4Ffdz0Fpg0YCw8NzVUM1O7pJIae2yIx4w +zMiUyLb1O4Z/P6Yun/Y+LLWSlj7fLJOK/4GMDw9ZIRlXvVWa +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP +MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx +MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV +BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o +Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt +5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s +3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej +vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu +8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw +DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil +zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ +3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD +FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 +Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 +ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJO +TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEy +MTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVk +ZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxhbmRlbiBSb290IENB +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFtvszn +ExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw71 +9tV2U02PjLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MO +hXeiD+EwR+4A5zN9RGcaC1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+U +tFE5A3+y3qcym7RHjm+0Sq7lr7HcsBthvJly3uSJt3omXdozSVtSnA71iq3DuD3o +BmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn622r+I/q85Ej0ZytqERAh +SQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRVHSAAMDww +OgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMv +cm9vdC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA +7Jbg0zTBLL9s+DANBgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k +/rvuFbQvBgwp8qiSpGEN/KtcCFtREytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzm +eafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbwMVcoEoJz6TMvplW0C5GUR5z6 +u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3ynGQI0DvDKcWy +7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR +iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl +MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp +U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw +NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE +ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp +ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 +DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf +8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN ++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 +X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa +K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA +1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G +A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR +zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 +YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD +bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 +L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D +eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp +VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY +WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW +MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg +Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 +MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi +U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh +cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk +pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf +OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C +Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT +Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi +HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM +Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w ++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ +Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 +Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B +26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID +AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE +FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j +ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js +LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM +BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 +Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy +dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh +cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh +YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg +dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp +bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ +YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT +TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ +9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 +jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW +FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz +ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 +ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L +EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu +L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq +yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC +O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V +um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh +NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFFjCCBH+gAwIBAgIBADANBgkqhkiG9w0BAQQFADCBsDELMAkGA1UEBhMCSUwx +DzANBgNVBAgTBklzcmFlbDEOMAwGA1UEBxMFRWlsYXQxFjAUBgNVBAoTDVN0YXJ0 +Q29tIEx0ZC4xGjAYBgNVBAsTEUNBIEF1dGhvcml0eSBEZXAuMSkwJwYDVQQDEyBG +cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJARYS +YWRtaW5Ac3RhcnRjb20ub3JnMB4XDTA1MDMxNzE3Mzc0OFoXDTM1MDMxMDE3Mzc0 +OFowgbAxCzAJBgNVBAYTAklMMQ8wDQYDVQQIEwZJc3JhZWwxDjAMBgNVBAcTBUVp +bGF0MRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMRowGAYDVQQLExFDQSBBdXRob3Jp +dHkgRGVwLjEpMCcGA1UEAxMgRnJlZSBTU0wgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkxITAfBgkqhkiG9w0BCQEWEmFkbWluQHN0YXJ0Y29tLm9yZzCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEA7YRgACOeyEpRKSfeOqE5tWmrCbIvNP1h3D3TsM+x +18LEwrHkllbEvqoUDufMOlDIOmKdw6OsWXuO7lUaHEe+o5c5s7XvIywI6Nivcy+5 +yYPo7QAPyHWlLzRMGOh2iCNJitu27Wjaw7ViKUylS7eYtAkUEKD4/mJ2IhULpNYI +LzUCAwEAAaOCAjwwggI4MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgHmMB0G +A1UdDgQWBBQcicOWzL3+MtUNjIExtpidjShkjTCB3QYDVR0jBIHVMIHSgBQcicOW +zL3+MtUNjIExtpidjShkjaGBtqSBszCBsDELMAkGA1UEBhMCSUwxDzANBgNVBAgT +BklzcmFlbDEOMAwGA1UEBxMFRWlsYXQxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4x +GjAYBgNVBAsTEUNBIEF1dGhvcml0eSBEZXAuMSkwJwYDVQQDEyBGcmVlIFNTTCBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJARYSYWRtaW5Ac3Rh +cnRjb20ub3JnggEAMB0GA1UdEQQWMBSBEmFkbWluQHN0YXJ0Y29tLm9yZzAdBgNV +HRIEFjAUgRJhZG1pbkBzdGFydGNvbS5vcmcwEQYJYIZIAYb4QgEBBAQDAgAHMC8G +CWCGSAGG+EIBDQQiFiBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAy +BglghkgBhvhCAQQEJRYjaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL2NhLWNybC5j +cmwwKAYJYIZIAYb4QgECBBsWGWh0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy8wOQYJ +YIZIAYb4QgEIBCwWKmh0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9pbmRleC5waHA/ +YXBwPTExMTANBgkqhkiG9w0BAQQFAAOBgQBscSXhnjSRIe/bbL0BCFaPiNhBOlP1 +ct8nV0t2hPdopP7rPwl+KLhX6h/BquL/lp9JmeaylXOWxkjHXo0Hclb4g4+fd68p +00UOpO6wNnQt8M2YI3s3S9r+UZjEHjQ8iP2ZO1CnwYszx8JSFhKVU2Ui77qLzmLb +cCOxgN8aIDjnfg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBk +MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 +YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg +Q0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4MTgyMjA2MjBaMGQxCzAJBgNVBAYT +AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp +Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9 +m2BtRsiMMW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdih +FvkcxC7mlSpnzNApbjyFNDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/ +TilftKaNXXsLmREDA/7n29uj/x2lzZAeAR81sH8A25Bvxn570e56eqeqDFdvpG3F +EzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkCb6dJtDZd0KTeByy2dbco +kdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn7uHbHaBu +HYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNF +vJbNcA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo +19AOeCMgkckkKmUpWyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjC +L3UcPX7ape8eYIVpQtPM+GP+HkM5haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJW +bjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNYMUJDLXT5xp6mig/p/r+D5kNX +JLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw +FDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j +BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzc +K6FptWfUjNP9MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzf +ky9NfEBWMXrrpA9gzXrzvsMnjgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7Ik +Vh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQMbFamIp1TpBcahQq4FJHgmDmHtqB +sfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4HVtA4oJVwIHaM190e +3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtlvrsR +ls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ip +mXeascClOS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HH +b6D0jqTsNFFbjCYDcKF31QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksf +rK/7DZBaZmBwXarNeNQk7shBoJMBkpxqnvy5JMWzFYJ+vq6VK+uxwNrjAWALXmms +hFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCyx/yP2FS1k2Kdzs9Z+z0Y +zirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMWNY6E0F/6 +MBr1mmz0DlP5OlvRHA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV +BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln +biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF +MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT +d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 +76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ +bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c +6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE +emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd +MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt +MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y +MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y +FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi +aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM +gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB +qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 +lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn +8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov +L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 +45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO +UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 +O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC +bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv +GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a +77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC +hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 +92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp +Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w +ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt +Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFwTCCA6mgAwIBAgIITrIAZwwDXU8wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE +BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEjMCEGA1UEAxMaU3dpc3NTaWdu +IFBsYXRpbnVtIENBIC0gRzIwHhcNMDYxMDI1MDgzNjAwWhcNMzYxMDI1MDgzNjAw +WjBJMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMSMwIQYDVQQD +ExpTd2lzc1NpZ24gUGxhdGludW0gQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAMrfogLi2vj8Bxax3mCq3pZcZB/HL37PZ/pEQtZ2Y5Wu669y +IIpFR4ZieIbWIDkm9K6j/SPnpZy1IiEZtzeTIsBQnIJ71NUERFzLtMKfkr4k2Htn +IuJpX+UFeNSH2XFwMyVTtIc7KZAoNppVRDBopIOXfw0enHb/FZ1glwCNioUD7IC+ +6ixuEFGSzH7VozPY1kneWCqv9hbrS3uQMpe5up1Y8fhXSQQeol0GcN1x2/ndi5ob +jM89o03Oy3z2u5yg+gnOI2Ky6Q0f4nIoj5+saCB9bzuohTEJfwvH6GXp43gOCWcw +izSC+13gzJ2BbWLuCB4ELE6b7P6pT1/9aXjvCR+htL/68++QHkwFix7qepF6w9fl ++zC8bBsQWJj3Gl/QKTIDE0ZNYWqFTFJ0LwYfexHihJfGmfNtf9dng34TaNhxKFrY +zt3oEBSa/m0jh26OWnA81Y0JAKeqvLAxN23IhBQeW71FYyBrS3SMvds6DsHPWhaP +pZjydomyExI7C3d3rLvlPClKknLKYRorXkzig3R3+jVIeoVNjZpTxN94ypeRSCtF +KwH3HBqi7Ri6Cr2D+m+8jVeTO9TUps4e8aCxzqv9KyiaTxvXw3LbpMS/XUz13XuW +ae5ogObnmLo2t/5u7Su9IPhlGdpVCX4l3P5hYnL5fhgC72O00Puv5TtjjGePAgMB +AAGjgawwgakwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFFCvzAeHFUdvOMW0ZdHelarp35zMMB8GA1UdIwQYMBaAFFCvzAeHFUdvOMW0 +ZdHelarp35zMMEYGA1UdIAQ/MD0wOwYJYIV0AVkBAQEBMC4wLAYIKwYBBQUHAgEW +IGh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5jb20vMA0GCSqGSIb3DQEBBQUA +A4ICAQAIhab1Fgz8RBrBY+D5VUYI/HAcQiiWjrfFwUF1TglxeeVtlspLpYhg0DB0 +uMoI3LQwnkAHFmtllXcBrqS3NQuB2nEVqXQXOHtYyvkv+8Bldo1bAbl93oI9ZLi+ +FHSjClTTLJUYFzX1UWs/j6KWYTl4a0vlpqD4U99REJNi54Av4tHgvI42Rncz7Lj7 +jposiU0xEQ8mngS7twSNC/K5/FqdOxa3L8iYq/6KUFkuozv8KV2LwUvJ4ooTHbG/ +u0IdUt1O2BReEMYxB+9xJ/cbOQncguqLs5WGXv312l0xpuAxtpTmREl0xRbl9x8D +YSjFyMsSoEJL+WuICI20MhjzdZ/EfwBPBZWcoxcCw7NTm6ogOSkrZvqdr16zktK1 +puEa+S1BaYEUtLS17Yk9zvupnTVCRLEcFHOBzyoBNZox1S2PbYTfgE1X4z/FhHXa +icYwu+uPyyIIoK6q8QNsOktNCaUOcsZWayFCTiMlFGiudgp8DAdwZPmaL/YFOSbG +DI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSYMdp08YSTcU1f+2BY0fvEwW2JorsgH51x +kcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAciIfNAChs0B0QTwoRqjt8Z +Wr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE +BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu +IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow +RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY +U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv +Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br +YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF +nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH +6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt +eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/ +c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ +MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH +HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf +jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6 +5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB +rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU +F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c +wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 +cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB +AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp +WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9 +xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ +2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ +IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8 +aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X +em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR +dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/ +OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+ +hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy +tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/ +MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow +PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR +IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q +gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy +yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts +F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2 +jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx +ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC +VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK +YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH +EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN +Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud +DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE +MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK +UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ +TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf +qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK +ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE +JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7 +hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1 +EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm +nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX +udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz +ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe +LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl +pYYsfPQS +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDXDCCAsWgAwIBAgICA+owDQYJKoZIhvcNAQEEBQAwgbwxCzAJBgNVBAYTAkRF +MRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFU +QyBUcnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJI +MSIwIAYDVQQLExlUQyBUcnVzdENlbnRlciBDbGFzcyAyIENBMSkwJwYJKoZIhvcN +AQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAeFw05ODAzMDkxMTU5NTla +Fw0xMTAxMDExMTU5NTlaMIG8MQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFtYnVy +ZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UEChMxVEMgVHJ1c3RDZW50ZXIgZm9y +IFNlY3VyaXR5IGluIERhdGEgTmV0d29ya3MgR21iSDEiMCAGA1UECxMZVEMgVHJ1 +c3RDZW50ZXIgQ2xhc3MgMiBDQTEpMCcGCSqGSIb3DQEJARYaY2VydGlmaWNhdGVA +dHJ1c3RjZW50ZXIuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANo46O0y +AClxgwENv4wB3NrGrTmkqYov1YtcaF9QxmL1Zr3KkSLsqh1R1z2zUbKDTl3LSbDw +TFXlay3HhQswHJJOgtTKAu33b77c4OMUuAVT8pr0VotanoWT0bSCVq5Nu6hLVxa8 +/vhYnvgpjbB7zXjJT6yLZwzxnPv8V5tXXE8NAgMBAAGjazBpMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgGGMDMGCWCGSAGG+EIBCAQmFiRodHRwOi8vd3d3 +LnRydXN0Y2VudGVyLmRlL2d1aWRlbGluZXMwEQYJYIZIAYb4QgEBBAQDAgAHMA0G +CSqGSIb3DQEBBAUAA4GBAIRS+yjf/x91AbwBvgRWl2p0QiQxg/lGsQaKic+WLDO/ +jLVfenKhhQbOhvgFjuj5Jcrag4wGrOs2bYWRNAQ29ELw+HkuCkhcq8xRT3h2oNms +Gb0q0WkEKJHKNhAngFdb0lz1wlurZIFjdFH0l7/NEij3TWZ/p/AcASZ4smZHcFFk +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDXDCCAsWgAwIBAgICA+swDQYJKoZIhvcNAQEEBQAwgbwxCzAJBgNVBAYTAkRF +MRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFU +QyBUcnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJI +MSIwIAYDVQQLExlUQyBUcnVzdENlbnRlciBDbGFzcyAzIENBMSkwJwYJKoZIhvcN +AQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAeFw05ODAzMDkxMTU5NTla +Fw0xMTAxMDExMTU5NTlaMIG8MQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFtYnVy +ZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UEChMxVEMgVHJ1c3RDZW50ZXIgZm9y +IFNlY3VyaXR5IGluIERhdGEgTmV0d29ya3MgR21iSDEiMCAGA1UECxMZVEMgVHJ1 +c3RDZW50ZXIgQ2xhc3MgMyBDQTEpMCcGCSqGSIb3DQEJARYaY2VydGlmaWNhdGVA +dHJ1c3RjZW50ZXIuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALa0wTUF +Lg2N7KBAahwOJ6ZQkmtQGwfeLud2zODa/ISoXoxjaitN2U4CdhHBC/KNecoAtvGw +Dtf7pBc9r6tpepYnv68zoZoqWarEtTcI8hKlMbZD9TKWcSgoq40oht+77uMMfTDW +w1Krj10nnGvAo+cFa1dJRLNu6mTP0o56UHd3AgMBAAGjazBpMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgGGMDMGCWCGSAGG+EIBCAQmFiRodHRwOi8vd3d3 +LnRydXN0Y2VudGVyLmRlL2d1aWRlbGluZXMwEQYJYIZIAYb4QgEBBAQDAgAHMA0G +CSqGSIb3DQEBBAUAA4GBABY9xs3Bu4VxhUafPiCPUSiZ7C1FIWMjWwS7TJC4iJIE +Tb19AaM/9uzO8d7+feXhPrvGq14L3T2WxMup1Pkm5gZOngylerpuw3yCGdHHsbHD +2w2Om0B8NwvxXej9H5CIpQ5ON2QhqE6NtJ/x3kit1VYYUimLRzQSCdS7kjXvD9s0 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJE +SzEVMBMGA1UEChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQg +Um9vdCBDQTAeFw0wMTA0MDUxNjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNV +BAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJuZXQxHTAbBgNVBAsTFFREQyBJbnRl +cm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxLhA +vJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20jxsNu +Zp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a +0vnRrEvLznWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc1 +4izbSysseLlJ28TQx5yc5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGN +eGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcD +R0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZIAYb4QgEBBAQDAgAHMGUG +A1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMMVERDIElu +dGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxME +Q1JMMTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3 +WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAw +HQYDVR0OBBYEFGxkAcf9hW2syNqeUAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJ +KoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4IBAQBO +Q8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540mgwV5dOy0uaOX +wTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+ +2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm89 +9qNLPg7kbWzbO0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0 +jUNAE4z9mQNUecYu6oah9jrUCbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38 +aQNiuJkFBT1reBK9sG9l +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJE +SzEMMAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEw +ODM5MzBaFw0zNzAyMTEwOTA5MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNU +REMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuHnEz9pPPEXyG9VhDr +2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0zY0s +2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItU +GBxIYXvViGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKj +dGqPqcNiKXEx5TukYBdedObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+r +TpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO3QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/ +BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB5DCB4TCB3gYIKoFQgSkB +AQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5kay9yZXBv +c2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRl +ciBmcmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEu +MS4xLiBDZXJ0aWZpY2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIg +T0lEIDEuMi4yMDguMTY5LjEuMS4xLjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1Ud +HwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEMMAoGA1UEChMDVERDMRQwEgYD +VQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYmaHR0cDovL2Ny +bC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy +MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZ +J2cdUBVLc647+RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqG +SIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACrom +JkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4A9G28kNBKWKnctj7fAXmMXAnVBhO +inxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYscA+UYyAFMP8uXBV2Y +caaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9AOoB +mbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQ +YqbsFbS1AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9 +BKNDLdr8C2LqL19iUw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDITCCAoqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD +VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT +ZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFBlcnNvbmFsIEJhc2lj +IENBMSgwJgYJKoZIhvcNAQkBFhlwZXJzb25hbC1iYXNpY0B0aGF3dGUuY29tMB4X +DTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgcsxCzAJBgNVBAYTAlpBMRUw +EwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEaMBgGA1UE +ChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy +dmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQZXJzb25hbCBCYXNpYyBD +QTEoMCYGCSqGSIb3DQEJARYZcGVyc29uYWwtYmFzaWNAdGhhd3RlLmNvbTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvLyTU23AUE+CFeZIlDWmWr5vQvoPR+53 +dXLdjUmbllegeNTKP1GzaQuRdhciB5dqxFGTS+CN7zeVoQxN2jSQHReJl+A1OFdK +wPQIcOk8RHtQfmGakOMj04gRRif1CwcOu93RfyAKiLlWCy4cgNrx454p7xS9CkT7 +G1sY0b8jkyECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQF +AAOBgQAt4plrsD16iddZopQBHyvdEktTwq1/qqcAXJFAVyVKOKqEcLnZgA+le1z7 +c8a914phXAPjLSeoF+CEhULcXpvGt7Jtu3Sv5D/Lp7ew4F2+eIMllNLbgQ95B21P +9DkVWlIBe94y1k049hJcBlDfBVu9FEuh3ym6O0GN92NWod8isQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDLTCCApagAwIBAgIBADANBgkqhkiG9w0BAQQFADCB0TELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD +VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT +ZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFsIEZyZWVt +YWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUu +Y29tMB4XDTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgdExCzAJBgNVBAYT +AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEa +MBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRp +b24gU2VydmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBG +cmVlbWFpbCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhh +d3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1GnX1LCUZFtx6UfY +DFG26nKRsIRefS0Nj3sS34UldSh0OkIsYyeflXtL734Zhx2G6qPduc6WZBrCFG5E +rHzmj+hND3EfQDimAKOHePb5lIZererAXnbr2RSjXW56fAylS1V/Bhkpf56aJtVq +uzgkCGqYx7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zAN +BgkqhkiG9w0BAQQFAAOBgQDH7JJ+Tvj1lqVnYiqk8E0RYNBvjWBYYawmu1I1XAjP +MPuoSpaKH2JCI4wXD/S6ZJwXrEcp352YXtJsYHFcoqzceePnbgBHH7UNKOgCneSa +/RP0ptl8sfjcXyMmCZGAc9AUG95DqYMl8uacLxXK/qarigd1iwzdUYRr5PjRznei +gQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBzzELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD +VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT +ZXJ2aWNlcyBEaXZpc2lvbjEjMCEGA1UEAxMaVGhhd3RlIFBlcnNvbmFsIFByZW1p +dW0gQ0ExKjAoBgkqhkiG9w0BCQEWG3BlcnNvbmFsLXByZW1pdW1AdGhhd3RlLmNv +bTAeFw05NjAxMDEwMDAwMDBaFw0yMDEyMzEyMzU5NTlaMIHPMQswCQYDVQQGEwJa +QTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xGjAY +BgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9u +IFNlcnZpY2VzIERpdmlzaW9uMSMwIQYDVQQDExpUaGF3dGUgUGVyc29uYWwgUHJl +bWl1bSBDQTEqMCgGCSqGSIb3DQEJARYbcGVyc29uYWwtcHJlbWl1bUB0aGF3dGUu +Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJZtn4B0TPuYwu8KHvE0Vs +Bd/eJxZRNkERbGw77f4QfRKe5ZtCmv5gMcNmt3M6SK5O0DI3lIi1DbbZ8/JE2dWI +Et12TfIa/G8jHnrx2JhFTgcQ7xZC0EN1bUre4qrJMf8fAHB8Zs8QJQi6+u4A6UYD +ZicRFTuqW/KY3TZCstqIdQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG +SIb3DQEBBAUAA4GBAGk2ifc0KjNyL2071CKyuG+axTZmDhs8obF1Wub9NdP4qPIH +b4Vnjt4rueIXsDqg8A6iAJrf8xQVbrvIhVqYgPn/vnQdPfP+MCXRNzRn+qVxeTBh +KXLA4CxM+1bkOqhv5TJZUtt1KFBZDPgLGeSs2a+WjS9Q2wfD6h+rM+D1KzGJ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD +VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy +dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t +MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB +MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG +A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp +b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl +cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv +bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE +VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ +ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR +uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG +9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI +hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM +pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB +qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw +MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV +BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw +NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j +LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG +A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs +W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta +3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk +6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 +Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J +NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP +r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU +DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz +YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX +xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 +/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ +LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 +jVaMaA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD +VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm +MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx +MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT +DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 +dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl +cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 +DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 +yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX +L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj +EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG +7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e +QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ +qdq5snUb9kLy78fyGPmJvKP/iiMucEc= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICoTCCAgqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBizELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzAN +BgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAd +BgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwHhcNOTcwMTAxMDAwMDAwWhcN +MjAxMjMxMjM1OTU5WjCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4g +Q2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsG +A1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1l +c3RhbXBpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYrWHhhRYZT +6jR7UZztsOYuGA7+4F+oJ9O0yeB8WU4WDnNUYMF/9p8u6TqFJBU820cEY8OexJQa +Wt9MevPZQx08EHp5JduQ/vBR5zDWQQD9nyjfeb6Uu522FOMjhdepQeBMpHmwKxqL +8vg7ij5FrHGSALSQQZj7X+36ty6K+Ig3AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMB +Af8wDQYJKoZIhvcNAQEEBQADgYEAZ9viwuaHPUCDhjc1fR/OmsMMZiCouqoEiYbC +9RAIDb/LogWK0E02PvTX72nGXuSwlG9KuefeW4i2e9vjJ+V2w/A1wcu1J5szedyQ +pgCed/r8zSeUQhac0xxo7L9c3eWpexAKMnRUEzGLhQOEkbdYATAUOK8oyvyxUBkZ +CayJSdM= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOc +UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx +c8SxMQswCQYDVQQGDAJUUjEPMA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykg +MjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8 +dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMxMDI3MTdaFw0xNTAz +MjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2Vy +dGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYD +VQQHDAZBTktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kg +xLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEu +xZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7 +XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GXyGl8hMW0kWxsE2qkVa2k +heiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8iSi9BB35J +YbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5C +urKZ8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1 +JuTm5Rh8i27fbMx4W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51 +b0dewQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV +9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46sWrv7/hg0Uw2ZkUd82YCdAR7 +kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxEq8Sn5RTOPEFh +fEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy +B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdA +aLX/7KfS0zgYnNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKS +RGQDJereW26fyfJOrN3H +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOc +UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx +c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xS +S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg +SGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcNMDUxMTA3MTAwNzU3 +WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVrdHJv +bmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJU +UjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSw +bGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWe +LiAoYykgS2FzxLFtIDIwMDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqeLCDe2JAOCtFp0if7qnef +J1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKIx+XlZEdh +R3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJ +Qv2gQrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGX +JHpsmxcPbe9TmJEr5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1p +zpwACPI2/z7woQ8arBT9pmAPAgMBAAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58S +Fq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/nttRbj2hWyfIvwq +ECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 +Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFz +gw2lGh1uEpJ+hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotH +uFEJjOp9zYhys2AzsfAKRO8P9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LS +y3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5UrbnBEI= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB +kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw +IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD +VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu +dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 +E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ +D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK +4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq +lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW +bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB +o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT +MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js +LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr +BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB +AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft +Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj +j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH +KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv +2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 +mfnGV/TJVTl4uix5yaaIK/QI +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCB +rjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0BgNVBAMTLVVUTi1VU0VSRmlyc3Qt +Q2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05OTA3MDkxNzI4NTBa +Fw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAV +BgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5l +dHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UE +AxMtVVROLVVTRVJGaXJzdC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWls +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3B +YHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIxB8dOtINknS4p1aJkxIW9 +hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8om+rWV6l +L8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLm +SGHGTPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM +1tZUOt4KpLoDd7NlyP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws +6wIDAQABo4G5MIG2MAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNVHR8EUTBPME2gS6BJhkdodHRw +Oi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGllbnRBdXRoZW50 +aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH +AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u +7mFVbwQ+zznexRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0 +xtcgBEXkzYABurorbs6q15L+5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQ +rfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarVNZ1yQAOJujEdxRBoUp7fooXFXAim +eOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZw7JHpsIyYdfHb0gk +USeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB +lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt +SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe +MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v +d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh +cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn +0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ +M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a +MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd +oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI +DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy +oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 +dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy +bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF +BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM +//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli +CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE +CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t +3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS +KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUFADCB +ozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3Qt +TmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0ODM5WhcNMTkwNzA5MTg1 +NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0 +IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYD +VQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VS +Rmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQCz+5Gh5DZVhawGNFugmliy+LUPBXeDrjKxdpJo7CNKyXY/45y2 +N3kDuatpjQclthln5LAbGHNhSuh+zdMvZOOmfAz6F4CjDUeJT1FxL+78P/m4FoCH +iZMlIJpDgmkkdihZNaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXuOzr0hARe +YFmnjDRy7rh4xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1 +axwiP8vv/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6g +yN7igEL66S/ozjIEj3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQD +AgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPqGydvguul49Uuo1hXf8NPh +ahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9V +VE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0GCSqGSIb3DQEB +BQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXhi6r/fWRRzwr/vH3Y +IWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUqf9FuVSTiuwL7MT++6Lzs +QCv4AdRWOOTKRIK1YSAhZ2X28AvnNPilwpyjXEAfhZOVBt5P1CeptqX8Fs1zMT+4 +ZSfP1FMa8Kxun08FDAOBp4QpxFq9ZFdyrTvPNximmMatBrTcCKME1SmklpoSZ0qM +YEWd8SOasACcaLWYUNPvji6SZbFIPiG+FTAqDbUMo2s/rn9X9R+WfN9v3YIwLGUb +QErNaLly7HF27FSOH4UMAWr6pjisH8SE +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy +NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y +LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+ +TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y +TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0 +LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW +I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw +nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy +NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY +dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 +WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS +v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v +UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu +IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC +W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8xCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh +c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05 +NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYD +VQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMSBQdWJsaWMgUHJp +bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOB +jQAwgYkCgYEA5Rm/baNWYS2ZSHH2Z965jeu3noaACpEO+jglr0aIguVzqKCbJF0N +H8xlbgyw0FaEGIeaBpsQoXPftFg5a27B9hXVqKg/qhIGjTGsf7A01480Z4gJzRQR +4k5FVmkfeAKA2txHkSm7NsljXMXg1y2He6G3MrB7MLoqLzGq7qNn2tsCAwEAATAN +BgkqhkiG9w0BAQIFAAOBgQBMP7iLxmjf7kMzDl3ppssHhE16M/+SG/Q2rdiVIjZo +EWx8QszznC7EBz8UsA9P/5CSdvnivErpj82ggAr3xSnxgiJduLHdgSOjeyUVRjB5 +FvjqBUuUfx3CHMjjt/QQQDwTw18fU+hI5Ia0e6E1sHslurjTjqs/OJ0ANACY89Fx +lA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK +VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm +Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0J +h9ZrbWB85a7FkCMMXErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2ul +uIncrKTdcu1OofdPvAbT6shkdHvClUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68 +DzFc6PLZ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4 +nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO +8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV +ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb +PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2 +6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr +n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a +qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4 +wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 +ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs +pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4 +E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEC0b/EoXjaOR6+f/9YtFvgswDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAyIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZMJaLtVRKXxaeAufqDwSCg+i8VDXyh +YGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvEerf4Zh+AVPy3wo5ZShRXRtGak75BkQO7 +FYCTXOvnzAhsPz6zSvz/S2wj1VCCJkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0G +CSqGSIb3DQEBAgUAA4GBAIobK/o5wXTXXtgZZKJYSi034DNHD6zt96rbHuSLBlxg +J8pFUs4W7z8GZOeUaHxgMxURaa+dYo2jA1Rrpr7l7gUYYAS/QoD90KioHgE796Nc +r6Pc5iaAIzy4RHT3Cq5Ji2F4zCS/iIqnDupzGUH9TQPwiNHleI2lKk/2lw0Xd8rY +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns +YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH +MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y +aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe +Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX +MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj +IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx +KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM +HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw +DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC +AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji +nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX +rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn +jBJ7xUS0rg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy +aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s +IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp +Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV +BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp +Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu +Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g +Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt +IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU +J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO +JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY +wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o +koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN +qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E +Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe +xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u +7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU +sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI +sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP +cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE +BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is +I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G +CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do +lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc +AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 +pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 +13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk +U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i +F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY +oJ2daZH9 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b +N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t +KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu +kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm +CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ +Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu +imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te +2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe +DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p +F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt +TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW +ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 +nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex +t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz +SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG +BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ +rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ +NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH +BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv +MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE +p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y +5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK +WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ +4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N +hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRNzjMHPVKmIquNDM +HO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDHqGKB3FtK +qsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwj +cSGIL4LcY/oCRaxFWdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0y +cyfYaT5DdPauxYma51N86Xv2S/PBZYPejYqcPIiNOVn8qj8ijaHBZlCBckztImRP +T8qAkbYp +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 +GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ ++mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd +U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm +NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY +ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ +ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 +CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq +g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm +fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c +2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ +bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICNDCCAaECEAKtZn5ORf5eV288mBle3cAwDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYD +VQQLEyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk0 +MTEwOTAwMDAwMFoXDTEwMDEwNzIzNTk1OVowXzELMAkGA1UEBhMCVVMxIDAeBgNV +BAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2Vy +dmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGbMA0GCSqGSIb3DQEBAQUAA4GJ +ADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6zV4ZFQD5YRAUcm/jwjiioII +0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXATcXY+m3dM41CJVphI +uR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAAEwDQYJKoZI +hvcNAQECBQADfgBl3X7hsuyw4jrg7HFGmhkRuNPHoLQDQCYCPgmc4RKz0Vr2N6W3 +YQO2WxZpO8ZECAyIUwxrl0nHPjXcbLm7qt9cuzovk2C2qUtN8iD3zV9/ZHuO3ABc +1/p3yjkWWW8O6tO1g39NTUJWdrTJXwT4OPjr0l91X817/OWOgHz8UA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDzTCCAzagAwIBAgIQU2GyYK7bcY6nlLMTM/QHCTANBgkqhkiG9w0BAQUFADCB +wTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTwwOgYDVQQL +EzNDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRzIxOjA4BgNVBAsTMShjKSAxOTk4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1 +dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmswHhcNMDAwOTI2MDAwMDAwWhcNMTAwOTI1MjM1OTU5WjCBpTEXMBUGA1UEChMO +VmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsx +OzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5j +b20vcnBhIChjKTAwMSwwKgYDVQQDEyNWZXJpU2lnbiBUaW1lIFN0YW1waW5nIEF1 +dGhvcml0eSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0hmdZ8IAIVli +zrQJIkRpivglWtvtDbc2fk7gu5Q+kCWHwmFHKdm9VLhjzCx9abQzNvQ3B5rB3UBU +/OB4naCTuQk9I1F/RMIUdNsKvsvJMDRAmD7Q1yUQgZS9B0+c1lQn3y6ov8uQjI11 +S7zi6ESHzeZBCiVu6PQkAsVSD27smHUCAwEAAaOB3zCB3DAPBgNVHRMECDAGAQH/ +AgEAMEUGA1UdIAQ+MDwwOgYMYIZIAYb4RQEHFwEDMCowKAYIKwYBBQUHAgEWHGh0 +dHBzOi8vd3d3LnZlcmlzaWduLmNvbS9ycGEwMQYDVR0fBCowKDAmoCSgIoYgaHR0 +cDovL2NybC52ZXJpc2lnbi5jb20vcGNhMy5jcmwwCwYDVR0PBAQDAgEGMEIGCCsG +AQUFBwEBBDYwNDAyBggrBgEFBQcwAaYmFiRodHRwOi8vb2NzcC52ZXJpc2lnbi5j +b20vb2NzcC9zdGF0dXMwDQYJKoZIhvcNAQEFBQADgYEAgnBold+2DcIBcBlK0lRW +HqzyRUyHuPU163hLBanInTsZIS5wNEqi9YngFXVF5yg3ADQnKeg3S/LvRJdrF1Ea +w1adPBqK9kpGRjeM+sv1ZFo4aC4cw+9wzrhGBha/937ntag+RaypJXUie28/sJyU +58dzq6wf7iWbwBbtt8pb8BQ= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr +MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl +cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv +bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw +CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h +dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l +cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h +2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E +lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV +ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq +299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t +vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL +dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF +AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR +zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 +LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd +7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw +++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt +398znM/jra6O1I7mT1GvFpLgXPYHDw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDgDCCAmigAwIBAgICAx4wDQYJKoZIhvcNAQEFBQAwYTELMAkGA1UEBhMCVVMx +DTALBgNVBAoTBFZJU0ExLzAtBgNVBAsTJlZpc2EgSW50ZXJuYXRpb25hbCBTZXJ2 +aWNlIEFzc29jaWF0aW9uMRIwEAYDVQQDEwlHUCBSb290IDIwHhcNMDAwODE2MjI1 +MTAwWhcNMjAwODE1MjM1OTAwWjBhMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklT +QTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRp +b24xEjAQBgNVBAMTCUdQIFJvb3QgMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAKkBcLWqxEDwq2omYXkZAPy/mzdZDK9vZBv42pWUJGkzEXDK41Z0ohdX +ZFwgBuHW73G3O/erwWnQSaSxBNf0V2KJXLB1LRckaeNCYOTudNargFbYiCjh+20i +/SN8RnNPflRzHqgsVVh1t0zzWkWlAhr62p3DRcMiXvOL8WAp0sdftAw6UYPvMPjU +58fy+pmjIlC++QU3o63tmsPm7IgbthknGziLgE3sucfFicv8GjLtI/C1AVj59o/g +halMCXI5Etuz9c9OYmTaxhkVOmMd6RdVoUwiPDQyRvhlV7or7zaMavrZ2UT0qt2E +1w0cslSsMoW0ZA3eQbuxNMYBhjJk1Z8CAwEAAaNCMEAwHQYDVR0OBBYEFJ59SzS/ +ca3CBfYDdYDOqU8axCRMMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQAhpXYUVfmtJ3CPPPTVbMjMCqujmAuKBiPFyWHb +mQdpNSYx/scuhMKZYdQN6X0uEyt8joW2hcdLzzW2LEc9zikv2G+fiRxkk78IvXbQ +kIqUs38oW26sTTMs7WXcFsziza6kPWKSBpUmv9+55CCmc2rBvveURNZNbyoLaxhN +dBA2aGpawWqn3TYpjLgwi08hPwAuVDAHOrqK5MOeyti12HvOdUVmB/RtLdh6yumJ +ivIj2C/LbgA2T/vwLwHMD8AiZfSr4k5hLQOCfZEWtTDVFN5ex5D8ofyrEK9ca3Cn +B+8phuiyJccg/ybdd+95RBTEvd07xQObdyPsoOy7Wjm1zK0G +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9v +dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDAxMDExMTY0MTI4WhcNMjEwMTE0 +MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSww +KgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0G +A1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n13 +5zHCLielTWi5MbqNQ1mXx3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHE +SxP9cMIlrCL1dQu3U+SlK93OvRw6esP3E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4O +JgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5OEL8pahbSCOz6+MlsoCu +ltQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4jsNtlAHCE +AQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMB +AAGjYTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcB +CzAyMDAGCCsGAQUFBwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRw +b2xpY3kwDQYJKoZIhvcNAQEFBQADggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo +7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrvm+0fazbuSCUlFLZWohDo7qd/ +0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0ROhPs7fpvcmR7 +nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx +x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ +33ZwmVxwQ023tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMx +IDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxs +cyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9v +dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcxMjEzMTcwNzU0WhcNMjIxMjE0 +MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdl +bGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQD +DC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+r +WxxTkqxtnt3CxC5FlAM1iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjU +Dk/41itMpBb570OYj7OeUt9tkTmPOL13i0Nj67eT/DBMHAGTthP796EfvyXhdDcs +HqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8bJVhHlfXBIEyg1J55oNj +z7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiBK0HmOFaf +SZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/Slwxl +AgMBAAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqG +KGh0dHA6Ly9jcmwucGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0P +AQH/BAQDAgHGMB0GA1UdDgQWBBQmlRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0j +BIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGBi6SBiDCBhTELMAkGA1UEBhMC +VVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNX +ZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEB +ALkVsUSRzCPIK0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd +/ZDJPHV3V3p9+N701NX3leZ0bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pB +A4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSljqHyita04pO2t/caaH/+Xc/77szWn +k4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+esE2fDbbFwRnzVlhE9 +iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJtylv +2G0xffX8oRAHh84vWdw+WNs= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB +gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk +MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY +UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx +NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 +dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy +dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 +38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP +KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q +DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 +qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa +JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi +PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P +BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs +jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 +eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR +vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa +IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy +i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ +O+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIETzCCAzegAwIBAgIEO63vKTANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQTDEfMB0GA1UE +ChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2Fjamkg +U2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBSb290Q0EwHhcNMDEwOTIzMTQxODE3WhcNMTEw +OTIzMTMxODE3WjB1MQswCQYDVQQGEwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5v +LjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MR8wHQYDVQQDExZDQyBTaWdu +ZXQgLSBDQSBLbGFzYSAxMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4SRW9Q58g5DY1Hw7h +gCRKBEdPdGn0MFHsfw7rlu/oQm7IChI/uWd9q5wwo77YojtTDjRnpgZsjqBeynX8T90vFILqsY2K +5CF1OESalwvVr3sZiQX79lisuFKat92u6hBFikFIVxfHHB67Af+g7u0dEHdDW7lwy81MwFYxBTRy +9wIDAQABo4IBbTCCAWkwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwggEEBgNVHSAE +gfwwgfkwgfYGDSsGAQQBvj8CAQoBAQAwgeQwgZoGCCsGAQUFBwICMIGNGoGKQ2VydHlmaWthdCB3 +eXN0YXdpb255IHpnb2RuaWUgeiBkb2t1bWVudGVtOiAiUG9saXR5a2EgQ2VydHlmaWthY2ppIGRs +YSBSb290Q0EiLiBDZXJ0eWZpa2F0IHd5c3Rhd2lvbnkgcHJ6ZXogUm9vdENBIHcgaGllcmFyY2hp +aSBDQyBTaWduZXQuMEUGCCsGAQUFBwIBFjlodHRwOi8vd3d3LnNpZ25ldC5wbC9yZXBvenl0b3Jp +dW0vZG9rdW1lbnR5L3BjX3Jvb3RjYS50eHQwHwYDVR0jBBgwFoAUwJvFIw0C4aZOSGsfAOnjmhQb +sa8wHQYDVR0OBBYEFMODHtVZd1T7TftXR/nEI1zR54njMA0GCSqGSIb3DQEBBQUAA4IBAQBRIHQB +FIGh8Jpxt87AgSLwIEEk4+oGy769u3NtoaR0R3WNMdmt7fXTi0tyTQ9V4AIszxVjhnUPaKnF1KYy +f8Tl+YTzk9ZfFkZ3kCdSaILZAOIrmqWNLPmjUQ5/JiMGho0e1YmWUcMci84+pIisTsytFzVP32/W ++sz2H4FQAvOIMmxB7EJX9AdbnXn9EXZ+4nCqi0ft5z96ZqOJJiCB3vSaoYg+wdkcvb6souMJzuc2 +uptXtR1Xf3ihlHaGW+hmnpcwFA6AoNrom6Vgzk6U1ienx0Cw28BhRSKqzKkyXkuK8gRflZUx84uf +tXncwKJrMiE3lvgOOBITRzcahirLer4c +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIE9zCCA9+gAwIBAgIEPL/xoTANBgkqhkiG9w0BAQUFADB2MQswCQYDVQQGEwJQTDEfMB0GA1UE +ChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2Fjamkg +U2lnbmV0MSAwHgYDVQQDExdDQyBTaWduZXQgLSBQQ0EgS2xhc2EgMjAeFw0wMjA0MTkxMDI5NTNa +Fw0xNzA0MTgxMjUzMDdaMHUxCzAJBgNVBAYTAlBMMR8wHQYDVQQKExZUUCBJbnRlcm5ldCBTcC4g +eiBvLm8uMSQwIgYDVQQLExtDZW50cnVtIENlcnR5ZmlrYWNqaSBTaWduZXQxHzAdBgNVBAMTFkND +IFNpZ25ldCAtIENBIEtsYXNhIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqgLJu +QqY4yavbSgHg8CyfKTx4BokNSDOVz4eD9vptUr11Kqd06ED1hlH7Sg0goBFAfntNU/QTKwSBaNui +me7C4sSEdgsKrPoAhGb4Mq8y7Ty7RqZz7mkzNMqzL2L2U4yQ2QjvpH8MH0IBqOWEcpSkpwnrCDIm +RoTfd+YlZWKi2JceQixUUYIQ45Ox8+x8hHbvvZdgqtcvo8PW27qoHkp/7hMuJ44kDAGrmxffBXl/ +OBRZp0uO1CSLcMcVJzyr2phKhy406MYdWrtNPEluGs0GFDzd0nrIctiWAO4cmct4S72S9Q6e//0G +O9f3/Ca5Kb2I1xYLj/xE+HgjHX9aD2MhAgMBAAGjggGMMIIBiDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjCB4wYDVR0gBIHbMIHYMIHVBg0rBgEEAb4/AhQKAQEAMIHDMHUGCCsGAQUF +BwICMGkaZ0NlcnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmllIHogZG9rdW1lbnRlbTogIlBvbGl0 +eWthIENlcnR5ZmlrYWNqaSBQQ0EyIC0gQ2VydHlmaWthdHkgVXJ6ZWRvdyBLbGFzeSAyIi4wSgYI +KwYBBQUHAgEWPmh0dHA6Ly93d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9kb2t1bWVudHkva2xh +c2EyL3BjX3BjYTIudHh0MD8GA1UdHwQ4MDYwNKAyoDCGLmh0dHA6Ly93d3cuc2lnbmV0LnBsL3Jl +cG96eXRvcml1bS9jcmwvcGNhMi5jcmwwHwYDVR0jBBgwFoAUwGxGyl2CfpYHRonE82AVXO08kMIw +HQYDVR0OBBYEFLtFBlILy4HNKVSzvHxBTM0HDowlMA0GCSqGSIb3DQEBBQUAA4IBAQBWTsCbqXrX +hBBev5v5cIuc6gJM8ww7oR0uMQRZoFSqvQUPWBYM2/TLI/f8UM9hSShUVj3zEsSj/vFHagUVmzuV +Xo5u0WK8iaqATSyEVBhADHrPG6wYcLKJlagge/ILA0m+SieyP2sjYD9MUB9KZIEyBKv0429UuDTw +6P7pslxMWJBSNyQxaLIs0SRKsqZZWkc7ZYAj2apSkBMX2Is1oHA+PwkF6jQMwCao/+CndXPUzfCF +6caa9WwW31W26MlXCvSmJgfiTPwGvm4PkPmOnmWZ3CczzhHl4q7ztHFzshJH3sZWDnrWwBFjzz5e +Pr3WHV1wA7EY6oT4zBx+2gT9XBTB +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEUzCCAzugAwIBAgIEPq+qjzANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJQTDE3MDUGA1UE +ChMuQ1ppQyBDZW50cmFzdCBTQSB3IGltaWVuaXUgTWluaXN0cmEgR29zcG9kYXJraTEZMBcGA1UE +AxMQQ1ppQyBDZW50cmFzdCBTQTAeFw0wMzA0MzAxMDUwNTVaFw0wODA0MjgxMDUwNTVaMGgxCzAJ +BgNVBAYTAlBMMR8wHQYDVQQKExZUUCBJbnRlcm5ldCBTcC4geiBvLm8uMR8wHQYDVQQDExZDQyBT +aWduZXQgLSBDQSBLbGFzYSAzMRcwFQYDVQQFEw5OdW1lciB3cGlzdTogNDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBALVdeOM62cPH2NERFxbS5FIp/HSv3fgesdVsTUFxZbGtE+/E0RMl +KZQJHH9emx7vRYubsi4EOLCjYsCOTFvgGRIpZzx7R7T5c0Di5XFkRU4gjBl7aHJoKb5SLzGlWdoX +GsekVtl6keEACrizV2EafqjI8cnBWY7OxQ1ooLQp5AeFjXg+5PT0lO6TUZAubqjFbhVbxSWjqvdj +93RGfyYE76MnNn4c2xWySD07n7uno06TC0IJe6+3WSX1h+76VsIFouWBXOoM7cxxiLjoqdBVu24+ +P8e81SukE7qEvOwDPmk9ZJFtt1nBNg8a1kaixcljrA/43XwOPz6qnJ+cIj/xywECAwEAAaOCAQow +ggEGMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMDMGA1UdIAEB/wQpMCcwJQYEVR0g +ADAdMBsGCCsGAQUFBwIBFg93d3cuY2VudHJhc3QucGwwgY4GA1UdIwSBhjCBg4AU2a7r85Cp1iJN +W0Ca1LR6VG3996ShZaRjMGExCzAJBgNVBAYTAlBMMTcwNQYDVQQKEy5DWmlDIENlbnRyYXN0IFNB +IHcgaW1pZW5pdSBNaW5pc3RyYSBHb3Nwb2RhcmtpMRkwFwYDVQQDExBDWmlDIENlbnRyYXN0IFNB +ggQ9/0sQMB0GA1UdDgQWBBR7Y8wZkHq0zrY7nn1tFSdQ0PlJuTANBgkqhkiG9w0BAQUFAAOCAQEA +ldt/svO5c1MU08FKgrOXCGEbEPbQxhpM0xcd6Iv3dCo6qugEgjEs9Qm5CwUNKMnFsvR27cJWUvZb +MVcvwlwCwclOdwF6u/QRS8bC2HYErhYo9bp9yuxxzuow2A94c5fPqfVrjXy+vDouchAm6+A5Wjzv +J8wxVFDCs+9iGACmyUWr/JGXCYiQIbQkwlkRKHHlan9ymKf1NvIej/3EpeT8fKr6ywxGuhAfqofW +pg3WJY/RCB4lTzD8vZGNwfMFGkWhJkypad3i9w3lGmDVpsHaWtCgGfd0H7tUtWPkP+t7EjIRCD9J +HYnTR+wbbewc5vOI+UobR15ynGfFIaSIiMTVtQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEejCCA2KgAwIBAgIEP4vk6TANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJQ +TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu +dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MR8wHQYDVQQDExZDQyBTaWduZXQgLSBD +QSBLbGFzYSAyMB4XDTAzMTAxNDExNTgyMloXDTE3MDQxODEyNTMwN1owdzELMAkG +A1UEBhMCUEwxHzAdBgNVBAoTFlRQIEludGVybmV0IFNwLiB6IG8uby4xJDAiBgNV +BAsTG0NlbnRydW0gQ2VydHlmaWthY2ppIFNpZ25ldDEhMB8GA1UEAxMYQ0MgU2ln +bmV0IC0gT0NTUCBLbGFzYSAyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCo +VCsaBStblXQYVNthe3dvaCrfvKpPXngh4almm988iIlEv9CVTaAdCfaJNihvA+Vs +Qw8++ix1VqteMQE474/MV/YaXigP0Zr0QB+g+/7PWVlv+5U9Gzp9+Xx4DJay8AoI +iB7Iy5Qf9iZiHm5BiPRIuUXT4ZRbZRYPh0/76vgRsQIDAQABo4IBkjCCAY4wDgYD +VR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMJMEEGA1UdHwQ6MDgwNqA0 +oDKGMGh0dHA6Ly93d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9jcmwva2xhc2Ey +LmNybDCB2AYDVR0gBIHQMIHNMIHKBg4rBgEEAb4/AoFICgwBADCBtzBsBggrBgEF +BQcCAjBgGl5DZXJ0eWZpa2F0IHd5ZGFueSB6Z29kbmllIHogZG9rdW1lbnRlbSAi +UG9saXR5a2EgQ2VydHlmaWthY2ppIC0gQ2VydHlmaWthdHkgcmVzcG9uZGVyb3cg +T0NTUCIuMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnNpZ25ldC5wbC9yZXBvenl0 +b3JpdW0vZG9rdW1lbnR5L3BjX29jc3BfMV8wLnBkZjAfBgNVHSMEGDAWgBS7RQZS +C8uBzSlUs7x8QUzNBw6MJTAdBgNVHQ4EFgQUKEVrOY7cEHvsVgvoyZdytlbtgwEw +CQYDVR0TBAIwADANBgkqhkiG9w0BAQUFAAOCAQEAQrRg5MV6dxr0HU2IsLInxhvt +iUVmSFkIUsBCjzLoewOXA16d2oDyHhI/eE+VgAsp+2ANjZu4xRteHIHoYMsN218M +eD2MLRsYS0U9xxAFK9gDj/KscPbrrdoqLvtPSMhUb4adJS9HLhvUe6BicvBf3A71 +iCNe431axGNDWKnpuj2KUpj4CFHYsWCXky847YtTXDjri9NIwJJauazsrSjK+oXp +ngRS506mdQ7vWrtApkh8zhhWp7duCkjcCo1O8JxqYr2qEW1fXmgOISe010v2mmuv +hHxPyVwoAU4KkOw0nbXZn53yak0is5+XmAjh0wWue44AssHrjC9nUh3mkLt6eQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEezCCA2OgAwIBAgIEP4vnLzANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJQ +TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEfMB0GA1UEAxMWQ0Mg +U2lnbmV0IC0gQ0EgS2xhc2EgMzEXMBUGA1UEBRMOTnVtZXIgd3Bpc3U6IDQwHhcN +MDMxMDE0MTIwODAwWhcNMDgwNDI4MTA1MDU1WjB3MQswCQYDVQQGEwJQTDEfMB0G +A1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2VudHJ1bSBD +ZXJ0eWZpa2FjamkgU2lnbmV0MSEwHwYDVQQDExhDQyBTaWduZXQgLSBPQ1NQIEts +YXNhIDMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM/9GwvARNuCVN+PqZmO +4FqH8vTqhenUyqRkmAVT4YhLu0a9AXeLAYVDu+NTkYzsAUMAfu55rIKHNLlm6WbF +KvLiKKz4p4pbUr+ToPcwl/TDotidloUdBAxDg0SL+PmQqACZDe3seJho2IYf2vDL +/G4TLMbKmNB0mlWFuN0f4fJNAgMBAAGjggGgMIIBnDAOBgNVHQ8BAf8EBAMCB4Aw +EwYDVR0lBAwwCgYIKwYBBQUHAwkwTwYDVR0fBEgwRjBEoEKgQIY+aHR0cDovL3d3 +dy5zaWduZXQucGwva3dhbGlmaWtvd2FuZS9yZXBvenl0b3JpdW0vY3JsL2tsYXNh +My5jcmwwgdgGA1UdIASB0DCBzTCBygYOKwYBBAG+PwKCLAoCAQAwgbcwbAYIKwYB +BQUHAgIwYBpeQ2VydHlmaWthdCB3eWRhbnkgemdvZG5pZSB6IGRva3VtZW50ZW0g +IlBvbGl0eWthIENlcnR5ZmlrYWNqaSAtIENlcnR5ZmlrYXR5IHJlc3BvbmRlcm93 +IE9DU1AiLjBHBggrBgEFBQcCARY7aHR0cDovL3d3dy5zaWduZXQucGwvcmVwb3p5 +dG9yaXVtL2Rva3VtZW50eS9wY19vY3NwXzFfMC5wZGYwHwYDVR0jBBgwFoAUe2PM +GZB6tM62O559bRUnUND5SbkwHQYDVR0OBBYEFG4jnCMvBALRQXtmDn9TyXQ/EKP+ +MAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADggEBACXrKG5Def5lpRwmZom3UEDq +bl7y4U3qomG4B+ok2FVZGgPZti+ZgvrenPj7PtbYCUBPsCSTNrznKinoT3gD9lQQ +xkEHwdc6VD1GlFp+qI64u0+wS9Epatrdf7aBnizrOIB4LJd4E2TWQ6trspetjMIU +upyWls1BmYUxB91R7QkTiAUSNZ87s3auhZuG4f0V0JLVCcg2rn7AN1rfMkgxCbHk +GxiQbYWFljl6aatxR3odnnzVUe1I8uoY2JXpmmUcOG4dNGuQYziyKG3mtXCQWvug +5qi9Mf3KUh1oSTKx6HfLjjNl1+wMB5Mdb8LF0XyZLdJM9yIZh7SBRsYm9QiXevY= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFGjCCBAKgAwIBAgIEPL7eEDANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQTDEfMB0GA1UE +ChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2Fjamkg +U2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBSb290Q0EwHhcNMDIwNDE4MTQ1NDA4WhcNMjYw +OTIxMTU0MjE5WjB2MQswCQYDVQQGEwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5v +LjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MSAwHgYDVQQDExdDQyBTaWdu +ZXQgLSBQQ0EgS2xhc2EgMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM7BrBlbN5ma +M5eg0BOTqoZ+9NBDvU8Lm5rTdrMswFTCathzpVVLK/JD4K3+4oCZ9SRAspEXE4gvwb08ASY6w5s+ +HpRkeJw8YzMFR5kDZD5adgnCAy4vDfIXYZgppXPaTQ8wnfUZ7BZ7Zfa7QBemUIcJIzJBB0UqgtxW +Ceol9IekpBRVmuuSA6QG0Jkm+pGDJ05yj2eQG8jTcBENM7sVA8rGRMyFA4skSZ+D0OG6FS2xC1i9 +JyN0ag1yII/LPx8HK5J4W9MaPRNjAEeaa2qI9EpchwrOxnyVbQfSedCG1VRJfAsE/9tT9CMUPZ3x +W20QjQcSZJqVcmGW9gVsXKQOVLsCAwEAAaOCAbMwggGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMIIBBAYDVR0gBIH8MIH5MIH2Bg0rBgEEAb4/AgEKAQEBMIHkMIGaBggrBgEFBQcC +AjCBjRqBikNlcnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmllIHogZG9rdW1lbnRlbTogIlBvbGl0 +eWthIENlcnR5ZmlrYWNqaSBkbGEgUm9vdENBIi4gQ2VydHlmaWthdCB3eXN0YXdpb255IHByemV6 +IFJvb3RDQSB3IGhpZXJhcmNoaWkgQ0MgU2lnbmV0LjBFBggrBgEFBQcCARY5aHR0cDovL3d3dy5z +aWduZXQucGwvcmVwb3p5dG9yaXVtL2Rva3VtZW50eS9wY19yb290Y2EudHh0MEQGA1UdHwQ9MDsw +OaA3oDWGM2h0dHA6Ly93d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9yb290Y2Evcm9vdGNhLmNy +bDAfBgNVHSMEGDAWgBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAdBgNVHQ4EFgQUwGxGyl2CfpYHRonE +82AVXO08kMIwDQYJKoZIhvcNAQEFBQADggEBABp1TAUsa+BeVWg4cjowc8yTJ5XN3GvN96GObMkx +UGY7U9kVrLI71xBgoNVyzXTiMNDBvjh7vdPWjpl5SDiRpnnKiOFXA43HvNWzUaOkTu1mxjJsZsan +ot1Xt6j0ZDC+03FjLHdYMyM9kSWp6afb4980EPYZCcSzgM5TOGfJmNii5Tq468VFKrX+52Aou1G2 +2Ohu+EEOlOrG7ylKv1hHUJJCjwN0ZVEIn1nDbrU9FeGCz8J9ihVUvnENEBbBkU37PWqWuHitKQDV +tcwTwJJdR8cmKq3NmkwAm9fPacidQLpaw0WkuGrS+fEDhu1Nhy9xELP6NA9GRTCNxm/dXlcwnmY= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFGjCCBAKgAwIBAgIEPV0tNDANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQTDEfMB0GA1UE +ChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2Fjamkg +U2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBSb290Q0EwHhcNMDIwODE2MTY0OTU2WhcNMjYw +OTIxMTU0MjE5WjB2MQswCQYDVQQGEwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5v +LjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MSAwHgYDVQQDExdDQyBTaWdu +ZXQgLSBQQ0EgS2xhc2EgMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALN3LanJtdue +Ne6geWUTFENa+lEuzqELcoqhYB+a/tJcPEkc6TX/bYPzalRRjqs+quMP6KZTU0DixOrV+K7iWaqA +iQ913HX5IBLmKDCrTVW/ZvSDpiBKbxlHfSNuJxAuVT6HdbzK7yAW38ssX+yS2tZYHZ5FhZcfqzPE +OpO94mAKcBUhk6T/ki0evXX/ZvvktwmF3hKattzwtM4JMLurAEl8SInyEYULw5JdlfcBez2Tg6Db +w34hA1A+ckTwhxzecrB8TUe2BnQKOs9vr2cCACpFFcOmPkM0Drtjctr1QHm1tYSqRFRf9VcV5tfC +3P8QqoK4ONjtLPHc9x5NE1uK/FMCAwEAAaOCAbMwggGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMIIBBAYDVR0gBIH8MIH5MIH2Bg0rBgEEAb4/AgEKAQECMIHkMIGaBggrBgEFBQcC +AjCBjRqBikNlcnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmllIHogZG9rdW1lbnRlbTogIlBvbGl0 +eWthIENlcnR5ZmlrYWNqaSBkbGEgUm9vdENBIi4gQ2VydHlmaWthdCB3eXN0YXdpb255IHByemV6 +IFJvb3RDQSB3IGhpZXJhcmNoaWkgQ0MgU2lnbmV0LjBFBggrBgEFBQcCARY5aHR0cDovL3d3dy5z +aWduZXQucGwvcmVwb3p5dG9yaXVtL2Rva3VtZW50eS9wY19yb290Y2EudHh0MEQGA1UdHwQ9MDsw +OaA3oDWGM2h0dHA6Ly93d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9yb290Y2Evcm9vdGNhLmNy +bDAfBgNVHSMEGDAWgBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAdBgNVHQ4EFgQUXvthcPHlH5BgGhlM +ErJNXWlhlgAwDQYJKoZIhvcNAQEFBQADggEBACIce95Mvn710KCAISA0CuHD4aznTU6pLoCDShW4 +7OR+GTpJUm1coTcUqlBHV9mra4VFrBcBuOkHZoBLq/jmE0QJWnpSEULDcH9J3mF0nqO9SM+mWyJG +dsJF/XU/7smummgjMNQXwzQTtWORF+6v5KUbWX85anO2wR+M6YTBWC55zWpWi4RG3vkHFs5Ze2oF +JTlpuxw9ZgxTnWlwI9QR2MvEhYIUMKMOWxw1nt0kKj+5TCNQQGh/VJJ1dsiroGh/io1DOcePEhKz +1Ag52y6Wf0nJJB9yk0sFakqZH18F7eQecQImgZyyeRtsG95leNugB3BXWCW+KxwiBrtQTXv4dTE= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEzzCCA7egAwIBAgIEO6ocGTANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQTDEfMB0GA1UE +ChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2Fjamkg +U2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBSb290Q0EwHhcNMDEwOTIwMTY0MjE5WhcNMjYw +OTIxMTU0MjE5WjBxMQswCQYDVQQGEwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5v +LjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MRswGQYDVQQDExJDQyBTaWdu +ZXQgLSBSb290Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrr2vydnNpELfGW3Ks +ARiDhJvwDtUe4AbWev+OfMc3+vA29nX8ZmIwno3gmItjo5DbUCCRiCMq5c9epcGu+kg4a3BJChVX +REl8gVh0ST15rr3RKrSc4VgsvQzl0ZUraeQLl8JoRT5PLsUj3qwF78jUCQVckiiLVcnGfZtFCm+D +CJXliQBDMB9XFAUEiO/DtEBs0B7wJGx7lgJeJpQUcGiaOPjcJDYOk7rNAYmmD2gWeSlepufO8luU +YG/YDxTC4mqhRqfa4MnVO5dqy+ICj2UvUpHbZDB0KfGRibgBYeQP1kuqgIzJN4UqknVAJb0aMBSP +l+9k2fAUdchx1njlbdcbAgMBAAGjggFtMIIBaTAPBgNVHRMBAf8EBTADAQH/MIIBBAYDVR0gBIH8 +MIH5MIH2Bg0rBgEEAb4/AgEKAQEAMIHkMIGaBggrBgEFBQcCAjCBjRqBikNlcnR5ZmlrYXQgd3lz +dGF3aW9ueSB6Z29kbmllIHogZG9rdW1lbnRlbTogIlBvbGl0eWthIENlcnR5ZmlrYWNqaSBkbGEg +Um9vdENBIi4gQ2VydHlmaWthdCB3eXN0YXdpb255IHByemV6IFJvb3RDQSB3IGhpZXJhcmNoaWkg +Q0MgU2lnbmV0LjBFBggrBgEFBQcCARY5aHR0cDovL3d3dy5zaWduZXQucGwvcmVwb3p5dG9yaXVt +L2Rva3VtZW50eS9wY19yb290Y2EudHh0MB0GA1UdDgQWBBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAf +BgNVHSMEGDAWgBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcN +AQEFBQADggEBAGnY5QmYqnnO9OqFOWZxxb25UHRnaRF6IV9aaGit5BZufZj2Tq3v8L3SgE34GOoI +cdRMMG5JEpEU4mN/Ef3oY6Eo+7HfqaPHI4KFmbDSPiK5s+wmf+bQSm0Yq5/h4ZOdcAESlLQeLSt1 +CQk2JoKQJ6pyAf6xJBgWEIlm4RXE4J3324PUiOp83kW6MDvaa1xY976WyInr4rwoLgxVl11LZeKW +ha0RJJxJgw/NyWpKG7LWCm1fglF8JH51vZNndGYq1iKtfnrIOvLZq6bzaCiZm1EurD8HE6P7pmAB +KK6o3C2OXlNfNIgwkDN/cDqk5TYsTkrpfriJPdxXBH8hQOkW89g= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID/TCCA2agAwIBAgIEP4/gkTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJQTDEfMB0GA1UE +ChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2Fjamkg +U2lnbmV0MR8wHQYDVQQDExZDQyBTaWduZXQgLSBDQSBLbGFzYSAxMB4XDTAzMTAxNzEyMjkwMloX +DTExMDkyMzExMTgxN1owdjELMAkGA1UEBhMCUEwxHzAdBgNVBAoTFlRQIEludGVybmV0IFNwLiB6 +IG8uby4xJDAiBgNVBAsTG0NlbnRydW0gQ2VydHlmaWthY2ppIFNpZ25ldDEgMB4GA1UEAxMXQ0Mg +U2lnbmV0IC0gVFNBIEtsYXNhIDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOJYrISEtSsd +uHajROh5/n7NGrkpYTT9NEaPe9+ucuQ37KxIbfJwXJjgUc1dw4wCkcQ12FJarD1X6mSQ4cfN/60v +LfKI5ZD4nhJTMKlAj1pX9ScQ/MuyvKStCbn5WTkjPhjRAM0tdwXSnzuTEunfw0Oup559y3Iqxg1c +ExflB6cfAgMBAAGjggGXMIIBkzBBBgNVHR8EOjA4MDagNKAyhjBodHRwOi8vd3d3LnNpZ25ldC5w +bC9yZXBvenl0b3JpdW0vY3JsL2tsYXNhMS5jcmwwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQM +MAoGCCsGAQUFBwMIMIHaBgNVHSAEgdIwgc8wgcwGDSsGAQQBvj8CZAoRAgEwgbowbwYIKwYBBQUH +AgIwYxphQ2VydHlmaWthdCB3eXN0YXdpb255IHpnb2RuaWUgeiBkb2t1bWVudGVtICJQb2xpdHlr +YSBDZXJ0eWZpa2FjamkgQ0MgU2lnbmV0IC0gWm5ha293YW5pZSBjemFzZW0iLjBHBggrBgEFBQcC +ARY7aHR0cDovL3d3dy5zaWduZXQucGwvcmVwb3p5dG9yaXVtL2Rva3VtZW50eS9wY190c2ExXzJf +MS5wZGYwHwYDVR0jBBgwFoAUw4Me1Vl3VPtN+1dH+cQjXNHnieMwHQYDVR0OBBYEFJdDwEqtcavO +Yd9u9tej53vWXwNBMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADgYEAnpiQkqLCJQYXUrqMHUEz ++z3rOqS0XzSFnVVLhkVssvXc8S3FkJIiQTUrkScjI4CToCzujj3EyfNxH6yiLlMbskF8I31JxIeB +vueqV+s+o76CZm3ycu9hb0I4lswuxoT+q5ZzPR8Irrb51rZXlolR+7KtwMg4sFDJZ8RNgOf7tbA= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEFTCCA36gAwIBAgIBADANBgkqhkiG9w0BAQQFADCBvjELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0luZGlhbmExFTATBgNVBAcTDEluZGlhbmFwb2xpczEoMCYGA1UE +ChMfU29mdHdhcmUgaW4gdGhlIFB1YmxpYyBJbnRlcmVzdDETMBEGA1UECxMKaG9z +dG1hc3RlcjEgMB4GA1UEAxMXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxJTAjBgkq +hkiG9w0BCQEWFmhvc3RtYXN0ZXJAc3BpLWluYy5vcmcwHhcNMDMwMTE1MTYyOTE3 +WhcNMDcwMTE0MTYyOTE3WjCBvjELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0luZGlh +bmExFTATBgNVBAcTDEluZGlhbmFwb2xpczEoMCYGA1UEChMfU29mdHdhcmUgaW4g +dGhlIFB1YmxpYyBJbnRlcmVzdDETMBEGA1UECxMKaG9zdG1hc3RlcjEgMB4GA1UE +AxMXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxJTAjBgkqhkiG9w0BCQEWFmhvc3Rt +YXN0ZXJAc3BpLWluYy5vcmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPB6 +rdoiLR3RodtM22LMcfwfqb5OrJNl7fwmvskgF7yP6sdD2bOfDIXhg9852jhY8/kL +VOFe1ELAL2OyN4RAxk0rliZQVgeTgqvgkOVIBbNwgnjN6mqtuWzFiPL+NXQExq40 +I3whM+4lEiwSHaV+MYxWanMdhc+kImT50LKfkxcdAgMBAAGjggEfMIIBGzAdBgNV +HQ4EFgQUB63oQR1/vda/G4F6P4xLiN4E0vowgesGA1UdIwSB4zCB4IAUB63oQR1/ +vda/G4F6P4xLiN4E0vqhgcSkgcEwgb4xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdJ +bmRpYW5hMRUwEwYDVQQHEwxJbmRpYW5hcG9saXMxKDAmBgNVBAoTH1NvZnR3YXJl +IGluIHRoZSBQdWJsaWMgSW50ZXJlc3QxEzARBgNVBAsTCmhvc3RtYXN0ZXIxIDAe +BgNVBAMTF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MSUwIwYJKoZIhvcNAQkBFhZo +b3N0bWFzdGVyQHNwaS1pbmMub3JnggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN +AQEEBQADgYEAm/Abn8c2y1nO3fgpAIslxvi9iNBZDhQtJ0VQZY6wgSfANyDOR4DW +iexO/AlorB49KnkFS7TjCAoLOZhcg5FaNiKnlstMI5krQmau1Qnb/vGSNsE/UGms +1ts+QYPUs0KmGEAFUri2XzLy+aQo9Kw74VBvqnxvaaMeY5yMcKNOieY= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIIDjCCBfagAwIBAgIJAOiOtsn4KhQoMA0GCSqGSIb3DQEBBQUAMIG8MQswCQYD +VQQGEwJVUzEQMA4GA1UECBMHSW5kaWFuYTEVMBMGA1UEBxMMSW5kaWFuYXBvbGlz +MSgwJgYDVQQKEx9Tb2Z0d2FyZSBpbiB0aGUgUHVibGljIEludGVyZXN0MRMwEQYD +VQQLEwpob3N0bWFzdGVyMR4wHAYDVQQDExVDZXJ0aWZpY2F0ZSBBdXRob3JpdHkx +JTAjBgkqhkiG9w0BCQEWFmhvc3RtYXN0ZXJAc3BpLWluYy5vcmcwHhcNMDgwNTEz +MDgwNzU2WhcNMTgwNTExMDgwNzU2WjCBvDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0luZGlhbmExFTATBgNVBAcTDEluZGlhbmFwb2xpczEoMCYGA1UEChMfU29mdHdh +cmUgaW4gdGhlIFB1YmxpYyBJbnRlcmVzdDETMBEGA1UECxMKaG9zdG1hc3RlcjEe +MBwGA1UEAxMVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSUwIwYJKoZIhvcNAQkBFhZo +b3N0bWFzdGVyQHNwaS1pbmMub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEA3DbmR0LCxFF1KYdAw9iOIQbSGE7r7yC9kDyFEBOMKVuUY/b0LfEGQpG5 +GcRCaQi/izZF6igFM0lIoCdDkzWKQdh4s/Dvs24t3dHLfer0dSbTPpA67tfnLAS1 +fOH1fMVO73e9XKKTM5LOfYFIz2u1IiwIg/3T1c87Lf21SZBb9q1NE8re06adU1Fx +Y0b4ShZcmO4tbZoWoXaQ4mBDmdaJ1mwuepiyCwMs43pPx93jzONKao15Uvr0wa8u +jyoIyxspgpJyQ7zOiKmqp4pRQ1WFmjcDeJPI8L20QcgHQprLNZd6ioFl3h1UCAHx +ZFy3FxpRvB7DWYd2GBaY7r/2Z4GLBjXFS21ZGcfSxki+bhQog0oQnBv1b7ypjvVp +/rLBVcznFMn5WxRTUQfqzj3kTygfPGEJ1zPSbqdu1McTCW9rXRTunYkbpWry9vjQ +co7qch8vNGopCsUK7BxAhRL3pqXTT63AhYxMfHMgzFMY8bJYTAH1v+pk1Vw5xc5s +zFNaVrpBDyXfa1C2x4qgvQLCxTtVpbJkIoRRKFauMe5e+wsWTUYFkYBE7axt8Feo ++uthSKDLG7Mfjs3FIXcDhB78rKNDCGOM7fkn77SwXWfWT+3Qiz5dW8mRvZYChD3F +TbxCP3T9PF2sXEg2XocxLxhsxGjuoYvJWdAY4wCAs1QnLpnwFVMCAwEAAaOCAg8w +ggILMB0GA1UdDgQWBBQ0cdE41xU2g0dr1zdkQjuOjVKdqzCB8QYDVR0jBIHpMIHm +gBQ0cdE41xU2g0dr1zdkQjuOjVKdq6GBwqSBvzCBvDELMAkGA1UEBhMCVVMxEDAO +BgNVBAgTB0luZGlhbmExFTATBgNVBAcTDEluZGlhbmFwb2xpczEoMCYGA1UEChMf +U29mdHdhcmUgaW4gdGhlIFB1YmxpYyBJbnRlcmVzdDETMBEGA1UECxMKaG9zdG1h +c3RlcjEeMBwGA1UEAxMVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSUwIwYJKoZIhvcN +AQkBFhZob3N0bWFzdGVyQHNwaS1pbmMub3JnggkA6I62yfgqFCgwDwYDVR0TAQH/ +BAUwAwEB/zARBglghkgBhvhCAQEEBAMCAAcwCQYDVR0SBAIwADAuBglghkgBhvhC +AQ0EIRYfU29mdHdhcmUgaW4gdGhlIFB1YmxpYyBJbnRlcmVzdDAwBglghkgBhvhC +AQQEIxYhaHR0cHM6Ly9jYS5zcGktaW5jLm9yZy9jYS1jcmwucGVtMDIGCWCGSAGG ++EIBAwQlFiNodHRwczovL2NhLnNwaS1pbmMub3JnL2NlcnQtY3JsLnBlbTAhBgNV +HREEGjAYgRZob3N0bWFzdGVyQHNwaS1pbmMub3JnMA4GA1UdDwEB/wQEAwIBBjAN +BgkqhkiG9w0BAQUFAAOCAgEAtM294LnqsgMrfjLp3nI/yUuCXp3ir1UJogxU6M8Y +PCggHam7AwIvUjki+RfPrWeQswN/2BXja367m1YBrzXU2rnHZxeb1NUON7MgQS4M +AcRb+WU+wmHo0vBqlXDDxm/VNaSsWXLhid+hoJ0kvSl56WEq2dMeyUakCHhBknIP +qxR17QnwovBc78MKYiC3wihmrkwvLo9FYyaW8O4x5otVm6o6+YI5HYg84gd1GuEP +sTC8cTLSOv76oYnzQyzWcsR5pxVIBcDYLXIC48s9Fmq6ybgREOJJhcyWR2AFJS7v +dVkz9UcZFu/abF8HyKZQth3LZjQl/GaD68W2MEH4RkRiqMEMVObqTFoo5q7Gt/5/ +O5aoLu7HaD7dAD0prypjq1/uSSotxdz70cbT0ZdWUoa2lOvUYFG3/B6bzAKb1B+P ++UqPti4oOxfMxaYF49LTtcYDyeFIQpvLP+QX4P4NAZUJurgNceQJcHdC2E3hQqlg +g9cXiUPS1N2nGLar1CQlh7XU4vwuImm9rWgs/3K1mKoGnOcqarihk3bOsPN/nOHg +T7jYhkalMwIsJWE3KpLIrIF0aGOHM3a9BX9e1dUCbb2v/ypaqknsmHlHU5H2DjRa +yaXG67Ljxay2oHA1u8hRadDytaIybrw/oDc5fHE2pgXfDBLkFqfF1stjo5VwP+YE +o2A= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc +MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj +IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB +IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE +RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl +U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290 +IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU +ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC +QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr +rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S +NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc +QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH +txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP +BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC +AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp +tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa +IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl +6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+ +xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU +Cm26OWMohpLzGITY+9HPBVZkVw== +-----END CERTIFICATE----- + diff --git a/interactive-mining-madoap/madoap/src/tornado/curl_httpclient.py b/interactive-mining-madoap/madoap/src/tornado/curl_httpclient.py new file mode 100644 index 0000000..5a3e624 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/curl_httpclient.py @@ -0,0 +1,435 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Blocking and non-blocking HTTP client implementations using pycurl.""" + +from __future__ import with_statement + +import cStringIO +import collections +import logging +import pycurl +import threading +import time + +from tornado import httputil +from tornado import ioloop +from tornado import stack_context + +from tornado.escape import utf8 +from tornado.httpclient import HTTPRequest, HTTPResponse, HTTPError, AsyncHTTPClient, main + +class CurlAsyncHTTPClient(AsyncHTTPClient): + def initialize(self, io_loop=None, max_clients=10, + max_simultaneous_connections=None): + self.io_loop = io_loop + self._multi = pycurl.CurlMulti() + self._multi.setopt(pycurl.M_TIMERFUNCTION, self._set_timeout) + self._multi.setopt(pycurl.M_SOCKETFUNCTION, self._handle_socket) + self._curls = [_curl_create(max_simultaneous_connections) + for i in xrange(max_clients)] + self._free_list = self._curls[:] + self._requests = collections.deque() + self._fds = {} + self._timeout = None + + try: + self._socket_action = self._multi.socket_action + except AttributeError: + # socket_action is found in pycurl since 7.18.2 (it's been + # in libcurl longer than that but wasn't accessible to + # python). + logging.warning("socket_action method missing from pycurl; " + "falling back to socket_all. Upgrading " + "libcurl and pycurl will improve performance") + self._socket_action = \ + lambda fd, action: self._multi.socket_all() + + # libcurl has bugs that sometimes cause it to not report all + # relevant file descriptors and timeouts to TIMERFUNCTION/ + # SOCKETFUNCTION. Mitigate the effects of such bugs by + # forcing a periodic scan of all active requests. + self._force_timeout_callback = ioloop.PeriodicCallback( + self._handle_force_timeout, 1000, io_loop=io_loop) + self._force_timeout_callback.start() + + def close(self): + self._force_timeout_callback.stop() + for curl in self._curls: + curl.close() + self._multi.close() + self._closed = True + super(CurlAsyncHTTPClient, self).close() + + def fetch(self, request, callback, **kwargs): + if not isinstance(request, HTTPRequest): + request = HTTPRequest(url=request, **kwargs) + self._requests.append((request, stack_context.wrap(callback))) + self._process_queue() + self._set_timeout(0) + + def _handle_socket(self, event, fd, multi, data): + """Called by libcurl when it wants to change the file descriptors + it cares about. + """ + event_map = { + pycurl.POLL_NONE: ioloop.IOLoop.NONE, + pycurl.POLL_IN: ioloop.IOLoop.READ, + pycurl.POLL_OUT: ioloop.IOLoop.WRITE, + pycurl.POLL_INOUT: ioloop.IOLoop.READ | ioloop.IOLoop.WRITE + } + if event == pycurl.POLL_REMOVE: + self.io_loop.remove_handler(fd) + del self._fds[fd] + else: + ioloop_event = event_map[event] + if fd not in self._fds: + self._fds[fd] = ioloop_event + self.io_loop.add_handler(fd, self._handle_events, + ioloop_event) + else: + self._fds[fd] = ioloop_event + self.io_loop.update_handler(fd, ioloop_event) + + def _set_timeout(self, msecs): + """Called by libcurl to schedule a timeout.""" + if self._timeout is not None: + self.io_loop.remove_timeout(self._timeout) + self._timeout = self.io_loop.add_timeout( + time.time() + msecs/1000.0, self._handle_timeout) + + def _handle_events(self, fd, events): + """Called by IOLoop when there is activity on one of our + file descriptors. + """ + action = 0 + if events & ioloop.IOLoop.READ: action |= pycurl.CSELECT_IN + if events & ioloop.IOLoop.WRITE: action |= pycurl.CSELECT_OUT + while True: + try: + ret, num_handles = self._socket_action(fd, action) + except pycurl.error, e: + ret = e.args[0] + if ret != pycurl.E_CALL_MULTI_PERFORM: + break + self._finish_pending_requests() + + def _handle_timeout(self): + """Called by IOLoop when the requested timeout has passed.""" + with stack_context.NullContext(): + self._timeout = None + while True: + try: + ret, num_handles = self._socket_action( + pycurl.SOCKET_TIMEOUT, 0) + except pycurl.error, e: + ret = e.args[0] + if ret != pycurl.E_CALL_MULTI_PERFORM: + break + self._finish_pending_requests() + + # In theory, we shouldn't have to do this because curl will + # call _set_timeout whenever the timeout changes. However, + # sometimes after _handle_timeout we will need to reschedule + # immediately even though nothing has changed from curl's + # perspective. This is because when socket_action is + # called with SOCKET_TIMEOUT, libcurl decides internally which + # timeouts need to be processed by using a monotonic clock + # (where available) while tornado uses python's time.time() + # to decide when timeouts have occurred. When those clocks + # disagree on elapsed time (as they will whenever there is an + # NTP adjustment), tornado might call _handle_timeout before + # libcurl is ready. After each timeout, resync the scheduled + # timeout with libcurl's current state. + new_timeout = self._multi.timeout() + if new_timeout != -1: + self._set_timeout(new_timeout) + + def _handle_force_timeout(self): + """Called by IOLoop periodically to ask libcurl to process any + events it may have forgotten about. + """ + with stack_context.NullContext(): + while True: + try: + ret, num_handles = self._multi.socket_all() + except pycurl.error, e: + ret = e.args[0] + if ret != pycurl.E_CALL_MULTI_PERFORM: + break + self._finish_pending_requests() + + def _finish_pending_requests(self): + """Process any requests that were completed by the last + call to multi.socket_action. + """ + while True: + num_q, ok_list, err_list = self._multi.info_read() + for curl in ok_list: + self._finish(curl) + for curl, errnum, errmsg in err_list: + self._finish(curl, errnum, errmsg) + if num_q == 0: + break + self._process_queue() + + def _process_queue(self): + with stack_context.NullContext(): + while True: + started = 0 + while self._free_list and self._requests: + started += 1 + curl = self._free_list.pop() + (request, callback) = self._requests.popleft() + curl.info = { + "headers": httputil.HTTPHeaders(), + "buffer": cStringIO.StringIO(), + "request": request, + "callback": callback, + "curl_start_time": time.time(), + } + # Disable IPv6 to mitigate the effects of this bug + # on curl versions <= 7.21.0 + # http://sourceforge.net/tracker/?func=detail&aid=3017819&group_id=976&atid=100976 + if pycurl.version_info()[2] <= 0x71500: # 7.21.0 + curl.setopt(pycurl.IPRESOLVE, pycurl.IPRESOLVE_V4) + _curl_setup_request(curl, request, curl.info["buffer"], + curl.info["headers"]) + self._multi.add_handle(curl) + + if not started: + break + + def _finish(self, curl, curl_error=None, curl_message=None): + info = curl.info + curl.info = None + self._multi.remove_handle(curl) + self._free_list.append(curl) + buffer = info["buffer"] + if curl_error: + error = CurlError(curl_error, curl_message) + code = error.code + effective_url = None + buffer.close() + buffer = None + else: + error = None + code = curl.getinfo(pycurl.HTTP_CODE) + effective_url = curl.getinfo(pycurl.EFFECTIVE_URL) + buffer.seek(0) + # the various curl timings are documented at + # http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html + time_info = dict( + queue=info["curl_start_time"] - info["request"].start_time, + namelookup=curl.getinfo(pycurl.NAMELOOKUP_TIME), + connect=curl.getinfo(pycurl.CONNECT_TIME), + pretransfer=curl.getinfo(pycurl.PRETRANSFER_TIME), + starttransfer=curl.getinfo(pycurl.STARTTRANSFER_TIME), + total=curl.getinfo(pycurl.TOTAL_TIME), + redirect=curl.getinfo(pycurl.REDIRECT_TIME), + ) + try: + info["callback"](HTTPResponse( + request=info["request"], code=code, headers=info["headers"], + buffer=buffer, effective_url=effective_url, error=error, + request_time=time.time() - info["curl_start_time"], + time_info=time_info)) + except Exception: + self.handle_callback_exception(info["callback"]) + + + def handle_callback_exception(self, callback): + self.io_loop.handle_callback_exception(callback) + + +class CurlError(HTTPError): + def __init__(self, errno, message): + HTTPError.__init__(self, 599, message) + self.errno = errno + + +def _curl_create(max_simultaneous_connections=None): + curl = pycurl.Curl() + if logging.getLogger().isEnabledFor(logging.DEBUG): + curl.setopt(pycurl.VERBOSE, 1) + curl.setopt(pycurl.DEBUGFUNCTION, _curl_debug) + curl.setopt(pycurl.MAXCONNECTS, max_simultaneous_connections or 5) + return curl + + +def _curl_setup_request(curl, request, buffer, headers): + curl.setopt(pycurl.URL, request.url) + + # libcurl's magic "Expect: 100-continue" behavior causes delays + # with servers that don't support it (which include, among others, + # Google's OpenID endpoint). Additionally, this behavior has + # a bug in conjunction with the curl_multi_socket_action API + # (https://sourceforge.net/tracker/?func=detail&atid=100976&aid=3039744&group_id=976), + # which increases the delays. It's more trouble than it's worth, + # so just turn off the feature (yes, setting Expect: to an empty + # value is the official way to disable this) + if "Expect" not in request.headers: + request.headers["Expect"] = "" + + # libcurl adds Pragma: no-cache by default; disable that too + if "Pragma" not in request.headers: + request.headers["Pragma"] = "" + + # Request headers may be either a regular dict or HTTPHeaders object + if isinstance(request.headers, httputil.HTTPHeaders): + curl.setopt(pycurl.HTTPHEADER, + [utf8("%s: %s" % i) for i in request.headers.get_all()]) + else: + curl.setopt(pycurl.HTTPHEADER, + [utf8("%s: %s" % i) for i in request.headers.iteritems()]) + + if request.header_callback: + curl.setopt(pycurl.HEADERFUNCTION, request.header_callback) + else: + curl.setopt(pycurl.HEADERFUNCTION, + lambda line: _curl_header_callback(headers, line)) + if request.streaming_callback: + curl.setopt(pycurl.WRITEFUNCTION, request.streaming_callback) + else: + curl.setopt(pycurl.WRITEFUNCTION, buffer.write) + curl.setopt(pycurl.FOLLOWLOCATION, request.follow_redirects) + curl.setopt(pycurl.MAXREDIRS, request.max_redirects) + curl.setopt(pycurl.CONNECTTIMEOUT, int(request.connect_timeout)) + curl.setopt(pycurl.TIMEOUT, int(request.request_timeout)) + if request.user_agent: + curl.setopt(pycurl.USERAGENT, utf8(request.user_agent)) + else: + curl.setopt(pycurl.USERAGENT, "Mozilla/5.0 (compatible; pycurl)") + if request.network_interface: + curl.setopt(pycurl.INTERFACE, request.network_interface) + if request.use_gzip: + curl.setopt(pycurl.ENCODING, "gzip,deflate") + else: + curl.setopt(pycurl.ENCODING, "none") + if request.proxy_host and request.proxy_port: + curl.setopt(pycurl.PROXY, request.proxy_host) + curl.setopt(pycurl.PROXYPORT, request.proxy_port) + if request.proxy_username: + credentials = '%s:%s' % (request.proxy_username, + request.proxy_password) + curl.setopt(pycurl.PROXYUSERPWD, credentials) + else: + curl.setopt(pycurl.PROXY, '') + if request.validate_cert: + curl.setopt(pycurl.SSL_VERIFYPEER, 1) + curl.setopt(pycurl.SSL_VERIFYHOST, 2) + else: + curl.setopt(pycurl.SSL_VERIFYPEER, 0) + curl.setopt(pycurl.SSL_VERIFYHOST, 0) + if request.ca_certs is not None: + curl.setopt(pycurl.CAINFO, request.ca_certs) + else: + # There is no way to restore pycurl.CAINFO to its default value + # (Using unsetopt makes it reject all certificates). + # I don't see any way to read the default value from python so it + # can be restored later. We'll have to just leave CAINFO untouched + # if no ca_certs file was specified, and require that if any + # request uses a custom ca_certs file, they all must. + pass + + if request.allow_ipv6 is False: + # Curl behaves reasonably when DNS resolution gives an ipv6 address + # that we can't reach, so allow ipv6 unless the user asks to disable. + # (but see version check in _process_queue above) + curl.setopt(pycurl.IPRESOLVE, pycurl.IPRESOLVE_V4) + + # Set the request method through curl's retarded interface which makes + # up names for almost every single method + curl_options = { + "GET": pycurl.HTTPGET, + "POST": pycurl.POST, + "PUT": pycurl.UPLOAD, + "HEAD": pycurl.NOBODY, + } + custom_methods = set(["DELETE"]) + for o in curl_options.values(): + curl.setopt(o, False) + if request.method in curl_options: + curl.unsetopt(pycurl.CUSTOMREQUEST) + curl.setopt(curl_options[request.method], True) + elif request.allow_nonstandard_methods or request.method in custom_methods: + curl.setopt(pycurl.CUSTOMREQUEST, request.method) + else: + raise KeyError('unknown method ' + request.method) + + # Handle curl's cryptic options for every individual HTTP method + if request.method in ("POST", "PUT"): + request_buffer = cStringIO.StringIO(utf8(request.body)) + curl.setopt(pycurl.READFUNCTION, request_buffer.read) + if request.method == "POST": + def ioctl(cmd): + if cmd == curl.IOCMD_RESTARTREAD: + request_buffer.seek(0) + curl.setopt(pycurl.IOCTLFUNCTION, ioctl) + curl.setopt(pycurl.POSTFIELDSIZE, len(request.body)) + else: + curl.setopt(pycurl.INFILESIZE, len(request.body)) + + if request.auth_username and request.auth_password: + userpwd = "%s:%s" % (request.auth_username, request.auth_password) + curl.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC) + curl.setopt(pycurl.USERPWD, userpwd) + logging.debug("%s %s (username: %r)", request.method, request.url, + request.auth_username) + else: + curl.unsetopt(pycurl.USERPWD) + logging.debug("%s %s", request.method, request.url) + + if request.client_key is not None or request.client_cert is not None: + raise ValueError("Client certificate not supported with curl_httpclient") + + if threading.activeCount() > 1: + # libcurl/pycurl is not thread-safe by default. When multiple threads + # are used, signals should be disabled. This has the side effect + # of disabling DNS timeouts in some environments (when libcurl is + # not linked against ares), so we don't do it when there is only one + # thread. Applications that use many short-lived threads may need + # to set NOSIGNAL manually in a prepare_curl_callback since + # there may not be any other threads running at the time we call + # threading.activeCount. + curl.setopt(pycurl.NOSIGNAL, 1) + if request.prepare_curl_callback is not None: + request.prepare_curl_callback(curl) + + +def _curl_header_callback(headers, header_line): + # header_line as returned by curl includes the end-of-line characters. + header_line = header_line.strip() + if header_line.startswith("HTTP/"): + headers.clear() + return + if not header_line: + return + headers.parse_line(header_line) + +def _curl_debug(debug_type, debug_msg): + debug_types = ('I', '<', '>', '<', '>') + if debug_type == 0: + logging.debug('%s', debug_msg.strip()) + elif debug_type in (1, 2): + for line in debug_msg.splitlines(): + logging.debug('%s %s', debug_types[debug_type], line) + elif debug_type == 4: + logging.debug('%s %r', debug_types[debug_type], debug_msg) + +if __name__ == "__main__": + AsyncHTTPClient.configure(CurlAsyncHTTPClient) + main() diff --git a/interactive-mining-madoap/madoap/src/tornado/database.py b/interactive-mining-madoap/madoap/src/tornado/database.py new file mode 100644 index 0000000..9771713 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/database.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""A lightweight wrapper around MySQLdb.""" + +import copy +import MySQLdb.constants +import MySQLdb.converters +import MySQLdb.cursors +import itertools +import logging +import time + +class Connection(object): + """A lightweight wrapper around MySQLdb DB-API connections. + + The main value we provide is wrapping rows in a dict/object so that + columns can be accessed by name. Typical usage:: + + db = database.Connection("localhost", "mydatabase") + for article in db.query("SELECT * FROM articles"): + print article.title + + Cursors are hidden by the implementation, but other than that, the methods + are very similar to the DB-API. + + We explicitly set the timezone to UTC and the character encoding to + UTF-8 on all connections to avoid time zone and encoding errors. + """ + def __init__(self, host, database, user=None, password=None, + max_idle_time=7*3600): + self.host = host + self.database = database + self.max_idle_time = max_idle_time + + args = dict(conv=CONVERSIONS, use_unicode=True, charset="utf8", + db=database, init_command='SET time_zone = "+0:00"', + sql_mode="TRADITIONAL") + if user is not None: + args["user"] = user + if password is not None: + args["passwd"] = password + + # We accept a path to a MySQL socket file or a host(:port) string + if "/" in host: + args["unix_socket"] = host + else: + self.socket = None + pair = host.split(":") + if len(pair) == 2: + args["host"] = pair[0] + args["port"] = int(pair[1]) + else: + args["host"] = host + args["port"] = 3306 + + self._db = None + self._db_args = args + self._last_use_time = time.time() + try: + self.reconnect() + except Exception: + logging.error("Cannot connect to MySQL on %s", self.host, + exc_info=True) + + def __del__(self): + self.close() + + def close(self): + """Closes this database connection.""" + if getattr(self, "_db", None) is not None: + self._db.close() + self._db = None + + def reconnect(self): + """Closes the existing database connection and re-opens it.""" + self.close() + self._db = MySQLdb.connect(**self._db_args) + self._db.autocommit(True) + + def iter(self, query, *parameters): + """Returns an iterator for the given query and parameters.""" + self._ensure_connected() + cursor = MySQLdb.cursors.SSCursor(self._db) + try: + self._execute(cursor, query, parameters) + column_names = [d[0] for d in cursor.description] + for row in cursor: + yield Row(zip(column_names, row)) + finally: + cursor.close() + + def query(self, query, *parameters): + """Returns a row list for the given query and parameters.""" + cursor = self._cursor() + try: + self._execute(cursor, query, parameters) + column_names = [d[0] for d in cursor.description] + return [Row(itertools.izip(column_names, row)) for row in cursor] + finally: + cursor.close() + + def get(self, query, *parameters): + """Returns the first row returned for the given query.""" + rows = self.query(query, *parameters) + if not rows: + return None + elif len(rows) > 1: + raise Exception("Multiple rows returned for Database.get() query") + else: + return rows[0] + + # rowcount is a more reasonable default return value than lastrowid, + # but for historical compatibility execute() must return lastrowid. + def execute(self, query, *parameters): + """Executes the given query, returning the lastrowid from the query.""" + return self.execute_lastrowid(query, *parameters) + + def execute_lastrowid(self, query, *parameters): + """Executes the given query, returning the lastrowid from the query.""" + cursor = self._cursor() + try: + self._execute(cursor, query, parameters) + return cursor.lastrowid + finally: + cursor.close() + + def execute_rowcount(self, query, *parameters): + """Executes the given query, returning the rowcount from the query.""" + cursor = self._cursor() + try: + self._execute(cursor, query, parameters) + return cursor.rowcount + finally: + cursor.close() + + def executemany(self, query, parameters): + """Executes the given query against all the given param sequences. + + We return the lastrowid from the query. + """ + return self.executemany_lastrowid(query, parameters) + + def executemany_lastrowid(self, query, parameters): + """Executes the given query against all the given param sequences. + + We return the lastrowid from the query. + """ + cursor = self._cursor() + try: + cursor.executemany(query, parameters) + return cursor.lastrowid + finally: + cursor.close() + + def executemany_rowcount(self, query, parameters): + """Executes the given query against all the given param sequences. + + We return the rowcount from the query. + """ + cursor = self._cursor() + try: + cursor.executemany(query, parameters) + return cursor.rowcount + finally: + cursor.close() + + def _ensure_connected(self): + # Mysql by default closes client connections that are idle for + # 8 hours, but the client library does not report this fact until + # you try to perform a query and it fails. Protect against this + # case by preemptively closing and reopening the connection + # if it has been idle for too long (7 hours by default). + if (self._db is None or + (time.time() - self._last_use_time > self.max_idle_time)): + self.reconnect() + self._last_use_time = time.time() + + def _cursor(self): + self._ensure_connected() + return self._db.cursor() + + def _execute(self, cursor, query, parameters): + try: + return cursor.execute(query, parameters) + except OperationalError: + logging.error("Error connecting to MySQL on %s", self.host) + self.close() + raise + + +class Row(dict): + """A dict that allows for object-like property access syntax.""" + def __getattr__(self, name): + try: + return self[name] + except KeyError: + raise AttributeError(name) + + +# Fix the access conversions to properly recognize unicode/binary +FIELD_TYPE = MySQLdb.constants.FIELD_TYPE +FLAG = MySQLdb.constants.FLAG +CONVERSIONS = copy.copy(MySQLdb.converters.conversions) + +field_types = [FIELD_TYPE.BLOB, FIELD_TYPE.STRING, FIELD_TYPE.VAR_STRING] +if 'VARCHAR' in vars(FIELD_TYPE): + field_types.append(FIELD_TYPE.VARCHAR) + +for field_type in field_types: + CONVERSIONS[field_type] = [(FLAG.BINARY, str)] + CONVERSIONS[field_type] + + +# Alias some common MySQL exceptions +IntegrityError = MySQLdb.IntegrityError +OperationalError = MySQLdb.OperationalError diff --git a/interactive-mining-madoap/madoap/src/tornado/epoll.c b/interactive-mining-madoap/madoap/src/tornado/epoll.c new file mode 100644 index 0000000..9a2e3a3 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/epoll.c @@ -0,0 +1,112 @@ +/* + * Copyright 2009 Facebook + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#include "Python.h" +#include +#include + +#define MAX_EVENTS 24 + +/* + * Simple wrapper around epoll_create. + */ +static PyObject* _epoll_create(void) { + int fd = epoll_create(MAX_EVENTS); + if (fd == -1) { + PyErr_SetFromErrno(PyExc_Exception); + return NULL; + } + + return PyInt_FromLong(fd); +} + +/* + * Simple wrapper around epoll_ctl. We throw an exception if the call fails + * rather than returning the error code since it is an infrequent (and likely + * catastrophic) event when it does happen. + */ +static PyObject* _epoll_ctl(PyObject* self, PyObject* args) { + int epfd, op, fd, events; + struct epoll_event event; + + if (!PyArg_ParseTuple(args, "iiiI", &epfd, &op, &fd, &events)) { + return NULL; + } + + memset(&event, 0, sizeof(event)); + event.events = events; + event.data.fd = fd; + if (epoll_ctl(epfd, op, fd, &event) == -1) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +/* + * Simple wrapper around epoll_wait. We return None if the call times out and + * throw an exception if an error occurs. Otherwise, we return a list of + * (fd, event) tuples. + */ +static PyObject* _epoll_wait(PyObject* self, PyObject* args) { + struct epoll_event events[MAX_EVENTS]; + int epfd, timeout, num_events, i; + PyObject* list; + PyObject* tuple; + + if (!PyArg_ParseTuple(args, "ii", &epfd, &timeout)) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + num_events = epoll_wait(epfd, events, MAX_EVENTS, timeout); + Py_END_ALLOW_THREADS + if (num_events == -1) { + PyErr_SetFromErrno(PyExc_Exception); + return NULL; + } + + list = PyList_New(num_events); + for (i = 0; i < num_events; i++) { + tuple = PyTuple_New(2); + PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(events[i].data.fd)); + PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(events[i].events)); + PyList_SET_ITEM(list, i, tuple); + } + return list; +} + +/* + * Our method declararations + */ +static PyMethodDef kEpollMethods[] = { + {"epoll_create", (PyCFunction)_epoll_create, METH_NOARGS, + "Create an epoll file descriptor"}, + {"epoll_ctl", _epoll_ctl, METH_VARARGS, + "Control an epoll file descriptor"}, + {"epoll_wait", _epoll_wait, METH_VARARGS, + "Wait for events on an epoll file descriptor"}, + {NULL, NULL, 0, NULL} +}; + +/* + * Module initialization + */ +PyMODINIT_FUNC initepoll(void) { + Py_InitModule("epoll", kEpollMethods); +} diff --git a/interactive-mining-madoap/madoap/src/tornado/escape.py b/interactive-mining-madoap/madoap/src/tornado/escape.py new file mode 100644 index 0000000..4010b1c --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/escape.py @@ -0,0 +1,327 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Escaping/unescaping methods for HTML, JSON, URLs, and others. + +Also includes a few other miscellaneous string manipulation functions that +have crept in over time. +""" + +import htmlentitydefs +import re +import sys +import urllib + +# Python3 compatibility: On python2.5, introduce the bytes alias from 2.6 +try: bytes +except Exception: bytes = str + +try: + from urlparse import parse_qs # Python 2.6+ +except ImportError: + from cgi import parse_qs + +# json module is in the standard library as of python 2.6; fall back to +# simplejson if present for older versions. +try: + import json + assert hasattr(json, "loads") and hasattr(json, "dumps") + _json_decode = json.loads + _json_encode = json.dumps +except Exception: + try: + import simplejson + _json_decode = lambda s: simplejson.loads(_unicode(s)) + _json_encode = lambda v: simplejson.dumps(v) + except ImportError: + try: + # For Google AppEngine + from django.utils import simplejson + _json_decode = lambda s: simplejson.loads(_unicode(s)) + _json_encode = lambda v: simplejson.dumps(v) + except ImportError: + def _json_decode(s): + raise NotImplementedError( + "A JSON parser is required, e.g., simplejson at " + "http://pypi.python.org/pypi/simplejson/") + _json_encode = _json_decode + + +_XHTML_ESCAPE_RE = re.compile('[&<>"]') +_XHTML_ESCAPE_DICT = {'&': '&', '<': '<', '>': '>', '"': '"'} +def xhtml_escape(value): + """Escapes a string so it is valid within XML or XHTML.""" + return _XHTML_ESCAPE_RE.sub(lambda match: _XHTML_ESCAPE_DICT[match.group(0)], + to_basestring(value)) + + +def xhtml_unescape(value): + """Un-escapes an XML-escaped string.""" + return re.sub(r"&(#?)(\w+?);", _convert_entity, _unicode(value)) + + +def json_encode(value): + """JSON-encodes the given Python object.""" + # JSON permits but does not require forward slashes to be escaped. + # This is useful when json data is emitted in a tags from prematurely terminating + # the javscript. Some json libraries do this escaping by default, + # although python's standard library does not, so we do it here. + # http://stackoverflow.com/questions/1580647/json-why-are-forward-slashes-escaped + return _json_encode(recursive_unicode(value)).replace("?@\[\]^`{|}~\s]))|(?:\((?:[^\s&()]|&|")*\)))+)""") + + +def linkify(text, shorten=False, extra_params="", + require_protocol=False, permitted_protocols=["http", "https"]): + """Converts plain text into HTML with links. + + For example: ``linkify("Hello http://tornadoweb.org!")`` would return + ``Hello http://tornadoweb.org!`` + + Parameters: + + shorten: Long urls will be shortened for display. + + extra_params: Extra text to include in the link tag, + e.g. linkify(text, extra_params='rel="nofollow" class="external"') + + require_protocol: Only linkify urls which include a protocol. If this is + False, urls such as www.facebook.com will also be linkified. + + permitted_protocols: List (or set) of protocols which should be linkified, + e.g. linkify(text, permitted_protocols=["http", "ftp", "mailto"]). + It is very unsafe to include protocols such as "javascript". + """ + if extra_params: + extra_params = " " + extra_params.strip() + + def make_link(m): + url = m.group(1) + proto = m.group(2) + if require_protocol and not proto: + return url # not protocol, no linkify + + if proto and proto not in permitted_protocols: + return url # bad protocol, no linkify + + href = m.group(1) + if not proto: + href = "http://" + href # no proto specified, use http + + params = extra_params + + # clip long urls. max_len is just an approximation + max_len = 30 + if shorten and len(url) > max_len: + before_clip = url + if proto: + proto_len = len(proto) + 1 + len(m.group(3) or "") # +1 for : + else: + proto_len = 0 + + parts = url[proto_len:].split("/") + if len(parts) > 1: + # Grab the whole host part plus the first bit of the path + # The path is usually not that interesting once shortened + # (no more slug, etc), so it really just provides a little + # extra indication of shortening. + url = url[:proto_len] + parts[0] + "/" + \ + parts[1][:8].split('?')[0].split('.')[0] + + if len(url) > max_len * 1.5: # still too long + url = url[:max_len] + + if url != before_clip: + amp = url.rfind('&') + # avoid splitting html char entities + if amp > max_len - 5: + url = url[:amp] + url += "..." + + if len(url) >= len(before_clip): + url = before_clip + else: + # full url is visible on mouse-over (for those who don't + # have a status bar, such as Safari by default) + params += ' title="%s"' % href + + return u'%s' % (href, params, url) + + # First HTML-escape so that our strings are all safe. + # The regex is modified to avoid character entites other than & so + # that we won't pick up ", etc. + text = _unicode(xhtml_escape(text)) + return _URL_RE.sub(make_link, text) + + +def _convert_entity(m): + if m.group(1) == "#": + try: + return unichr(int(m.group(2))) + except ValueError: + return "&#%s;" % m.group(2) + try: + return _HTML_UNICODE_MAP[m.group(2)] + except KeyError: + return "&%s;" % m.group(2) + + +def _build_unicode_map(): + unicode_map = {} + for name, value in htmlentitydefs.name2codepoint.iteritems(): + unicode_map[name] = unichr(value) + return unicode_map + +_HTML_UNICODE_MAP = _build_unicode_map() diff --git a/interactive-mining-madoap/madoap/src/tornado/gen.py b/interactive-mining-madoap/madoap/src/tornado/gen.py new file mode 100644 index 0000000..6f6b49a --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/gen.py @@ -0,0 +1,349 @@ +"""``tornado.gen`` is a generator-based interface to make it easier to +work in an asynchronous environment. Code using the ``gen`` module +is technically asynchronous, but it is written as a single generator +instead of a collection of separate functions. + +For example, the following asynchronous handler:: + + class AsyncHandler(RequestHandler): + @asynchronous + def get(self): + http_client = AsyncHTTPClient() + http_client.fetch("http://example.com", + callback=self.on_fetch) + + def on_fetch(self, response): + do_something_with_response(response) + self.render("template.html") + +could be written with ``gen`` as:: + + class GenAsyncHandler(RequestHandler): + @asynchronous + @gen.engine + def get(self): + http_client = AsyncHTTPClient() + response = yield gen.Task(http_client.fetch, "http://example.com") + do_something_with_response(response) + self.render("template.html") + +`Task` works with any function that takes a ``callback`` keyword +argument. You can also yield a list of ``Tasks``, which will be +started at the same time and run in parallel; a list of results will +be returned when they are all finished:: + + def get(self): + http_client = AsyncHTTPClient() + response1, response2 = yield [gen.Task(http_client.fetch, url1), + gen.Task(http_client.fetch, url2)] + +For more complicated interfaces, `Task` can be split into two parts: +`Callback` and `Wait`:: + + class GenAsyncHandler2(RequestHandler): + @asynchronous + @gen.engine + def get(self): + http_client = AsyncHTTPClient() + http_client.fetch("http://example.com", + callback=(yield gen.Callback("key")) + response = yield gen.Wait("key") + do_something_with_response(response) + self.render("template.html") + +The ``key`` argument to `Callback` and `Wait` allows for multiple +asynchronous operations to be started at different times and proceed +in parallel: yield several callbacks with different keys, then wait +for them once all the async operations have started. + +The result of a `Wait` or `Task` yield expression depends on how the callback +was run. If it was called with no arguments, the result is ``None``. If +it was called with one argument, the result is that argument. If it was +called with more than one argument or any keyword arguments, the result +is an `Arguments` object, which is a named tuple ``(args, kwargs)``. +""" + +import functools +import operator +import sys +import types + +class KeyReuseError(Exception): pass +class UnknownKeyError(Exception): pass +class LeakedCallbackError(Exception): pass +class BadYieldError(Exception): pass + +def engine(func): + """Decorator for asynchronous generators. + + Any generator that yields objects from this module must be wrapped + in this decorator. The decorator only works on functions that are + already asynchronous. For `~tornado.web.RequestHandler` + ``get``/``post``/etc methods, this means that both the `tornado.gen.engine` + and `tornado.web.asynchronous` decorators must be used (in either order). + In most other cases, it means that it doesn't make sense to use + ``gen.engine`` on functions that don't already take a callback argument. + """ + @functools.wraps(func) + def wrapper(*args, **kwargs): + gen = func(*args, **kwargs) + if isinstance(gen, types.GeneratorType): + Runner(gen).run() + return + assert gen is None, gen + # no yield, so we're done + return wrapper + +class YieldPoint(object): + """Base class for objects that may be yielded from the generator.""" + def start(self, runner): + """Called by the runner after the generator has yielded. + + No other methods will be called on this object before ``start``. + """ + raise NotImplementedError() + + def is_ready(self): + """Called by the runner to determine whether to resume the generator. + + Returns a boolean; may be called more than once. + """ + raise NotImplementedError() + + def get_result(self): + """Returns the value to use as the result of the yield expression. + + This method will only be called once, and only after `is_ready` + has returned true. + """ + raise NotImplementedError() + +class Callback(YieldPoint): + """Returns a callable object that will allow a matching `Wait` to proceed. + + The key may be any value suitable for use as a dictionary key, and is + used to match ``Callbacks`` to their corresponding ``Waits``. The key + must be unique among outstanding callbacks within a single run of the + generator function, but may be reused across different runs of the same + function (so constants generally work fine). + + The callback may be called with zero or one arguments; if an argument + is given it will be returned by `Wait`. + """ + def __init__(self, key): + self.key = key + + def start(self, runner): + self.runner = runner + runner.register_callback(self.key) + + def is_ready(self): + return True + + def get_result(self): + return self.runner.result_callback(self.key) + +class Wait(YieldPoint): + """Returns the argument passed to the result of a previous `Callback`.""" + def __init__(self, key): + self.key = key + + def start(self, runner): + self.runner = runner + + def is_ready(self): + return self.runner.is_ready(self.key) + + def get_result(self): + return self.runner.pop_result(self.key) + +class WaitAll(YieldPoint): + """Returns the results of multiple previous `Callbacks`. + + The argument is a sequence of `Callback` keys, and the result is + a list of results in the same order. + + `WaitAll` is equivalent to yielding a list of `Wait` objects. + """ + def __init__(self, keys): + self.keys = keys + + def start(self, runner): + self.runner = runner + + def is_ready(self): + return all(self.runner.is_ready(key) for key in self.keys) + + def get_result(self): + return [self.runner.pop_result(key) for key in self.keys] + + +class Task(YieldPoint): + """Runs a single asynchronous operation. + + Takes a function (and optional additional arguments) and runs it with + those arguments plus a ``callback`` keyword argument. The argument passed + to the callback is returned as the result of the yield expression. + + A `Task` is equivalent to a `Callback`/`Wait` pair (with a unique + key generated automatically):: + + result = yield gen.Task(func, args) + + func(args, callback=(yield gen.Callback(key))) + result = yield gen.Wait(key) + """ + def __init__(self, func, *args, **kwargs): + assert "callback" not in kwargs + self.args = args + self.kwargs = kwargs + self.func = func + + def start(self, runner): + self.runner = runner + self.key = object() + runner.register_callback(self.key) + self.kwargs["callback"] = runner.result_callback(self.key) + self.func(*self.args, **self.kwargs) + + def is_ready(self): + return self.runner.is_ready(self.key) + + def get_result(self): + return self.runner.pop_result(self.key) + +class Multi(YieldPoint): + """Runs multiple asynchronous operations in parallel. + + Takes a list of ``Tasks`` or other ``YieldPoints`` and returns a list of + their responses. It is not necessary to call `Multi` explicitly, + since the engine will do so automatically when the generator yields + a list of ``YieldPoints``. + """ + def __init__(self, children): + assert all(isinstance(i, YieldPoint) for i in children) + self.children = children + + def start(self, runner): + for i in self.children: + i.start(runner) + + def is_ready(self): + return all(i.is_ready() for i in self.children) + + def get_result(self): + return [i.get_result() for i in self.children] + +class _NullYieldPoint(YieldPoint): + def start(self, runner): + pass + def is_ready(self): + return True + def get_result(self): + return None + +class Runner(object): + """Internal implementation of `tornado.gen.engine`. + + Maintains information about pending callbacks and their results. + """ + def __init__(self, gen): + self.gen = gen + self.yield_point = _NullYieldPoint() + self.pending_callbacks = set() + self.results = {} + self.running = False + self.finished = False + self.exc_info = None + + def register_callback(self, key): + """Adds ``key`` to the list of callbacks.""" + if key in self.pending_callbacks: + raise KeyReuseError("key %r is already pending" % key) + self.pending_callbacks.add(key) + + def is_ready(self, key): + """Returns true if a result is available for ``key``.""" + if key not in self.pending_callbacks: + raise UnknownKeyError("key %r is not pending" % key) + return key in self.results + + def set_result(self, key, result): + """Sets the result for ``key`` and attempts to resume the generator.""" + self.results[key] = result + self.run() + + def pop_result(self, key): + """Returns the result for ``key`` and unregisters it.""" + self.pending_callbacks.remove(key) + return self.results.pop(key) + + def run(self): + """Starts or resumes the generator, running until it reaches a + yield point that is not ready. + """ + if self.running or self.finished: + return + try: + self.running = True + while True: + if self.exc_info is None: + try: + if not self.yield_point.is_ready(): + return + next = self.yield_point.get_result() + except Exception: + self.exc_info = sys.exc_info() + try: + if self.exc_info is not None: + exc_info = self.exc_info + self.exc_info = None + yielded = self.gen.throw(*exc_info) + else: + yielded = self.gen.send(next) + except StopIteration: + self.finished = True + if self.pending_callbacks: + raise LeakedCallbackError( + "finished without waiting for callbacks %r" % + self.pending_callbacks) + return + except Exception: + self.finished = True + raise + if isinstance(yielded, list): + yielded = Multi(yielded) + if isinstance(yielded, YieldPoint): + self.yield_point = yielded + self.yield_point.start(self) + else: + self.exc_info = (BadYieldError("yielded unknown object %r" % yielded),) + finally: + self.running = False + + def result_callback(self, key): + def inner(*args, **kwargs): + if kwargs or len(args) > 1: + result = Arguments(args, kwargs) + elif args: + result = args[0] + else: + result = None + self.set_result(key, result) + return inner + +# in python 2.6+ this could be a collections.namedtuple +class Arguments(tuple): + """The result of a yield expression whose callback had more than one + argument (or keyword arguments). + + The `Arguments` object can be used as a tuple ``(args, kwargs)`` + or an object with attributes ``args`` and ``kwargs``. + """ + __slots__ = () + + def __new__(cls, args, kwargs): + return tuple.__new__(cls, (args, kwargs)) + + args = property(operator.itemgetter(0)) + kwargs = property(operator.itemgetter(1)) diff --git a/interactive-mining-madoap/madoap/src/tornado/httpclient.py b/interactive-mining-madoap/madoap/src/tornado/httpclient.py new file mode 100644 index 0000000..b8f97c6 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/httpclient.py @@ -0,0 +1,408 @@ +"""Blocking and non-blocking HTTP client interfaces. + +This module defines a common interface shared by two implementations, +`simple_httpclient` and `curl_httpclient`. Applications may either +instantiate their chosen implementation class directly or use the +`AsyncHTTPClient` class from this module, which selects an implementation +that can be overridden with the `AsyncHTTPClient.configure` method. + +The default implementation is `simple_httpclient`, and this is expected +to be suitable for most users' needs. However, some applications may wish +to switch to `curl_httpclient` for reasons such as the following: + +* `curl_httpclient` is more likely to be compatible with sites that are + not-quite-compliant with the HTTP spec, or sites that use little-exercised + features of HTTP. + +* `simple_httpclient` only supports SSL on Python 2.6 and above. + +* `curl_httpclient` is faster + +* `curl_httpclient` was the default prior to Tornado 2.0. + +Note that if you are using `curl_httpclient`, it is highly recommended that +you use a recent version of ``libcurl`` and ``pycurl``. Currently the minimum +supported version is 7.18.2, and the recommended version is 7.21.1 or newer. +""" + +import calendar +import email.utils +import httplib +import time +import weakref + +from tornado.escape import utf8 +from tornado import httputil +from tornado.ioloop import IOLoop +from tornado.util import import_object, bytes_type + +class HTTPClient(object): + """A blocking HTTP client. + + This interface is provided for convenience and testing; most applications + that are running an IOLoop will want to use `AsyncHTTPClient` instead. + Typical usage looks like this:: + + http_client = httpclient.HTTPClient() + try: + response = http_client.fetch("http://www.google.com/") + print response.body + except httpclient.HTTPError, e: + print "Error:", e + """ + def __init__(self): + self._io_loop = IOLoop() + self._async_client = AsyncHTTPClient(self._io_loop) + self._response = None + self._closed = False + + def __del__(self): + self.close() + + def close(self): + """Closes the HTTPClient, freeing any resources used.""" + if not self._closed: + self._async_client.close() + self._io_loop.close() + self._closed = True + + def fetch(self, request, **kwargs): + """Executes a request, returning an `HTTPResponse`. + + The request may be either a string URL or an `HTTPRequest` object. + If it is a string, we construct an `HTTPRequest` using any additional + kwargs: ``HTTPRequest(request, **kwargs)`` + + If an error occurs during the fetch, we raise an `HTTPError`. + """ + def callback(response): + self._response = response + self._io_loop.stop() + self._async_client.fetch(request, callback, **kwargs) + self._io_loop.start() + response = self._response + self._response = None + response.rethrow() + return response + +class AsyncHTTPClient(object): + """An non-blocking HTTP client. + + Example usage:: + + import ioloop + + def handle_request(response): + if response.error: + print "Error:", response.error + else: + print response.body + ioloop.IOLoop.instance().stop() + + http_client = httpclient.AsyncHTTPClient() + http_client.fetch("http://www.google.com/", handle_request) + ioloop.IOLoop.instance().start() + + The constructor for this class is magic in several respects: It actually + creates an instance of an implementation-specific subclass, and instances + are reused as a kind of pseudo-singleton (one per IOLoop). The keyword + argument force_instance=True can be used to suppress this singleton + behavior. Constructor arguments other than io_loop and force_instance + are deprecated. The implementation subclass as well as arguments to + its constructor can be set with the static method configure() + """ + _impl_class = None + _impl_kwargs = None + + @classmethod + def _async_clients(cls): + assert cls is not AsyncHTTPClient, "should only be called on subclasses" + if not hasattr(cls, '_async_client_dict'): + cls._async_client_dict = weakref.WeakKeyDictionary() + return cls._async_client_dict + + def __new__(cls, io_loop=None, max_clients=10, force_instance=False, + **kwargs): + io_loop = io_loop or IOLoop.instance() + if cls is AsyncHTTPClient: + if cls._impl_class is None: + from tornado.simple_httpclient import SimpleAsyncHTTPClient + AsyncHTTPClient._impl_class = SimpleAsyncHTTPClient + impl = AsyncHTTPClient._impl_class + else: + impl = cls + if io_loop in impl._async_clients() and not force_instance: + return impl._async_clients()[io_loop] + else: + instance = super(AsyncHTTPClient, cls).__new__(impl) + args = {} + if cls._impl_kwargs: + args.update(cls._impl_kwargs) + args.update(kwargs) + instance.initialize(io_loop, max_clients, **args) + if not force_instance: + impl._async_clients()[io_loop] = instance + return instance + + def close(self): + """Destroys this http client, freeing any file descriptors used. + Not needed in normal use, but may be helpful in unittests that + create and destroy http clients. No other methods may be called + on the AsyncHTTPClient after close(). + """ + if self._async_clients().get(self.io_loop) is self: + del self._async_clients()[self.io_loop] + + def fetch(self, request, callback, **kwargs): + """Executes a request, calling callback with an `HTTPResponse`. + + The request may be either a string URL or an `HTTPRequest` object. + If it is a string, we construct an `HTTPRequest` using any additional + kwargs: ``HTTPRequest(request, **kwargs)`` + + If an error occurs during the fetch, the HTTPResponse given to the + callback has a non-None error attribute that contains the exception + encountered during the request. You can call response.rethrow() to + throw the exception (if any) in the callback. + """ + raise NotImplementedError() + + @staticmethod + def configure(impl, **kwargs): + """Configures the AsyncHTTPClient subclass to use. + + AsyncHTTPClient() actually creates an instance of a subclass. + This method may be called with either a class object or the + fully-qualified name of such a class (or None to use the default, + SimpleAsyncHTTPClient) + + If additional keyword arguments are given, they will be passed + to the constructor of each subclass instance created. The + keyword argument max_clients determines the maximum number of + simultaneous fetch() operations that can execute in parallel + on each IOLoop. Additional arguments may be supported depending + on the implementation class in use. + + Example:: + + AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient") + """ + if isinstance(impl, (unicode, bytes_type)): + impl = import_object(impl) + if impl is not None and not issubclass(impl, AsyncHTTPClient): + raise ValueError("Invalid AsyncHTTPClient implementation") + AsyncHTTPClient._impl_class = impl + AsyncHTTPClient._impl_kwargs = kwargs + +class HTTPRequest(object): + """HTTP client request object.""" + def __init__(self, url, method="GET", headers=None, body=None, + auth_username=None, auth_password=None, + connect_timeout=20.0, request_timeout=20.0, + if_modified_since=None, follow_redirects=True, + max_redirects=5, user_agent=None, use_gzip=True, + network_interface=None, streaming_callback=None, + header_callback=None, prepare_curl_callback=None, + proxy_host=None, proxy_port=None, proxy_username=None, + proxy_password='', allow_nonstandard_methods=False, + validate_cert=True, ca_certs=None, + allow_ipv6=None, + client_key=None, client_cert=None): + """Creates an `HTTPRequest`. + + All parameters except `url` are optional. + + :arg string url: URL to fetch + :arg string method: HTTP method, e.g. "GET" or "POST" + :arg headers: Additional HTTP headers to pass on the request + :type headers: `~tornado.httputil.HTTPHeaders` or `dict` + :arg string auth_username: Username for HTTP "Basic" authentication + :arg string auth_password: Password for HTTP "Basic" authentication + :arg float connect_timeout: Timeout for initial connection in seconds + :arg float request_timeout: Timeout for entire request in seconds + :arg datetime if_modified_since: Timestamp for ``If-Modified-Since`` + header + :arg bool follow_redirects: Should redirects be followed automatically + or return the 3xx response? + :arg int max_redirects: Limit for `follow_redirects` + :arg string user_agent: String to send as ``User-Agent`` header + :arg bool use_gzip: Request gzip encoding from the server + :arg string network_interface: Network interface to use for request + :arg callable streaming_callback: If set, `streaming_callback` will + be run with each chunk of data as it is received, and + `~HTTPResponse.body` and `~HTTPResponse.buffer` will be empty in + the final response. + :arg callable header_callback: If set, `header_callback` will + be run with each header line as it is received, and + `~HTTPResponse.headers` will be empty in the final response. + :arg callable prepare_curl_callback: If set, will be called with + a `pycurl.Curl` object to allow the application to make additional + `setopt` calls. + :arg string proxy_host: HTTP proxy hostname. To use proxies, + `proxy_host` and `proxy_port` must be set; `proxy_username` and + `proxy_pass` are optional. Proxies are currently only support + with `curl_httpclient`. + :arg int proxy_port: HTTP proxy port + :arg string proxy_username: HTTP proxy username + :arg string proxy_password: HTTP proxy password + :arg bool allow_nonstandard_methods: Allow unknown values for `method` + argument? + :arg bool validate_cert: For HTTPS requests, validate the server's + certificate? + :arg string ca_certs: filename of CA certificates in PEM format, + or None to use defaults. Note that in `curl_httpclient`, if + any request uses a custom `ca_certs` file, they all must (they + don't have to all use the same `ca_certs`, but it's not possible + to mix requests with ca_certs and requests that use the defaults. + :arg bool allow_ipv6: Use IPv6 when available? Default is false in + `simple_httpclient` and true in `curl_httpclient` + :arg string client_key: Filename for client SSL key, if any + :arg string client_cert: Filename for client SSL certificate, if any + """ + if headers is None: + headers = httputil.HTTPHeaders() + if if_modified_since: + timestamp = calendar.timegm(if_modified_since.utctimetuple()) + headers["If-Modified-Since"] = email.utils.formatdate( + timestamp, localtime=False, usegmt=True) + self.proxy_host = proxy_host + self.proxy_port = proxy_port + self.proxy_username = proxy_username + self.proxy_password = proxy_password + self.url = url + self.method = method + self.headers = headers + self.body = utf8(body) + self.auth_username = auth_username + self.auth_password = auth_password + self.connect_timeout = connect_timeout + self.request_timeout = request_timeout + self.follow_redirects = follow_redirects + self.max_redirects = max_redirects + self.user_agent = user_agent + self.use_gzip = use_gzip + self.network_interface = network_interface + self.streaming_callback = streaming_callback + self.header_callback = header_callback + self.prepare_curl_callback = prepare_curl_callback + self.allow_nonstandard_methods = allow_nonstandard_methods + self.validate_cert = validate_cert + self.ca_certs = ca_certs + self.allow_ipv6 = allow_ipv6 + self.client_key = client_key + self.client_cert = client_cert + self.start_time = time.time() + + +class HTTPResponse(object): + """HTTP Response object. + + Attributes: + + * request: HTTPRequest object + + * code: numeric HTTP status code, e.g. 200 or 404 + + * headers: httputil.HTTPHeaders object + + * buffer: cStringIO object for response body + + * body: respose body as string (created on demand from self.buffer) + + * error: Exception object, if any + + * request_time: seconds from request start to finish + + * time_info: dictionary of diagnostic timing information from the request. + Available data are subject to change, but currently uses timings + available from http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html, + plus 'queue', which is the delay (if any) introduced by waiting for + a slot under AsyncHTTPClient's max_clients setting. + """ + def __init__(self, request, code, headers={}, buffer=None, + effective_url=None, error=None, request_time=None, + time_info={}): + self.request = request + self.code = code + self.headers = headers + self.buffer = buffer + self._body = None + if effective_url is None: + self.effective_url = request.url + else: + self.effective_url = effective_url + if error is None: + if self.code < 200 or self.code >= 300: + self.error = HTTPError(self.code, response=self) + else: + self.error = None + else: + self.error = error + self.request_time = request_time + self.time_info = time_info + + def _get_body(self): + if self.buffer is None: + return None + elif self._body is None: + self._body = self.buffer.getvalue() + + return self._body + + body = property(_get_body) + + def rethrow(self): + """If there was an error on the request, raise an `HTTPError`.""" + if self.error: + raise self.error + + def __repr__(self): + args = ",".join("%s=%r" % i for i in self.__dict__.iteritems()) + return "%s(%s)" % (self.__class__.__name__, args) + + +class HTTPError(Exception): + """Exception thrown for an unsuccessful HTTP request. + + Attributes: + + code - HTTP error integer error code, e.g. 404. Error code 599 is + used when no HTTP response was received, e.g. for a timeout. + + response - HTTPResponse object, if any. + + Note that if follow_redirects is False, redirects become HTTPErrors, + and you can look at error.response.headers['Location'] to see the + destination of the redirect. + """ + def __init__(self, code, message=None, response=None): + self.code = code + message = message or httplib.responses.get(code, "Unknown") + self.response = response + Exception.__init__(self, "HTTP %d: %s" % (self.code, message)) + + +def main(): + from tornado.options import define, options, parse_command_line + define("print_headers", type=bool, default=False) + define("print_body", type=bool, default=True) + define("follow_redirects", type=bool, default=True) + args = parse_command_line() + client = HTTPClient() + for arg in args: + try: + response = client.fetch(arg, + follow_redirects=options.follow_redirects) + except HTTPError, e: + if e.response is not None: + response = e.response + else: + raise + if options.print_headers: + print response.headers + if options.print_body: + print response.body + client.close() + +if __name__ == "__main__": + main() diff --git a/interactive-mining-madoap/madoap/src/tornado/httpserver.py b/interactive-mining-madoap/madoap/src/tornado/httpserver.py new file mode 100644 index 0000000..74f1a8a --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/httpserver.py @@ -0,0 +1,459 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""A non-blocking, single-threaded HTTP server. + +Typical applications have little direct interaction with the `HTTPServer` +class except to start a server at the beginning of the process +(and even that is often done indirectly via `tornado.web.Application.listen`). + +This module also defines the `HTTPRequest` class which is exposed via +`tornado.web.RequestHandler.request`. +""" + +import Cookie +import logging +import socket +import time +import urlparse + +from tornado.escape import utf8, native_str, parse_qs_bytes +from tornado import httputil +from tornado import iostream +from tornado.netutil import TCPServer +from tornado import stack_context +from tornado.util import b, bytes_type + +try: + import ssl # Python 2.6+ +except ImportError: + ssl = None + +class HTTPServer(TCPServer): + r"""A non-blocking, single-threaded HTTP server. + + A server is defined by a request callback that takes an HTTPRequest + instance as an argument and writes a valid HTTP response with + `HTTPRequest.write`. `HTTPRequest.finish` finishes the request (but does + not necessarily close the connection in the case of HTTP/1.1 keep-alive + requests). A simple example server that echoes back the URI you + requested:: + + import httpserver + import ioloop + + def handle_request(request): + message = "You requested %s\n" % request.uri + request.write("HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s" % ( + len(message), message)) + request.finish() + + http_server = httpserver.HTTPServer(handle_request) + http_server.listen(8888) + ioloop.IOLoop.instance().start() + + `HTTPServer` is a very basic connection handler. Beyond parsing the + HTTP request body and headers, the only HTTP semantics implemented + in `HTTPServer` is HTTP/1.1 keep-alive connections. We do not, however, + implement chunked encoding, so the request callback must provide a + ``Content-Length`` header or implement chunked encoding for HTTP/1.1 + requests for the server to run correctly for HTTP/1.1 clients. If + the request handler is unable to do this, you can provide the + ``no_keep_alive`` argument to the `HTTPServer` constructor, which will + ensure the connection is closed on every request no matter what HTTP + version the client is using. + + If ``xheaders`` is ``True``, we support the ``X-Real-Ip`` and ``X-Scheme`` + headers, which override the remote IP and HTTP scheme for all requests. + These headers are useful when running Tornado behind a reverse proxy or + load balancer. + + `HTTPServer` can serve SSL traffic with Python 2.6+ and OpenSSL. + To make this server serve SSL traffic, send the ssl_options dictionary + argument with the arguments required for the `ssl.wrap_socket` method, + including "certfile" and "keyfile":: + + HTTPServer(applicaton, ssl_options={ + "certfile": os.path.join(data_dir, "mydomain.crt"), + "keyfile": os.path.join(data_dir, "mydomain.key"), + }) + + `HTTPServer` initialization follows one of three patterns (the + initialization methods are defined on `tornado.netutil.TCPServer`): + + 1. `~tornado.netutil.TCPServer.listen`: simple single-process:: + + server = HTTPServer(app) + server.listen(8888) + IOLoop.instance().start() + + In many cases, `tornado.web.Application.listen` can be used to avoid + the need to explicitly create the `HTTPServer`. + + 2. `~tornado.netutil.TCPServer.bind`/`~tornado.netutil.TCPServer.start`: + simple multi-process:: + + server = HTTPServer(app) + server.bind(8888) + server.start(0) # Forks multiple sub-processes + IOLoop.instance().start() + + When using this interface, an `IOLoop` must *not* be passed + to the `HTTPServer` constructor. `start` will always start + the server on the default singleton `IOLoop`. + + 3. `~tornado.netutil.TCPServer.add_sockets`: advanced multi-process:: + + sockets = tornado.netutil.bind_sockets(8888) + tornado.process.fork_processes(0) + server = HTTPServer(app) + server.add_sockets(sockets) + IOLoop.instance().start() + + The `add_sockets` interface is more complicated, but it can be + used with `tornado.process.fork_processes` to give you more + flexibility in when the fork happens. `add_sockets` can + also be used in single-process servers if you want to create + your listening sockets in some way other than + `tornado.netutil.bind_sockets`. + + """ + def __init__(self, request_callback, no_keep_alive=False, io_loop=None, + xheaders=False, ssl_options=None, **kwargs): + self.request_callback = request_callback + self.no_keep_alive = no_keep_alive + self.xheaders = xheaders + TCPServer.__init__(self, io_loop=io_loop, ssl_options=ssl_options, + **kwargs) + + def handle_stream(self, stream, address): + HTTPConnection(stream, address, self.request_callback, + self.no_keep_alive, self.xheaders) + +class _BadRequestException(Exception): + """Exception class for malformed HTTP requests.""" + pass + +class HTTPConnection(object): + """Handles a connection to an HTTP client, executing HTTP requests. + + We parse HTTP headers and bodies, and execute the request callback + until the HTTP conection is closed. + """ + def __init__(self, stream, address, request_callback, no_keep_alive=False, + xheaders=False): + self.stream = stream + if self.stream.socket.family not in (socket.AF_INET, socket.AF_INET6): + # Unix (or other) socket; fake the remote address + address = ('0.0.0.0', 0) + self.address = address + self.request_callback = request_callback + self.no_keep_alive = no_keep_alive + self.xheaders = xheaders + self._request = None + self._request_finished = False + # Save stack context here, outside of any request. This keeps + # contexts from one request from leaking into the next. + self._header_callback = stack_context.wrap(self._on_headers) + self.stream.read_until(b("\r\n\r\n"), self._header_callback) + self._write_callback = None + + def write(self, chunk, callback=None): + """Writes a chunk of output to the stream.""" + assert self._request, "Request closed" + if not self.stream.closed(): + self._write_callback = stack_context.wrap(callback) + self.stream.write(chunk, self._on_write_complete) + + def finish(self): + """Finishes the request.""" + assert self._request, "Request closed" + self._request_finished = True + if not self.stream.writing(): + self._finish_request() + + def _on_write_complete(self): + if self._write_callback is not None: + callback = self._write_callback + self._write_callback = None + callback() + # _on_write_complete is enqueued on the IOLoop whenever the + # IOStream's write buffer becomes empty, but it's possible for + # another callback that runs on the IOLoop before it to + # simultaneously write more data and finish the request. If + # there is still data in the IOStream, a future + # _on_write_complete will be responsible for calling + # _finish_request. + if self._request_finished and not self.stream.writing(): + self._finish_request() + + def _finish_request(self): + if self.no_keep_alive: + disconnect = True + else: + connection_header = self._request.headers.get("Connection") + if self._request.supports_http_1_1(): + disconnect = connection_header == "close" + elif ("Content-Length" in self._request.headers + or self._request.method in ("HEAD", "GET")): + disconnect = connection_header != "Keep-Alive" + else: + disconnect = True + self._request = None + self._request_finished = False + if disconnect: + self.stream.close() + return + self.stream.read_until(b("\r\n\r\n"), self._header_callback) + + def _on_headers(self, data): + try: + data = native_str(data.decode('latin1')) + eol = data.find("\r\n") + start_line = data[:eol] + try: + method, uri, version = start_line.split(" ") + except ValueError: + raise _BadRequestException("Malformed HTTP request line") + if not version.startswith("HTTP/"): + raise _BadRequestException("Malformed HTTP version in HTTP Request-Line") + headers = httputil.HTTPHeaders.parse(data[eol:]) + self._request = HTTPRequest( + connection=self, method=method, uri=uri, version=version, + headers=headers, remote_ip=self.address[0]) + + content_length = headers.get("Content-Length") + if content_length: + content_length = int(content_length) + if content_length > self.stream.max_buffer_size: + raise _BadRequestException("Content-Length too long") + if headers.get("Expect") == "100-continue": + self.stream.write(b("HTTP/1.1 100 (Continue)\r\n\r\n")) + self.stream.read_bytes(content_length, self._on_request_body) + return + + self.request_callback(self._request) + except _BadRequestException, e: + logging.info("Malformed HTTP request from %s: %s", + self.address[0], e) + self.stream.close() + return + + def _on_request_body(self, data): + self._request.body = data + content_type = self._request.headers.get("Content-Type", "") + if self._request.method in ("POST", "PUT"): + if content_type.startswith("application/x-www-form-urlencoded"): + arguments = parse_qs_bytes(native_str(self._request.body)) + for name, values in arguments.iteritems(): + values = [v for v in values if v] + if values: + self._request.arguments.setdefault(name, []).extend( + values) + elif content_type.startswith("multipart/form-data"): + fields = content_type.split(";") + for field in fields: + k, sep, v = field.strip().partition("=") + if k == "boundary" and v: + httputil.parse_multipart_form_data( + utf8(v), data, + self._request.arguments, + self._request.files) + break + else: + logging.warning("Invalid multipart/form-data") + self.request_callback(self._request) + + +class HTTPRequest(object): + """A single HTTP request. + + All attributes are type `str` unless otherwise noted. + + .. attribute:: method + + HTTP request method, e.g. "GET" or "POST" + + .. attribute:: uri + + The requested uri. + + .. attribute:: path + + The path portion of `uri` + + .. attribute:: query + + The query portion of `uri` + + .. attribute:: version + + HTTP version specified in request, e.g. "HTTP/1.1" + + .. attribute:: headers + + `HTTPHeader` dictionary-like object for request headers. Acts like + a case-insensitive dictionary with additional methods for repeated + headers. + + .. attribute:: body + + Request body, if present, as a byte string. + + .. attribute:: remote_ip + + Client's IP address as a string. If `HTTPServer.xheaders` is set, + will pass along the real IP address provided by a load balancer + in the ``X-Real-Ip`` header + + .. attribute:: protocol + + The protocol used, either "http" or "https". If `HTTPServer.xheaders` + is seet, will pass along the protocol used by a load balancer if + reported via an ``X-Scheme`` header. + + .. attribute:: host + + The requested hostname, usually taken from the ``Host`` header. + + .. attribute:: arguments + + GET/POST arguments are available in the arguments property, which + maps arguments names to lists of values (to support multiple values + for individual names). Names are of type `str`, while arguments + are byte strings. Note that this is different from + `RequestHandler.get_argument`, which returns argument values as + unicode strings. + + .. attribute:: files + + File uploads are available in the files property, which maps file + names to lists of :class:`HTTPFile`. + + .. attribute:: connection + + An HTTP request is attached to a single HTTP connection, which can + be accessed through the "connection" attribute. Since connections + are typically kept open in HTTP/1.1, multiple requests can be handled + sequentially on a single connection. + """ + def __init__(self, method, uri, version="HTTP/1.0", headers=None, + body=None, remote_ip=None, protocol=None, host=None, + files=None, connection=None): + self.method = method + self.uri = uri + self.version = version + self.headers = headers or httputil.HTTPHeaders() + self.body = body or "" + if connection and connection.xheaders: + # Squid uses X-Forwarded-For, others use X-Real-Ip + self.remote_ip = self.headers.get( + "X-Real-Ip", self.headers.get("X-Forwarded-For", remote_ip)) + # AWS uses X-Forwarded-Proto + self.protocol = self.headers.get( + "X-Scheme", self.headers.get("X-Forwarded-Proto", protocol)) + if self.protocol not in ("http", "https"): + self.protocol = "http" + else: + self.remote_ip = remote_ip + if protocol: + self.protocol = protocol + elif connection and isinstance(connection.stream, + iostream.SSLIOStream): + self.protocol = "https" + else: + self.protocol = "http" + self.host = host or self.headers.get("Host") or "127.0.0.1" + self.files = files or {} + self.connection = connection + self._start_time = time.time() + self._finish_time = None + + scheme, netloc, path, query, fragment = urlparse.urlsplit(native_str(uri)) + self.path = path + self.query = query + arguments = parse_qs_bytes(query) + self.arguments = {} + for name, values in arguments.iteritems(): + values = [v for v in values if v] + if values: self.arguments[name] = values + + def supports_http_1_1(self): + """Returns True if this request supports HTTP/1.1 semantics""" + return self.version == "HTTP/1.1" + + @property + def cookies(self): + """A dictionary of Cookie.Morsel objects.""" + if not hasattr(self, "_cookies"): + self._cookies = Cookie.SimpleCookie() + if "Cookie" in self.headers: + try: + self._cookies.load( + native_str(self.headers["Cookie"])) + except Exception: + self._cookies = None + return self._cookies + + def write(self, chunk, callback=None): + """Writes the given chunk to the response stream.""" + assert isinstance(chunk, bytes_type) + self.connection.write(chunk, callback=callback) + + def finish(self): + """Finishes this HTTP request on the open connection.""" + self.connection.finish() + self._finish_time = time.time() + + def full_url(self): + """Reconstructs the full URL for this request.""" + return self.protocol + "://" + self.host + self.uri + + def request_time(self): + """Returns the amount of time it took for this request to execute.""" + if self._finish_time is None: + return time.time() - self._start_time + else: + return self._finish_time - self._start_time + + def get_ssl_certificate(self): + """Returns the client's SSL certificate, if any. + + To use client certificates, the HTTPServer must have been constructed + with cert_reqs set in ssl_options, e.g.:: + + server = HTTPServer(app, + ssl_options=dict( + certfile="foo.crt", + keyfile="foo.key", + cert_reqs=ssl.CERT_REQUIRED, + ca_certs="cacert.crt")) + + The return value is a dictionary, see SSLSocket.getpeercert() in + the standard library for more details. + http://docs.python.org/library/ssl.html#sslsocket-objects + """ + try: + return self.connection.stream.socket.getpeercert() + except ssl.SSLError: + return None + + def __repr__(self): + attrs = ("protocol", "host", "method", "uri", "version", "remote_ip", + "body") + args = ", ".join(["%s=%r" % (n, getattr(self, n)) for n in attrs]) + return "%s(%s, headers=%s)" % ( + self.__class__.__name__, args, dict(self.headers)) diff --git a/interactive-mining-madoap/madoap/src/tornado/httputil.py b/interactive-mining-madoap/madoap/src/tornado/httputil.py new file mode 100644 index 0000000..8aec4b4 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/httputil.py @@ -0,0 +1,280 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""HTTP utility code shared by clients and servers.""" + +import logging +import urllib +import re + +from tornado.util import b, ObjectDict + +class HTTPHeaders(dict): + """A dictionary that maintains Http-Header-Case for all keys. + + Supports multiple values per key via a pair of new methods, + add() and get_list(). The regular dictionary interface returns a single + value per key, with multiple values joined by a comma. + + >>> h = HTTPHeaders({"content-type": "text/html"}) + >>> h.keys() + ['Content-Type'] + >>> h["Content-Type"] + 'text/html' + + >>> h.add("Set-Cookie", "A=B") + >>> h.add("Set-Cookie", "C=D") + >>> h["set-cookie"] + 'A=B,C=D' + >>> h.get_list("set-cookie") + ['A=B', 'C=D'] + + >>> for (k,v) in sorted(h.get_all()): + ... print '%s: %s' % (k,v) + ... + Content-Type: text/html + Set-Cookie: A=B + Set-Cookie: C=D + """ + def __init__(self, *args, **kwargs): + # Don't pass args or kwargs to dict.__init__, as it will bypass + # our __setitem__ + dict.__init__(self) + self._as_list = {} + self._last_key = None + self.update(*args, **kwargs) + + # new public methods + + def add(self, name, value): + """Adds a new value for the given key.""" + norm_name = HTTPHeaders._normalize_name(name) + self._last_key = norm_name + if norm_name in self: + # bypass our override of __setitem__ since it modifies _as_list + dict.__setitem__(self, norm_name, self[norm_name] + ',' + value) + self._as_list[norm_name].append(value) + else: + self[norm_name] = value + + def get_list(self, name): + """Returns all values for the given header as a list.""" + norm_name = HTTPHeaders._normalize_name(name) + return self._as_list.get(norm_name, []) + + def get_all(self): + """Returns an iterable of all (name, value) pairs. + + If a header has multiple values, multiple pairs will be + returned with the same name. + """ + for name, list in self._as_list.iteritems(): + for value in list: + yield (name, value) + + def parse_line(self, line): + """Updates the dictionary with a single header line. + + >>> h = HTTPHeaders() + >>> h.parse_line("Content-Type: text/html") + >>> h.get('content-type') + 'text/html' + """ + if line[0].isspace(): + # continuation of a multi-line header + new_part = ' ' + line.lstrip() + self._as_list[self._last_key][-1] += new_part + dict.__setitem__(self, self._last_key, + self[self._last_key] + new_part) + else: + name, value = line.split(":", 1) + self.add(name, value.strip()) + + @classmethod + def parse(cls, headers): + """Returns a dictionary from HTTP header text. + + >>> h = HTTPHeaders.parse("Content-Type: text/html\\r\\nContent-Length: 42\\r\\n") + >>> sorted(h.iteritems()) + [('Content-Length', '42'), ('Content-Type', 'text/html')] + """ + h = cls() + for line in headers.splitlines(): + if line: + h.parse_line(line) + return h + + # dict implementation overrides + + def __setitem__(self, name, value): + norm_name = HTTPHeaders._normalize_name(name) + dict.__setitem__(self, norm_name, value) + self._as_list[norm_name] = [value] + + def __getitem__(self, name): + return dict.__getitem__(self, HTTPHeaders._normalize_name(name)) + + def __delitem__(self, name): + norm_name = HTTPHeaders._normalize_name(name) + dict.__delitem__(self, norm_name) + del self._as_list[norm_name] + + def __contains__(self, name): + norm_name = HTTPHeaders._normalize_name(name) + return dict.__contains__(self, norm_name) + + def get(self, name, default=None): + return dict.get(self, HTTPHeaders._normalize_name(name), default) + + def update(self, *args, **kwargs): + # dict.update bypasses our __setitem__ + for k, v in dict(*args, **kwargs).iteritems(): + self[k] = v + + _NORMALIZED_HEADER_RE = re.compile(r'^[A-Z0-9][a-z0-9]*(-[A-Z0-9][a-z0-9]*)*$') + _normalized_headers = {} + + @staticmethod + def _normalize_name(name): + """Converts a name to Http-Header-Case. + + >>> HTTPHeaders._normalize_name("coNtent-TYPE") + 'Content-Type' + """ + try: + return HTTPHeaders._normalized_headers[name] + except KeyError: + if HTTPHeaders._NORMALIZED_HEADER_RE.match(name): + normalized = name + else: + normalized = "-".join([w.capitalize() for w in name.split("-")]) + HTTPHeaders._normalized_headers[name] = normalized + return normalized + + +def url_concat(url, args): + """Concatenate url and argument dictionary regardless of whether + url has existing query parameters. + + >>> url_concat("http://example.com/foo?a=b", dict(c="d")) + 'http://example.com/foo?a=b&c=d' + """ + if not args: return url + if url[-1] not in ('?', '&'): + url += '&' if ('?' in url) else '?' + return url + urllib.urlencode(args) + + +class HTTPFile(ObjectDict): + """Represents an HTTP file. For backwards compatibility, its instance + attributes are also accessible as dictionary keys. + + :ivar filename: + :ivar body: + :ivar content_type: The content_type comes from the provided HTTP header + and should not be trusted outright given that it can be easily forged. + """ + pass + + +def parse_multipart_form_data(boundary, data, arguments, files): + """Parses a multipart/form-data body. + + The boundary and data parameters are both byte strings. + The dictionaries given in the arguments and files parameters + will be updated with the contents of the body. + """ + # The standard allows for the boundary to be quoted in the header, + # although it's rare (it happens at least for google app engine + # xmpp). I think we're also supposed to handle backslash-escapes + # here but I'll save that until we see a client that uses them + # in the wild. + if boundary.startswith(b('"')) and boundary.endswith(b('"')): + boundary = boundary[1:-1] + if data.endswith(b("\r\n")): + footer_length = len(boundary) + 6 + else: + footer_length = len(boundary) + 4 + parts = data[:-footer_length].split(b("--") + boundary + b("\r\n")) + for part in parts: + if not part: continue + eoh = part.find(b("\r\n\r\n")) + if eoh == -1: + logging.warning("multipart/form-data missing headers") + continue + headers = HTTPHeaders.parse(part[:eoh].decode("utf-8")) + disp_header = headers.get("Content-Disposition", "") + disposition, disp_params = _parse_header(disp_header) + if disposition != "form-data" or not part.endswith(b("\r\n")): + logging.warning("Invalid multipart/form-data") + continue + value = part[eoh + 4:-2] + if not disp_params.get("name"): + logging.warning("multipart/form-data value missing name") + continue + name = disp_params["name"] + if disp_params.get("filename"): + ctype = headers.get("Content-Type", "application/unknown") + files.setdefault(name, []).append(HTTPFile( + filename=disp_params["filename"], body=value, + content_type=ctype)) + else: + arguments.setdefault(name, []).append(value) + + +# _parseparam and _parse_header are copied and modified from python2.7's cgi.py +# The original 2.7 version of this code did not correctly support some +# combinations of semicolons and double quotes. +def _parseparam(s): + while s[:1] == ';': + s = s[1:] + end = s.find(';') + while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2: + end = s.find(';', end + 1) + if end < 0: + end = len(s) + f = s[:end] + yield f.strip() + s = s[end:] + +def _parse_header(line): + """Parse a Content-type like header. + + Return the main content-type and a dictionary of options. + + """ + parts = _parseparam(';' + line) + key = parts.next() + pdict = {} + for p in parts: + i = p.find('=') + if i >= 0: + name = p[:i].strip().lower() + value = p[i+1:].strip() + if len(value) >= 2 and value[0] == value[-1] == '"': + value = value[1:-1] + value = value.replace('\\\\', '\\').replace('\\"', '"') + pdict[name] = value + return key, pdict + + +def doctests(): + import doctest + return doctest.DocTestSuite() + +if __name__ == "__main__": + import doctest + doctest.testmod() diff --git a/interactive-mining-madoap/madoap/src/tornado/ioloop.py b/interactive-mining-madoap/madoap/src/tornado/ioloop.py new file mode 100644 index 0000000..bcf5d52 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/ioloop.py @@ -0,0 +1,636 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""An I/O event loop for non-blocking sockets. + +Typical applications will use a single `IOLoop` object, in the +`IOLoop.instance` singleton. The `IOLoop.start` method should usually +be called at the end of the ``main()`` function. Atypical applications may +use more than one `IOLoop`, such as one `IOLoop` per thread, or per `unittest` +case. + +In addition to I/O events, the `IOLoop` can also schedule time-based events. +`IOLoop.add_timeout` is a non-blocking alternative to `time.sleep`. +""" + +from __future__ import with_statement + +import datetime +import errno +import heapq +import os +import logging +import select +import thread +import threading +import time +import traceback + +from tornado import stack_context + +try: + import signal +except ImportError: + signal = None + +from tornado.platform.auto import set_close_exec, Waker + + +class IOLoop(object): + """A level-triggered I/O loop. + + We use epoll (Linux) or kqueue (BSD and Mac OS X; requires python + 2.6+) if they are available, or else we fall back on select(). If + you are implementing a system that needs to handle thousands of + simultaneous connections, you should use a system that supports either + epoll or queue. + + Example usage for a simple TCP server:: + + import errno + import functools + import ioloop + import socket + + def connection_ready(sock, fd, events): + while True: + try: + connection, address = sock.accept() + except socket.error, e: + if e.args[0] not in (errno.EWOULDBLOCK, errno.EAGAIN): + raise + return + connection.setblocking(0) + handle_connection(connection, address) + + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.setblocking(0) + sock.bind(("", port)) + sock.listen(128) + + io_loop = ioloop.IOLoop.instance() + callback = functools.partial(connection_ready, sock) + io_loop.add_handler(sock.fileno(), callback, io_loop.READ) + io_loop.start() + + """ + # Constants from the epoll module + _EPOLLIN = 0x001 + _EPOLLPRI = 0x002 + _EPOLLOUT = 0x004 + _EPOLLERR = 0x008 + _EPOLLHUP = 0x010 + _EPOLLRDHUP = 0x2000 + _EPOLLONESHOT = (1 << 30) + _EPOLLET = (1 << 31) + + # Our events map exactly to the epoll events + NONE = 0 + READ = _EPOLLIN + WRITE = _EPOLLOUT + ERROR = _EPOLLERR | _EPOLLHUP + + def __init__(self, impl=None): + self._impl = impl or _poll() + if hasattr(self._impl, 'fileno'): + set_close_exec(self._impl.fileno()) + self._handlers = {} + self._events = {} + self._callbacks = [] + self._callback_lock = threading.Lock() + self._timeouts = [] + self._running = False + self._stopped = False + self._thread_ident = None + self._blocking_signal_threshold = None + + # Create a pipe that we send bogus data to when we want to wake + # the I/O loop when it is idle + self._waker = Waker() + self.add_handler(self._waker.fileno(), + lambda fd, events: self._waker.consume(), + self.READ) + + @staticmethod + def instance(): + """Returns a global IOLoop instance. + + Most single-threaded applications have a single, global IOLoop. + Use this method instead of passing around IOLoop instances + throughout your code. + + A common pattern for classes that depend on IOLoops is to use + a default argument to enable programs with multiple IOLoops + but not require the argument for simpler applications:: + + class MyClass(object): + def __init__(self, io_loop=None): + self.io_loop = io_loop or IOLoop.instance() + """ + if not hasattr(IOLoop, "_instance"): + IOLoop._instance = IOLoop() + return IOLoop._instance + + @staticmethod + def initialized(): + """Returns true if the singleton instance has been created.""" + return hasattr(IOLoop, "_instance") + + def install(self): + """Installs this IOloop object as the singleton instance. + + This is normally not necessary as `instance()` will create + an IOLoop on demand, but you may want to call `install` to use + a custom subclass of IOLoop. + """ + assert not IOLoop.initialized() + IOLoop._instance = self + + def close(self, all_fds=False): + """Closes the IOLoop, freeing any resources used. + + If ``all_fds`` is true, all file descriptors registered on the + IOLoop will be closed (not just the ones created by the IOLoop itself. + """ + self.remove_handler(self._waker.fileno()) + if all_fds: + for fd in self._handlers.keys()[:]: + try: + os.close(fd) + except Exception: + logging.debug("error closing fd %d", fd, exc_info=True) + self._waker.close() + self._impl.close() + + def add_handler(self, fd, handler, events): + """Registers the given handler to receive the given events for fd.""" + self._handlers[fd] = stack_context.wrap(handler) + self._impl.register(fd, events | self.ERROR) + + def update_handler(self, fd, events): + """Changes the events we listen for fd.""" + self._impl.modify(fd, events | self.ERROR) + + def remove_handler(self, fd): + """Stop listening for events on fd.""" + self._handlers.pop(fd, None) + self._events.pop(fd, None) + try: + self._impl.unregister(fd) + except (OSError, IOError): + logging.debug("Error deleting fd from IOLoop", exc_info=True) + + def set_blocking_signal_threshold(self, seconds, action): + """Sends a signal if the ioloop is blocked for more than s seconds. + + Pass seconds=None to disable. Requires python 2.6 on a unixy + platform. + + The action parameter is a python signal handler. Read the + documentation for the python 'signal' module for more information. + If action is None, the process will be killed if it is blocked for + too long. + """ + if not hasattr(signal, "setitimer"): + logging.error("set_blocking_signal_threshold requires a signal module " + "with the setitimer method") + return + self._blocking_signal_threshold = seconds + if seconds is not None: + signal.signal(signal.SIGALRM, + action if action is not None else signal.SIG_DFL) + + def set_blocking_log_threshold(self, seconds): + """Logs a stack trace if the ioloop is blocked for more than s seconds. + Equivalent to set_blocking_signal_threshold(seconds, self.log_stack) + """ + self.set_blocking_signal_threshold(seconds, self.log_stack) + + def log_stack(self, signal, frame): + """Signal handler to log the stack trace of the current thread. + + For use with set_blocking_signal_threshold. + """ + logging.warning('IOLoop blocked for %f seconds in\n%s', + self._blocking_signal_threshold, + ''.join(traceback.format_stack(frame))) + + def start(self): + """Starts the I/O loop. + + The loop will run until one of the I/O handlers calls stop(), which + will make the loop stop after the current event iteration completes. + """ + if self._stopped: + self._stopped = False + return + self._thread_ident = thread.get_ident() + self._running = True + while True: + # Never use an infinite timeout here - it can stall epoll + poll_timeout = 0.2 + + # Prevent IO event starvation by delaying new callbacks + # to the next iteration of the event loop. + with self._callback_lock: + callbacks = self._callbacks + self._callbacks = [] + for callback in callbacks: + self._run_callback(callback) + + if self._timeouts: + now = time.time() + while self._timeouts: + if self._timeouts[0].callback is None: + # the timeout was cancelled + heapq.heappop(self._timeouts) + elif self._timeouts[0].deadline <= now: + timeout = heapq.heappop(self._timeouts) + self._run_callback(timeout.callback) + else: + milliseconds = self._timeouts[0].deadline - now + poll_timeout = min(milliseconds, poll_timeout) + break + + if self._callbacks: + # If any callbacks or timeouts called add_callback, + # we don't want to wait in poll() before we run them. + poll_timeout = 0.0 + + if not self._running: + break + + if self._blocking_signal_threshold is not None: + # clear alarm so it doesn't fire while poll is waiting for + # events. + signal.setitimer(signal.ITIMER_REAL, 0, 0) + + try: + event_pairs = self._impl.poll(poll_timeout) + except Exception, e: + # Depending on python version and IOLoop implementation, + # different exception types may be thrown and there are + # two ways EINTR might be signaled: + # * e.errno == errno.EINTR + # * e.args is like (errno.EINTR, 'Interrupted system call') + if (getattr(e, 'errno', None) == errno.EINTR or + (isinstance(getattr(e, 'args', None), tuple) and + len(e.args) == 2 and e.args[0] == errno.EINTR)): + continue + else: + raise + + if self._blocking_signal_threshold is not None: + signal.setitimer(signal.ITIMER_REAL, + self._blocking_signal_threshold, 0) + + # Pop one fd at a time from the set of pending fds and run + # its handler. Since that handler may perform actions on + # other file descriptors, there may be reentrant calls to + # this IOLoop that update self._events + self._events.update(event_pairs) + while self._events: + fd, events = self._events.popitem() + try: + self._handlers[fd](fd, events) + except (OSError, IOError), e: + if e.args[0] == errno.EPIPE: + # Happens when the client closes the connection + pass + else: + logging.error("Exception in I/O handler for fd %d", + fd, exc_info=True) + except Exception: + logging.error("Exception in I/O handler for fd %d", + fd, exc_info=True) + # reset the stopped flag so another start/stop pair can be issued + self._stopped = False + if self._blocking_signal_threshold is not None: + signal.setitimer(signal.ITIMER_REAL, 0, 0) + + def stop(self): + """Stop the loop after the current event loop iteration is complete. + If the event loop is not currently running, the next call to start() + will return immediately. + + To use asynchronous methods from otherwise-synchronous code (such as + unit tests), you can start and stop the event loop like this:: + + ioloop = IOLoop() + async_method(ioloop=ioloop, callback=ioloop.stop) + ioloop.start() + + ioloop.start() will return after async_method has run its callback, + whether that callback was invoked before or after ioloop.start. + """ + self._running = False + self._stopped = True + self._waker.wake() + + def running(self): + """Returns true if this IOLoop is currently running.""" + return self._running + + def add_timeout(self, deadline, callback): + """Calls the given callback at the time deadline from the I/O loop. + + Returns a handle that may be passed to remove_timeout to cancel. + + ``deadline`` may be a number denoting a unix timestamp (as returned + by ``time.time()`` or a ``datetime.timedelta`` object for a deadline + relative to the current time. + """ + timeout = _Timeout(deadline, stack_context.wrap(callback)) + heapq.heappush(self._timeouts, timeout) + return timeout + + def remove_timeout(self, timeout): + """Cancels a pending timeout. + + The argument is a handle as returned by add_timeout. + """ + # Removing from a heap is complicated, so just leave the defunct + # timeout object in the queue (see discussion in + # http://docs.python.org/library/heapq.html). + # If this turns out to be a problem, we could add a garbage + # collection pass whenever there are too many dead timeouts. + timeout.callback = None + + def add_callback(self, callback): + """Calls the given callback on the next I/O loop iteration. + + It is safe to call this method from any thread at any time. + Note that this is the *only* method in IOLoop that makes this + guarantee; all other interaction with the IOLoop must be done + from that IOLoop's thread. add_callback() may be used to transfer + control from other threads to the IOLoop's thread. + """ + with self._callback_lock: + list_empty = not self._callbacks + self._callbacks.append(stack_context.wrap(callback)) + if list_empty and thread.get_ident() != self._thread_ident: + # If we're in the IOLoop's thread, we know it's not currently + # polling. If we're not, and we added the first callback to an + # empty list, we may need to wake it up (it may wake up on its + # own, but an occasional extra wake is harmless). Waking + # up a polling IOLoop is relatively expensive, so we try to + # avoid it when we can. + self._waker.wake() + + def _run_callback(self, callback): + try: + callback() + except Exception: + self.handle_callback_exception(callback) + + def handle_callback_exception(self, callback): + """This method is called whenever a callback run by the IOLoop + throws an exception. + + By default simply logs the exception as an error. Subclasses + may override this method to customize reporting of exceptions. + + The exception itself is not passed explicitly, but is available + in sys.exc_info. + """ + logging.error("Exception in callback %r", callback, exc_info=True) + + +class _Timeout(object): + """An IOLoop timeout, a UNIX timestamp and a callback""" + + # Reduce memory overhead when there are lots of pending callbacks + __slots__ = ['deadline', 'callback'] + + def __init__(self, deadline, callback): + if isinstance(deadline, (int, long, float)): + self.deadline = deadline + elif isinstance(deadline, datetime.timedelta): + self.deadline = time.time() + _Timeout.timedelta_to_seconds(deadline) + else: + raise TypeError("Unsupported deadline %r" % deadline) + self.callback = callback + + @staticmethod + def timedelta_to_seconds(td): + """Equivalent to td.total_seconds() (introduced in python 2.7).""" + return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / float(10**6) + + # Comparison methods to sort by deadline, with object id as a tiebreaker + # to guarantee a consistent ordering. The heapq module uses __le__ + # in python2.5, and __lt__ in 2.6+ (sort() and most other comparisons + # use __lt__). + def __lt__(self, other): + return ((self.deadline, id(self)) < + (other.deadline, id(other))) + + def __le__(self, other): + return ((self.deadline, id(self)) <= + (other.deadline, id(other))) + + +class PeriodicCallback(object): + """Schedules the given callback to be called periodically. + + The callback is called every callback_time milliseconds. + + `start` must be called after the PeriodicCallback is created. + """ + def __init__(self, callback, callback_time, io_loop=None): + self.callback = callback + self.callback_time = callback_time + self.io_loop = io_loop or IOLoop.instance() + self._running = False + + def start(self): + """Starts the timer.""" + self._running = True + self._next_timeout = time.time() + self._schedule_next() + + def stop(self): + """Stops the timer.""" + self._running = False + + def _run(self): + if not self._running: return + try: + self.callback() + except Exception: + logging.error("Error in periodic callback", exc_info=True) + self._schedule_next() + + def _schedule_next(self): + if self._running: + current_time = time.time() + while self._next_timeout <= current_time: + self._next_timeout += self.callback_time / 1000.0 + self.io_loop.add_timeout(self._next_timeout, self._run) + + +class _EPoll(object): + """An epoll-based event loop using our C module for Python 2.5 systems""" + _EPOLL_CTL_ADD = 1 + _EPOLL_CTL_DEL = 2 + _EPOLL_CTL_MOD = 3 + + def __init__(self): + self._epoll_fd = epoll.epoll_create() + + def fileno(self): + return self._epoll_fd + + def close(self): + os.close(self._epoll_fd) + + def register(self, fd, events): + epoll.epoll_ctl(self._epoll_fd, self._EPOLL_CTL_ADD, fd, events) + + def modify(self, fd, events): + epoll.epoll_ctl(self._epoll_fd, self._EPOLL_CTL_MOD, fd, events) + + def unregister(self, fd): + epoll.epoll_ctl(self._epoll_fd, self._EPOLL_CTL_DEL, fd, 0) + + def poll(self, timeout): + return epoll.epoll_wait(self._epoll_fd, int(timeout * 1000)) + + +class _KQueue(object): + """A kqueue-based event loop for BSD/Mac systems.""" + def __init__(self): + self._kqueue = select.kqueue() + self._active = {} + + def fileno(self): + return self._kqueue.fileno() + + def close(self): + self._kqueue.close() + + def register(self, fd, events): + self._control(fd, events, select.KQ_EV_ADD) + self._active[fd] = events + + def modify(self, fd, events): + self.unregister(fd) + self.register(fd, events) + + def unregister(self, fd): + events = self._active.pop(fd) + self._control(fd, events, select.KQ_EV_DELETE) + + def _control(self, fd, events, flags): + kevents = [] + if events & IOLoop.WRITE: + kevents.append(select.kevent( + fd, filter=select.KQ_FILTER_WRITE, flags=flags)) + if events & IOLoop.READ or not kevents: + # Always read when there is not a write + kevents.append(select.kevent( + fd, filter=select.KQ_FILTER_READ, flags=flags)) + # Even though control() takes a list, it seems to return EINVAL + # on Mac OS X (10.6) when there is more than one event in the list. + for kevent in kevents: + self._kqueue.control([kevent], 0) + + def poll(self, timeout): + kevents = self._kqueue.control(None, 1000, timeout) + events = {} + for kevent in kevents: + fd = kevent.ident + if kevent.filter == select.KQ_FILTER_READ: + events[fd] = events.get(fd, 0) | IOLoop.READ + if kevent.filter == select.KQ_FILTER_WRITE: + if kevent.flags & select.KQ_EV_EOF: + # If an asynchronous connection is refused, kqueue + # returns a write event with the EOF flag set. + # Turn this into an error for consistency with the + # other IOLoop implementations. + # Note that for read events, EOF may be returned before + # all data has been consumed from the socket buffer, + # so we only check for EOF on write events. + events[fd] = IOLoop.ERROR + else: + events[fd] = events.get(fd, 0) | IOLoop.WRITE + if kevent.flags & select.KQ_EV_ERROR: + events[fd] = events.get(fd, 0) | IOLoop.ERROR + return events.items() + + +class _Select(object): + """A simple, select()-based IOLoop implementation for non-Linux systems""" + def __init__(self): + self.read_fds = set() + self.write_fds = set() + self.error_fds = set() + self.fd_sets = (self.read_fds, self.write_fds, self.error_fds) + + def close(self): + pass + + def register(self, fd, events): + if events & IOLoop.READ: self.read_fds.add(fd) + if events & IOLoop.WRITE: self.write_fds.add(fd) + if events & IOLoop.ERROR: + self.error_fds.add(fd) + # Closed connections are reported as errors by epoll and kqueue, + # but as zero-byte reads by select, so when errors are requested + # we need to listen for both read and error. + self.read_fds.add(fd) + + def modify(self, fd, events): + self.unregister(fd) + self.register(fd, events) + + def unregister(self, fd): + self.read_fds.discard(fd) + self.write_fds.discard(fd) + self.error_fds.discard(fd) + + def poll(self, timeout): + readable, writeable, errors = select.select( + self.read_fds, self.write_fds, self.error_fds, timeout) + events = {} + for fd in readable: + events[fd] = events.get(fd, 0) | IOLoop.READ + for fd in writeable: + events[fd] = events.get(fd, 0) | IOLoop.WRITE + for fd in errors: + events[fd] = events.get(fd, 0) | IOLoop.ERROR + return events.items() + + +# Choose a poll implementation. Use epoll if it is available, fall back to +# select() for non-Linux platforms +if hasattr(select, "epoll"): + # Python 2.6+ on Linux + _poll = select.epoll +elif hasattr(select, "kqueue"): + # Python 2.6+ on BSD or Mac + _poll = _KQueue +else: + try: + # Linux systems with our C module installed + import epoll + _poll = _EPoll + except Exception: + # All other systems + import sys + if "linux" in sys.platform: + logging.warning("epoll module not found; using select()") + _poll = _Select diff --git a/interactive-mining-madoap/madoap/src/tornado/iostream.py b/interactive-mining-madoap/madoap/src/tornado/iostream.py new file mode 100644 index 0000000..6536527 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/iostream.py @@ -0,0 +1,692 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""A utility class to write to and read from a non-blocking socket.""" + +from __future__ import with_statement + +import collections +import errno +import logging +import socket +import sys +import re + +from tornado import ioloop +from tornado import stack_context +from tornado.util import b, bytes_type + +try: + import ssl # Python 2.6+ +except ImportError: + ssl = None + +class IOStream(object): + r"""A utility class to write to and read from a non-blocking socket. + + We support a non-blocking ``write()`` and a family of ``read_*()`` methods. + All of the methods take callbacks (since writing and reading are + non-blocking and asynchronous). + + The socket parameter may either be connected or unconnected. For + server operations the socket is the result of calling socket.accept(). + For client operations the socket is created with socket.socket(), + and may either be connected before passing it to the IOStream or + connected with IOStream.connect. + + A very simple (and broken) HTTP client using this class:: + + from tornado import ioloop + from tornado import iostream + import socket + + def send_request(): + stream.write("GET / HTTP/1.0\r\nHost: friendfeed.com\r\n\r\n") + stream.read_until("\r\n\r\n", on_headers) + + def on_headers(data): + headers = {} + for line in data.split("\r\n"): + parts = line.split(":") + if len(parts) == 2: + headers[parts[0].strip()] = parts[1].strip() + stream.read_bytes(int(headers["Content-Length"]), on_body) + + def on_body(data): + print data + stream.close() + ioloop.IOLoop.instance().stop() + + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + stream = iostream.IOStream(s) + stream.connect(("friendfeed.com", 80), send_request) + ioloop.IOLoop.instance().start() + + """ + def __init__(self, socket, io_loop=None, max_buffer_size=104857600, + read_chunk_size=4096): + self.socket = socket + self.socket.setblocking(False) + self.io_loop = io_loop or ioloop.IOLoop.instance() + self.max_buffer_size = max_buffer_size + self.read_chunk_size = read_chunk_size + self._read_buffer = collections.deque() + self._write_buffer = collections.deque() + self._read_buffer_size = 0 + self._write_buffer_frozen = False + self._read_delimiter = None + self._read_regex = None + self._read_bytes = None + self._read_until_close = False + self._read_callback = None + self._streaming_callback = None + self._write_callback = None + self._close_callback = None + self._connect_callback = None + self._connecting = False + self._state = None + self._pending_callbacks = 0 + + def connect(self, address, callback=None): + """Connects the socket to a remote address without blocking. + + May only be called if the socket passed to the constructor was + not previously connected. The address parameter is in the + same format as for socket.connect, i.e. a (host, port) tuple. + If callback is specified, it will be called when the + connection is completed. + + Note that it is safe to call IOStream.write while the + connection is pending, in which case the data will be written + as soon as the connection is ready. Calling IOStream read + methods before the socket is connected works on some platforms + but is non-portable. + """ + self._connecting = True + try: + self.socket.connect(address) + except socket.error, e: + # In non-blocking mode we expect connect() to raise an + # exception with EINPROGRESS or EWOULDBLOCK. + # + # On freebsd, other errors such as ECONNREFUSED may be + # returned immediately when attempting to connect to + # localhost, so handle them the same way as an error + # reported later in _handle_connect. + if e.args[0] not in (errno.EINPROGRESS, errno.EWOULDBLOCK): + logging.warning("Connect error on fd %d: %s", + self.socket.fileno(), e) + self.close() + return + self._connect_callback = stack_context.wrap(callback) + self._add_io_state(self.io_loop.WRITE) + + def read_until_regex(self, regex, callback): + """Call callback when we read the given regex pattern.""" + assert not self._read_callback, "Already reading" + self._read_regex = re.compile(regex) + self._read_callback = stack_context.wrap(callback) + while True: + # See if we've already got the data from a previous read + if self._read_from_buffer(): + return + self._check_closed() + if self._read_to_buffer() == 0: + break + self._add_io_state(self.io_loop.READ) + + def read_until(self, delimiter, callback): + """Call callback when we read the given delimiter.""" + assert not self._read_callback, "Already reading" + self._read_delimiter = delimiter + self._read_callback = stack_context.wrap(callback) + while True: + # See if we've already got the data from a previous read + if self._read_from_buffer(): + return + self._check_closed() + if self._read_to_buffer() == 0: + break + self._add_io_state(self.io_loop.READ) + + def read_bytes(self, num_bytes, callback, streaming_callback=None): + """Call callback when we read the given number of bytes. + + If a ``streaming_callback`` is given, it will be called with chunks + of data as they become available, and the argument to the final + ``callback`` will be empty. + """ + assert not self._read_callback, "Already reading" + assert isinstance(num_bytes, (int, long)) + self._read_bytes = num_bytes + self._read_callback = stack_context.wrap(callback) + self._streaming_callback = stack_context.wrap(streaming_callback) + while True: + if self._read_from_buffer(): + return + self._check_closed() + if self._read_to_buffer() == 0: + break + self._add_io_state(self.io_loop.READ) + + def read_until_close(self, callback, streaming_callback=None): + """Reads all data from the socket until it is closed. + + If a ``streaming_callback`` is given, it will be called with chunks + of data as they become available, and the argument to the final + ``callback`` will be empty. + + Subject to ``max_buffer_size`` limit from `IOStream` constructor if + a ``streaming_callback`` is not used. + """ + assert not self._read_callback, "Already reading" + if self.closed(): + self._run_callback(callback, self._consume(self._read_buffer_size)) + return + self._read_until_close = True + self._read_callback = stack_context.wrap(callback) + self._streaming_callback = stack_context.wrap(streaming_callback) + self._add_io_state(self.io_loop.READ) + + def write(self, data, callback=None): + """Write the given data to this stream. + + If callback is given, we call it when all of the buffered write + data has been successfully written to the stream. If there was + previously buffered write data and an old write callback, that + callback is simply overwritten with this new callback. + """ + assert isinstance(data, bytes_type) + self._check_closed() + self._write_buffer.append(data) + self._write_callback = stack_context.wrap(callback) + self._handle_write() + if self._write_buffer: + self._add_io_state(self.io_loop.WRITE) + self._maybe_add_error_listener() + + def set_close_callback(self, callback): + """Call the given callback when the stream is closed.""" + self._close_callback = stack_context.wrap(callback) + + def close(self): + """Close this stream.""" + if self.socket is not None: + if self._read_until_close: + callback = self._read_callback + self._read_callback = None + self._read_until_close = False + self._run_callback(callback, + self._consume(self._read_buffer_size)) + if self._state is not None: + self.io_loop.remove_handler(self.socket.fileno()) + self._state = None + self.socket.close() + self.socket = None + if self._close_callback and self._pending_callbacks == 0: + # if there are pending callbacks, don't run the close callback + # until they're done (see _maybe_add_error_handler) + cb = self._close_callback + self._close_callback = None + self._run_callback(cb) + + def reading(self): + """Returns true if we are currently reading from the stream.""" + return self._read_callback is not None + + def writing(self): + """Returns true if we are currently writing to the stream.""" + return bool(self._write_buffer) + + def closed(self): + """Returns true if the stream has been closed.""" + return self.socket is None + + def _handle_events(self, fd, events): + if not self.socket: + logging.warning("Got events for closed stream %d", fd) + return + try: + if events & self.io_loop.READ: + self._handle_read() + if not self.socket: + return + if events & self.io_loop.WRITE: + if self._connecting: + self._handle_connect() + self._handle_write() + if not self.socket: + return + if events & self.io_loop.ERROR: + # We may have queued up a user callback in _handle_read or + # _handle_write, so don't close the IOStream until those + # callbacks have had a chance to run. + self.io_loop.add_callback(self.close) + return + state = self.io_loop.ERROR + if self.reading(): + state |= self.io_loop.READ + if self.writing(): + state |= self.io_loop.WRITE + if state == self.io_loop.ERROR: + state |= self.io_loop.READ + if state != self._state: + assert self._state is not None, \ + "shouldn't happen: _handle_events without self._state" + self._state = state + self.io_loop.update_handler(self.socket.fileno(), self._state) + except Exception: + logging.error("Uncaught exception, closing connection.", + exc_info=True) + self.close() + raise + + def _run_callback(self, callback, *args): + def wrapper(): + self._pending_callbacks -= 1 + try: + callback(*args) + except Exception: + logging.error("Uncaught exception, closing connection.", + exc_info=True) + # Close the socket on an uncaught exception from a user callback + # (It would eventually get closed when the socket object is + # gc'd, but we don't want to rely on gc happening before we + # run out of file descriptors) + self.close() + # Re-raise the exception so that IOLoop.handle_callback_exception + # can see it and log the error + raise + self._maybe_add_error_listener() + # We schedule callbacks to be run on the next IOLoop iteration + # rather than running them directly for several reasons: + # * Prevents unbounded stack growth when a callback calls an + # IOLoop operation that immediately runs another callback + # * Provides a predictable execution context for e.g. + # non-reentrant mutexes + # * Ensures that the try/except in wrapper() is run outside + # of the application's StackContexts + with stack_context.NullContext(): + # stack_context was already captured in callback, we don't need to + # capture it again for IOStream's wrapper. This is especially + # important if the callback was pre-wrapped before entry to + # IOStream (as in HTTPConnection._header_callback), as we could + # capture and leak the wrong context here. + self._pending_callbacks += 1 + self.io_loop.add_callback(wrapper) + + def _handle_read(self): + while True: + try: + # Read from the socket until we get EWOULDBLOCK or equivalent. + # SSL sockets do some internal buffering, and if the data is + # sitting in the SSL object's buffer select() and friends + # can't see it; the only way to find out if it's there is to + # try to read it. + result = self._read_to_buffer() + except Exception: + self.close() + return + if result == 0: + break + else: + if self._read_from_buffer(): + return + + def _read_from_socket(self): + """Attempts to read from the socket. + + Returns the data read or None if there is nothing to read. + May be overridden in subclasses. + """ + try: + chunk = self.socket.recv(self.read_chunk_size) + except socket.error, e: + if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN): + return None + else: + raise + if not chunk: + self.close() + return None + return chunk + + def _read_to_buffer(self): + """Reads from the socket and appends the result to the read buffer. + + Returns the number of bytes read. Returns 0 if there is nothing + to read (i.e. the read returns EWOULDBLOCK or equivalent). On + error closes the socket and raises an exception. + """ + try: + chunk = self._read_from_socket() + except socket.error, e: + # ssl.SSLError is a subclass of socket.error + logging.warning("Read error on %d: %s", + self.socket.fileno(), e) + self.close() + raise + if chunk is None: + return 0 + self._read_buffer.append(chunk) + self._read_buffer_size += len(chunk) + if self._read_buffer_size >= self.max_buffer_size: + logging.error("Reached maximum read buffer size") + self.close() + raise IOError("Reached maximum read buffer size") + return len(chunk) + + def _read_from_buffer(self): + """Attempts to complete the currently-pending read from the buffer. + + Returns True if the read was completed. + """ + if self._read_bytes is not None: + if self._streaming_callback is not None and self._read_buffer_size: + bytes_to_consume = min(self._read_bytes, self._read_buffer_size) + self._read_bytes -= bytes_to_consume + self._run_callback(self._streaming_callback, + self._consume(bytes_to_consume)) + if self._read_buffer_size >= self._read_bytes: + num_bytes = self._read_bytes + callback = self._read_callback + self._read_callback = None + self._streaming_callback = None + self._read_bytes = None + self._run_callback(callback, self._consume(num_bytes)) + return True + elif self._read_delimiter is not None: + _merge_prefix(self._read_buffer, sys.maxint) + loc = self._read_buffer[0].find(self._read_delimiter) + if loc != -1: + callback = self._read_callback + delimiter_len = len(self._read_delimiter) + self._read_callback = None + self._streaming_callback = None + self._read_delimiter = None + self._run_callback(callback, + self._consume(loc + delimiter_len)) + return True + elif self._read_regex is not None: + _merge_prefix(self._read_buffer, sys.maxint) + m = self._read_regex.search(self._read_buffer[0]) + if m: + callback = self._read_callback + self._read_callback = None + self._streaming_callback = None + self._read_regex = None + self._run_callback(callback, self._consume(m.end())) + return True + elif self._read_until_close: + if self._streaming_callback is not None and self._read_buffer_size: + self._run_callback(self._streaming_callback, + self._consume(self._read_buffer_size)) + return False + + def _handle_connect(self): + err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) + if err != 0: + # IOLoop implementations may vary: some of them return + # an error state before the socket becomes writable, so + # in that case a connection failure would be handled by the + # error path in _handle_events instead of here. + logging.warning("Connect error on fd %d: %s", + self.socket.fileno(), errno.errorcode[err]) + self.close() + return + if self._connect_callback is not None: + callback = self._connect_callback + self._connect_callback = None + self._run_callback(callback) + self._connecting = False + + def _handle_write(self): + while self._write_buffer: + try: + if not self._write_buffer_frozen: + # On windows, socket.send blows up if given a + # write buffer that's too large, instead of just + # returning the number of bytes it was able to + # process. Therefore we must not call socket.send + # with more than 128KB at a time. + _merge_prefix(self._write_buffer, 128 * 1024) + num_bytes = self.socket.send(self._write_buffer[0]) + if num_bytes == 0: + # With OpenSSL, if we couldn't write the entire buffer, + # the very same string object must be used on the + # next call to send. Therefore we suppress + # merging the write buffer after an incomplete send. + # A cleaner solution would be to set + # SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER, but this is + # not yet accessible from python + # (http://bugs.python.org/issue8240) + self._write_buffer_frozen = True + break + self._write_buffer_frozen = False + _merge_prefix(self._write_buffer, num_bytes) + self._write_buffer.popleft() + except socket.error, e: + if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN): + self._write_buffer_frozen = True + break + else: + logging.warning("Write error on %d: %s", + self.socket.fileno(), e) + self.close() + return + if not self._write_buffer and self._write_callback: + callback = self._write_callback + self._write_callback = None + self._run_callback(callback) + + def _consume(self, loc): + if loc == 0: + return b("") + _merge_prefix(self._read_buffer, loc) + self._read_buffer_size -= loc + return self._read_buffer.popleft() + + def _check_closed(self): + if not self.socket: + raise IOError("Stream is closed") + + def _maybe_add_error_listener(self): + if self._state is None and self._pending_callbacks == 0: + if self.socket is None: + cb = self._close_callback + if cb is not None: + self._close_callback = None + self._run_callback(cb) + else: + self._add_io_state(ioloop.IOLoop.READ) + + def _add_io_state(self, state): + """Adds `state` (IOLoop.{READ,WRITE} flags) to our event handler. + + Implementation notes: Reads and writes have a fast path and a + slow path. The fast path reads synchronously from socket + buffers, while the slow path uses `_add_io_state` to schedule + an IOLoop callback. Note that in both cases, the callback is + run asynchronously with `_run_callback`. + + To detect closed connections, we must have called + `_add_io_state` at some point, but we want to delay this as + much as possible so we don't have to set an `IOLoop.ERROR` + listener that will be overwritten by the next slow-path + operation. As long as there are callbacks scheduled for + fast-path ops, those callbacks may do more reads. + If a sequence of fast-path ops do not end in a slow-path op, + (e.g. for an @asynchronous long-poll request), we must add + the error handler. This is done in `_run_callback` and `write` + (since the write callback is optional so we can have a + fast-path write with no `_run_callback`) + """ + if self.socket is None: + # connection has been closed, so there can be no future events + return + if self._state is None: + self._state = ioloop.IOLoop.ERROR | state + with stack_context.NullContext(): + self.io_loop.add_handler( + self.socket.fileno(), self._handle_events, self._state) + elif not self._state & state: + self._state = self._state | state + self.io_loop.update_handler(self.socket.fileno(), self._state) + + +class SSLIOStream(IOStream): + """A utility class to write to and read from a non-blocking SSL socket. + + If the socket passed to the constructor is already connected, + it should be wrapped with:: + + ssl.wrap_socket(sock, do_handshake_on_connect=False, **kwargs) + + before constructing the SSLIOStream. Unconnected sockets will be + wrapped when IOStream.connect is finished. + """ + def __init__(self, *args, **kwargs): + """Creates an SSLIOStream. + + If a dictionary is provided as keyword argument ssl_options, + it will be used as additional keyword arguments to ssl.wrap_socket. + """ + self._ssl_options = kwargs.pop('ssl_options', {}) + super(SSLIOStream, self).__init__(*args, **kwargs) + self._ssl_accepting = True + self._handshake_reading = False + self._handshake_writing = False + + def reading(self): + return self._handshake_reading or super(SSLIOStream, self).reading() + + def writing(self): + return self._handshake_writing or super(SSLIOStream, self).writing() + + def _do_ssl_handshake(self): + # Based on code from test_ssl.py in the python stdlib + try: + self._handshake_reading = False + self._handshake_writing = False + self.socket.do_handshake() + except ssl.SSLError, err: + if err.args[0] == ssl.SSL_ERROR_WANT_READ: + self._handshake_reading = True + return + elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE: + self._handshake_writing = True + return + elif err.args[0] in (ssl.SSL_ERROR_EOF, + ssl.SSL_ERROR_ZERO_RETURN): + return self.close() + elif err.args[0] == ssl.SSL_ERROR_SSL: + logging.warning("SSL Error on %d: %s", self.socket.fileno(), err) + return self.close() + raise + except socket.error, err: + if err.args[0] == errno.ECONNABORTED: + return self.close() + else: + self._ssl_accepting = False + super(SSLIOStream, self)._handle_connect() + + def _handle_read(self): + if self._ssl_accepting: + self._do_ssl_handshake() + return + super(SSLIOStream, self)._handle_read() + + def _handle_write(self): + if self._ssl_accepting: + self._do_ssl_handshake() + return + super(SSLIOStream, self)._handle_write() + + def _handle_connect(self): + self.socket = ssl.wrap_socket(self.socket, + do_handshake_on_connect=False, + **self._ssl_options) + # Don't call the superclass's _handle_connect (which is responsible + # for telling the application that the connection is complete) + # until we've completed the SSL handshake (so certificates are + # available, etc). + + + def _read_from_socket(self): + try: + # SSLSocket objects have both a read() and recv() method, + # while regular sockets only have recv(). + # The recv() method blocks (at least in python 2.6) if it is + # called when there is nothing to read, so we have to use + # read() instead. + chunk = self.socket.read(self.read_chunk_size) + except ssl.SSLError, e: + # SSLError is a subclass of socket.error, so this except + # block must come first. + if e.args[0] == ssl.SSL_ERROR_WANT_READ: + return None + else: + raise + except socket.error, e: + if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN): + return None + else: + raise + if not chunk: + self.close() + return None + return chunk + +def _merge_prefix(deque, size): + """Replace the first entries in a deque of strings with a single + string of up to size bytes. + + >>> d = collections.deque(['abc', 'de', 'fghi', 'j']) + >>> _merge_prefix(d, 5); print d + deque(['abcde', 'fghi', 'j']) + + Strings will be split as necessary to reach the desired size. + >>> _merge_prefix(d, 7); print d + deque(['abcdefg', 'hi', 'j']) + + >>> _merge_prefix(d, 3); print d + deque(['abc', 'defg', 'hi', 'j']) + + >>> _merge_prefix(d, 100); print d + deque(['abcdefghij']) + """ + if len(deque) == 1 and len(deque[0]) <= size: + return + prefix = [] + remaining = size + while deque and remaining > 0: + chunk = deque.popleft() + if len(chunk) > remaining: + deque.appendleft(chunk[remaining:]) + chunk = chunk[:remaining] + prefix.append(chunk) + remaining -= len(chunk) + # This data structure normally just contains byte strings, but + # the unittest gets messy if it doesn't use the default str() type, + # so do the merge based on the type of data that's actually present. + if prefix: + deque.appendleft(type(prefix[0])().join(prefix)) + if not deque: + deque.appendleft(b("")) + +def doctests(): + import doctest + return doctest.DocTestSuite() diff --git a/interactive-mining-madoap/madoap/src/tornado/locale.py b/interactive-mining-madoap/madoap/src/tornado/locale.py new file mode 100644 index 0000000..61cdb7e --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/locale.py @@ -0,0 +1,472 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Translation methods for generating localized strings. + +To load a locale and generate a translated string:: + + user_locale = locale.get("es_LA") + print user_locale.translate("Sign out") + +locale.get() returns the closest matching locale, not necessarily the +specific locale you requested. You can support pluralization with +additional arguments to translate(), e.g.:: + + people = [...] + message = user_locale.translate( + "%(list)s is online", "%(list)s are online", len(people)) + print message % {"list": user_locale.list(people)} + +The first string is chosen if len(people) == 1, otherwise the second +string is chosen. + +Applications should call one of load_translations (which uses a simple +CSV format) or load_gettext_translations (which uses the .mo format +supported by gettext and related tools). If neither method is called, +the locale.translate method will simply return the original string. +""" + +import csv +import datetime +import logging +import os +import re + +_default_locale = "en_US" +_translations = {} +_supported_locales = frozenset([_default_locale]) +_use_gettext = False + +def get(*locale_codes): + """Returns the closest match for the given locale codes. + + We iterate over all given locale codes in order. If we have a tight + or a loose match for the code (e.g., "en" for "en_US"), we return + the locale. Otherwise we move to the next code in the list. + + By default we return en_US if no translations are found for any of + the specified locales. You can change the default locale with + set_default_locale() below. + """ + return Locale.get_closest(*locale_codes) + + +def set_default_locale(code): + """Sets the default locale, used in get_closest_locale(). + + The default locale is assumed to be the language used for all strings + in the system. The translations loaded from disk are mappings from + the default locale to the destination locale. Consequently, you don't + need to create a translation file for the default locale. + """ + global _default_locale + global _supported_locales + _default_locale = code + _supported_locales = frozenset(_translations.keys() + [_default_locale]) + + +def load_translations(directory): + u"""Loads translations from CSV files in a directory. + + Translations are strings with optional Python-style named placeholders + (e.g., "My name is %(name)s") and their associated translations. + + The directory should have translation files of the form LOCALE.csv, + e.g. es_GT.csv. The CSV files should have two or three columns: string, + translation, and an optional plural indicator. Plural indicators should + be one of "plural" or "singular". A given string can have both singular + and plural forms. For example "%(name)s liked this" may have a + different verb conjugation depending on whether %(name)s is one + name or a list of names. There should be two rows in the CSV file for + that string, one with plural indicator "singular", and one "plural". + For strings with no verbs that would change on translation, simply + use "unknown" or the empty string (or don't include the column at all). + + The file is read using the csv module in the default "excel" dialect. + In this format there should not be spaces after the commas. + + Example translation es_LA.csv: + + "I love you","Te amo" + "%(name)s liked this","A %(name)s les gust\u00f3 esto","plural" + "%(name)s liked this","A %(name)s le gust\u00f3 esto","singular" + + """ + global _translations + global _supported_locales + _translations = {} + for path in os.listdir(directory): + if not path.endswith(".csv"): continue + locale, extension = path.split(".") + if not re.match("[a-z]+(_[A-Z]+)?$", locale): + logging.error("Unrecognized locale %r (path: %s)", locale, + os.path.join(directory, path)) + continue + f = open(os.path.join(directory, path), "r") + _translations[locale] = {} + for i, row in enumerate(csv.reader(f)): + if not row or len(row) < 2: continue + row = [c.decode("utf-8").strip() for c in row] + english, translation = row[:2] + if len(row) > 2: + plural = row[2] or "unknown" + else: + plural = "unknown" + if plural not in ("plural", "singular", "unknown"): + logging.error("Unrecognized plural indicator %r in %s line %d", + plural, path, i + 1) + continue + _translations[locale].setdefault(plural, {})[english] = translation + f.close() + _supported_locales = frozenset(_translations.keys() + [_default_locale]) + logging.info("Supported locales: %s", sorted(_supported_locales)) + +def load_gettext_translations(directory, domain): + """Loads translations from gettext's locale tree + + Locale tree is similar to system's /usr/share/locale, like: + + {directory}/{lang}/LC_MESSAGES/{domain}.mo + + Three steps are required to have you app translated: + + 1. Generate POT translation file + xgettext --language=Python --keyword=_:1,2 -d cyclone file1.py file2.html etc + + 2. Merge against existing POT file: + msgmerge old.po cyclone.po > new.po + + 3. Compile: + msgfmt cyclone.po -o {directory}/pt_BR/LC_MESSAGES/cyclone.mo + """ + import gettext + global _translations + global _supported_locales + global _use_gettext + _translations = {} + for lang in os.listdir(directory): + if lang.startswith('.'): continue # skip .svn, etc + if os.path.isfile(os.path.join(directory, lang)): continue + try: + os.stat(os.path.join(directory, lang, "LC_MESSAGES", domain+".mo")) + _translations[lang] = gettext.translation(domain, directory, + languages=[lang]) + except Exception, e: + logging.error("Cannot load translation for '%s': %s", lang, str(e)) + continue + _supported_locales = frozenset(_translations.keys() + [_default_locale]) + _use_gettext = True + logging.info("Supported locales: %s", sorted(_supported_locales)) + + +def get_supported_locales(cls): + """Returns a list of all the supported locale codes.""" + return _supported_locales + + +class Locale(object): + """Object representing a locale. + + After calling one of `load_translations` or `load_gettext_translations`, + call `get` or `get_closest` to get a Locale object. + """ + @classmethod + def get_closest(cls, *locale_codes): + """Returns the closest match for the given locale code.""" + for code in locale_codes: + if not code: continue + code = code.replace("-", "_") + parts = code.split("_") + if len(parts) > 2: + continue + elif len(parts) == 2: + code = parts[0].lower() + "_" + parts[1].upper() + if code in _supported_locales: + return cls.get(code) + if parts[0].lower() in _supported_locales: + return cls.get(parts[0].lower()) + return cls.get(_default_locale) + + @classmethod + def get(cls, code): + """Returns the Locale for the given locale code. + + If it is not supported, we raise an exception. + """ + if not hasattr(cls, "_cache"): + cls._cache = {} + if code not in cls._cache: + assert code in _supported_locales + translations = _translations.get(code, None) + if translations is None: + locale = CSVLocale(code, {}) + elif _use_gettext: + locale = GettextLocale(code, translations) + else: + locale = CSVLocale(code, translations) + cls._cache[code] = locale + return cls._cache[code] + + def __init__(self, code, translations): + self.code = code + self.name = LOCALE_NAMES.get(code, {}).get("name", u"Unknown") + self.rtl = False + for prefix in ["fa", "ar", "he"]: + if self.code.startswith(prefix): + self.rtl = True + break + self.translations = translations + + # Initialize strings for date formatting + _ = self.translate + self._months = [ + _("January"), _("February"), _("March"), _("April"), + _("May"), _("June"), _("July"), _("August"), + _("September"), _("October"), _("November"), _("December")] + self._weekdays = [ + _("Monday"), _("Tuesday"), _("Wednesday"), _("Thursday"), + _("Friday"), _("Saturday"), _("Sunday")] + + def translate(self, message, plural_message=None, count=None): + """Returns the translation for the given message for this locale. + + If plural_message is given, you must also provide count. We return + plural_message when count != 1, and we return the singular form + for the given message when count == 1. + """ + raise NotImplementedError() + + def format_date(self, date, gmt_offset=0, relative=True, shorter=False, + full_format=False): + """Formats the given date (which should be GMT). + + By default, we return a relative time (e.g., "2 minutes ago"). You + can return an absolute date string with relative=False. + + You can force a full format date ("July 10, 1980") with + full_format=True. + + This method is primarily intended for dates in the past. + For dates in the future, we fall back to full format. + """ + if self.code.startswith("ru"): + relative = False + if type(date) in (int, long, float): + date = datetime.datetime.utcfromtimestamp(date) + now = datetime.datetime.utcnow() + if date > now: + if relative and (date - now).seconds < 60: + # Due to click skew, things are some things slightly + # in the future. Round timestamps in the immediate + # future down to now in relative mode. + date = now + else: + # Otherwise, future dates always use the full format. + full_format = True + local_date = date - datetime.timedelta(minutes=gmt_offset) + local_now = now - datetime.timedelta(minutes=gmt_offset) + local_yesterday = local_now - datetime.timedelta(hours=24) + difference = now - date + seconds = difference.seconds + days = difference.days + + _ = self.translate + format = None + if not full_format: + if relative and days == 0: + if seconds < 50: + return _("1 second ago", "%(seconds)d seconds ago", + seconds) % { "seconds": seconds } + + if seconds < 50 * 60: + minutes = round(seconds / 60.0) + return _("1 minute ago", "%(minutes)d minutes ago", + minutes) % { "minutes": minutes } + + hours = round(seconds / (60.0 * 60)) + return _("1 hour ago", "%(hours)d hours ago", + hours) % { "hours": hours } + + if days == 0: + format = _("%(time)s") + elif days == 1 and local_date.day == local_yesterday.day and \ + relative: + format = _("yesterday") if shorter else \ + _("yesterday at %(time)s") + elif days < 5: + format = _("%(weekday)s") if shorter else \ + _("%(weekday)s at %(time)s") + elif days < 334: # 11mo, since confusing for same month last year + format = _("%(month_name)s %(day)s") if shorter else \ + _("%(month_name)s %(day)s at %(time)s") + + if format is None: + format = _("%(month_name)s %(day)s, %(year)s") if shorter else \ + _("%(month_name)s %(day)s, %(year)s at %(time)s") + + tfhour_clock = self.code not in ("en", "en_US", "zh_CN") + if tfhour_clock: + str_time = "%d:%02d" % (local_date.hour, local_date.minute) + elif self.code == "zh_CN": + str_time = "%s%d:%02d" % ( + (u'\u4e0a\u5348', u'\u4e0b\u5348')[local_date.hour >= 12], + local_date.hour % 12 or 12, local_date.minute) + else: + str_time = "%d:%02d %s" % ( + local_date.hour % 12 or 12, local_date.minute, + ("am", "pm")[local_date.hour >= 12]) + + return format % { + "month_name": self._months[local_date.month - 1], + "weekday": self._weekdays[local_date.weekday()], + "day": str(local_date.day), + "year": str(local_date.year), + "time": str_time + } + + def format_day(self, date, gmt_offset=0, dow=True): + """Formats the given date as a day of week. + + Example: "Monday, January 22". You can remove the day of week with + dow=False. + """ + local_date = date - datetime.timedelta(minutes=gmt_offset) + _ = self.translate + if dow: + return _("%(weekday)s, %(month_name)s %(day)s") % { + "month_name": self._months[local_date.month - 1], + "weekday": self._weekdays[local_date.weekday()], + "day": str(local_date.day), + } + else: + return _("%(month_name)s %(day)s") % { + "month_name": self._months[local_date.month - 1], + "day": str(local_date.day), + } + + def list(self, parts): + """Returns a comma-separated list for the given list of parts. + + The format is, e.g., "A, B and C", "A and B" or just "A" for lists + of size 1. + """ + _ = self.translate + if len(parts) == 0: return "" + if len(parts) == 1: return parts[0] + comma = u' \u0648 ' if self.code.startswith("fa") else u", " + return _("%(commas)s and %(last)s") % { + "commas": comma.join(parts[:-1]), + "last": parts[len(parts) - 1], + } + + def friendly_number(self, value): + """Returns a comma-separated number for the given integer.""" + if self.code not in ("en", "en_US"): + return str(value) + value = str(value) + parts = [] + while value: + parts.append(value[-3:]) + value = value[:-3] + return ",".join(reversed(parts)) + +class CSVLocale(Locale): + """Locale implementation using tornado's CSV translation format.""" + def translate(self, message, plural_message=None, count=None): + if plural_message is not None: + assert count is not None + if count != 1: + message = plural_message + message_dict = self.translations.get("plural", {}) + else: + message_dict = self.translations.get("singular", {}) + else: + message_dict = self.translations.get("unknown", {}) + return message_dict.get(message, message) + +class GettextLocale(Locale): + """Locale implementation using the gettext module.""" + def translate(self, message, plural_message=None, count=None): + if plural_message is not None: + assert count is not None + return self.translations.ungettext(message, plural_message, count) + else: + return self.translations.ugettext(message) + +LOCALE_NAMES = { + "af_ZA": {"name_en": u"Afrikaans", "name": u"Afrikaans"}, + "am_ET": {"name_en": u"Amharic", "name": u'\u12a0\u121b\u122d\u129b'}, + "ar_AR": {"name_en": u"Arabic", "name": u"\u0627\u0644\u0639\u0631\u0628\u064a\u0629"}, + "bg_BG": {"name_en": u"Bulgarian", "name": u"\u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438"}, + "bn_IN": {"name_en": u"Bengali", "name": u"\u09ac\u09be\u0982\u09b2\u09be"}, + "bs_BA": {"name_en": u"Bosnian", "name": u"Bosanski"}, + "ca_ES": {"name_en": u"Catalan", "name": u"Catal\xe0"}, + "cs_CZ": {"name_en": u"Czech", "name": u"\u010ce\u0161tina"}, + "cy_GB": {"name_en": u"Welsh", "name": u"Cymraeg"}, + "da_DK": {"name_en": u"Danish", "name": u"Dansk"}, + "de_DE": {"name_en": u"German", "name": u"Deutsch"}, + "el_GR": {"name_en": u"Greek", "name": u"\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac"}, + "en_GB": {"name_en": u"English (UK)", "name": u"English (UK)"}, + "en_US": {"name_en": u"English (US)", "name": u"English (US)"}, + "es_ES": {"name_en": u"Spanish (Spain)", "name": u"Espa\xf1ol (Espa\xf1a)"}, + "es_LA": {"name_en": u"Spanish", "name": u"Espa\xf1ol"}, + "et_EE": {"name_en": u"Estonian", "name": u"Eesti"}, + "eu_ES": {"name_en": u"Basque", "name": u"Euskara"}, + "fa_IR": {"name_en": u"Persian", "name": u"\u0641\u0627\u0631\u0633\u06cc"}, + "fi_FI": {"name_en": u"Finnish", "name": u"Suomi"}, + "fr_CA": {"name_en": u"French (Canada)", "name": u"Fran\xe7ais (Canada)"}, + "fr_FR": {"name_en": u"French", "name": u"Fran\xe7ais"}, + "ga_IE": {"name_en": u"Irish", "name": u"Gaeilge"}, + "gl_ES": {"name_en": u"Galician", "name": u"Galego"}, + "he_IL": {"name_en": u"Hebrew", "name": u"\u05e2\u05d1\u05e8\u05d9\u05ea"}, + "hi_IN": {"name_en": u"Hindi", "name": u"\u0939\u093f\u0928\u094d\u0926\u0940"}, + "hr_HR": {"name_en": u"Croatian", "name": u"Hrvatski"}, + "hu_HU": {"name_en": u"Hungarian", "name": u"Magyar"}, + "id_ID": {"name_en": u"Indonesian", "name": u"Bahasa Indonesia"}, + "is_IS": {"name_en": u"Icelandic", "name": u"\xcdslenska"}, + "it_IT": {"name_en": u"Italian", "name": u"Italiano"}, + "ja_JP": {"name_en": u"Japanese", "name": u"\u65e5\u672c\u8a9e"}, + "ko_KR": {"name_en": u"Korean", "name": u"\ud55c\uad6d\uc5b4"}, + "lt_LT": {"name_en": u"Lithuanian", "name": u"Lietuvi\u0173"}, + "lv_LV": {"name_en": u"Latvian", "name": u"Latvie\u0161u"}, + "mk_MK": {"name_en": u"Macedonian", "name": u"\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438"}, + "ml_IN": {"name_en": u"Malayalam", "name": u"\u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02"}, + "ms_MY": {"name_en": u"Malay", "name": u"Bahasa Melayu"}, + "nb_NO": {"name_en": u"Norwegian (bokmal)", "name": u"Norsk (bokm\xe5l)"}, + "nl_NL": {"name_en": u"Dutch", "name": u"Nederlands"}, + "nn_NO": {"name_en": u"Norwegian (nynorsk)", "name": u"Norsk (nynorsk)"}, + "pa_IN": {"name_en": u"Punjabi", "name": u"\u0a2a\u0a70\u0a1c\u0a3e\u0a2c\u0a40"}, + "pl_PL": {"name_en": u"Polish", "name": u"Polski"}, + "pt_BR": {"name_en": u"Portuguese (Brazil)", "name": u"Portugu\xeas (Brasil)"}, + "pt_PT": {"name_en": u"Portuguese (Portugal)", "name": u"Portugu\xeas (Portugal)"}, + "ro_RO": {"name_en": u"Romanian", "name": u"Rom\xe2n\u0103"}, + "ru_RU": {"name_en": u"Russian", "name": u"\u0420\u0443\u0441\u0441\u043a\u0438\u0439"}, + "sk_SK": {"name_en": u"Slovak", "name": u"Sloven\u010dina"}, + "sl_SI": {"name_en": u"Slovenian", "name": u"Sloven\u0161\u010dina"}, + "sq_AL": {"name_en": u"Albanian", "name": u"Shqip"}, + "sr_RS": {"name_en": u"Serbian", "name": u"\u0421\u0440\u043f\u0441\u043a\u0438"}, + "sv_SE": {"name_en": u"Swedish", "name": u"Svenska"}, + "sw_KE": {"name_en": u"Swahili", "name": u"Kiswahili"}, + "ta_IN": {"name_en": u"Tamil", "name": u"\u0ba4\u0bae\u0bbf\u0bb4\u0bcd"}, + "te_IN": {"name_en": u"Telugu", "name": u"\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41"}, + "th_TH": {"name_en": u"Thai", "name": u"\u0e20\u0e32\u0e29\u0e32\u0e44\u0e17\u0e22"}, + "tl_PH": {"name_en": u"Filipino", "name": u"Filipino"}, + "tr_TR": {"name_en": u"Turkish", "name": u"T\xfcrk\xe7e"}, + "uk_UA": {"name_en": u"Ukraini ", "name": u"\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"}, + "vi_VN": {"name_en": u"Vietnamese", "name": u"Ti\u1ebfng Vi\u1ec7t"}, + "zh_CN": {"name_en": u"Chinese (Simplified)", "name": u"\u4e2d\u6587(\u7b80\u4f53)"}, + "zh_TW": {"name_en": u"Chinese (Traditional)", "name": u"\u4e2d\u6587(\u7e41\u9ad4)"}, +} diff --git a/interactive-mining-madoap/madoap/src/tornado/netutil.py b/interactive-mining-madoap/madoap/src/tornado/netutil.py new file mode 100644 index 0000000..cfff0ba --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/netutil.py @@ -0,0 +1,320 @@ +#!/usr/bin/env python +# +# Copyright 2011 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Miscellaneous network utility code.""" + +import errno +import logging +import os +import socket +import stat + +from tornado import process +from tornado.ioloop import IOLoop +from tornado.iostream import IOStream, SSLIOStream +from tornado.platform.auto import set_close_exec + +try: + import ssl # Python 2.6+ +except ImportError: + ssl = None + +class TCPServer(object): + r"""A non-blocking, single-threaded TCP server. + + To use `TCPServer`, define a subclass which overrides the `handle_stream` + method. + + `TCPServer` can serve SSL traffic with Python 2.6+ and OpenSSL. + To make this server serve SSL traffic, send the ssl_options dictionary + argument with the arguments required for the `ssl.wrap_socket` method, + including "certfile" and "keyfile":: + + TCPServer(ssl_options={ + "certfile": os.path.join(data_dir, "mydomain.crt"), + "keyfile": os.path.join(data_dir, "mydomain.key"), + }) + + `TCPServer` initialization follows one of three patterns: + + 1. `listen`: simple single-process:: + + server = TCPServer() + server.listen(8888) + IOLoop.instance().start() + + 2. `bind`/`start`: simple multi-process:: + + server = TCPServer() + server.bind(8888) + server.start(0) # Forks multiple sub-processes + IOLoop.instance().start() + + When using this interface, an `IOLoop` must *not* be passed + to the `TCPServer` constructor. `start` will always start + the server on the default singleton `IOLoop`. + + 3. `add_sockets`: advanced multi-process:: + + sockets = bind_sockets(8888) + tornado.process.fork_processes(0) + server = TCPServer() + server.add_sockets(sockets) + IOLoop.instance().start() + + The `add_sockets` interface is more complicated, but it can be + used with `tornado.process.fork_processes` to give you more + flexibility in when the fork happens. `add_sockets` can + also be used in single-process servers if you want to create + your listening sockets in some way other than + `bind_sockets`. + """ + def __init__(self, io_loop=None, ssl_options=None): + self.io_loop = io_loop + self.ssl_options = ssl_options + self._sockets = {} # fd -> socket object + self._pending_sockets = [] + self._started = False + + def listen(self, port, address=""): + """Starts accepting connections on the given port. + + This method may be called more than once to listen on multiple ports. + `listen` takes effect immediately; it is not necessary to call + `TCPServer.start` afterwards. It is, however, necessary to start + the `IOLoop`. + """ + sockets = bind_sockets(port, address=address) + self.add_sockets(sockets) + + def add_sockets(self, sockets): + """Makes this server start accepting connections on the given sockets. + + The ``sockets`` parameter is a list of socket objects such as + those returned by `bind_sockets`. + `add_sockets` is typically used in combination with that + method and `tornado.process.fork_processes` to provide greater + control over the initialization of a multi-process server. + """ + if self.io_loop is None: + self.io_loop = IOLoop.instance() + + for sock in sockets: + self._sockets[sock.fileno()] = sock + add_accept_handler(sock, self._handle_connection, + io_loop=self.io_loop) + + def add_socket(self, socket): + """Singular version of `add_sockets`. Takes a single socket object.""" + self.add_sockets([socket]) + + def bind(self, port, address=None, family=socket.AF_UNSPEC, backlog=128): + """Binds this server to the given port on the given address. + + To start the server, call `start`. If you want to run this server + in a single process, you can call `listen` as a shortcut to the + sequence of `bind` and `start` calls. + + Address may be either an IP address or hostname. If it's a hostname, + the server will listen on all IP addresses associated with the + name. Address may be an empty string or None to listen on all + available interfaces. Family may be set to either ``socket.AF_INET`` + or ``socket.AF_INET6`` to restrict to ipv4 or ipv6 addresses, otherwise + both will be used if available. + + The ``backlog`` argument has the same meaning as for + `socket.listen`. + + This method may be called multiple times prior to `start` to listen + on multiple ports or interfaces. + """ + sockets = bind_sockets(port, address=address, family=family, + backlog=backlog) + if self._started: + self.add_sockets(sockets) + else: + self._pending_sockets.extend(sockets) + + def start(self, num_processes=1): + """Starts this server in the IOLoop. + + By default, we run the server in this process and do not fork any + additional child process. + + If num_processes is ``None`` or <= 0, we detect the number of cores + available on this machine and fork that number of child + processes. If num_processes is given and > 1, we fork that + specific number of sub-processes. + + Since we use processes and not threads, there is no shared memory + between any server code. + + Note that multiple processes are not compatible with the autoreload + module (or the ``debug=True`` option to `tornado.web.Application`). + When using multiple processes, no IOLoops can be created or + referenced until after the call to ``TCPServer.start(n)``. + """ + assert not self._started + self._started = True + if num_processes != 1: + process.fork_processes(num_processes) + sockets = self._pending_sockets + self._pending_sockets = [] + self.add_sockets(sockets) + + def stop(self): + """Stops listening for new connections. + + Requests currently in progress may still continue after the + server is stopped. + """ + for fd, sock in self._sockets.iteritems(): + self.io_loop.remove_handler(fd) + sock.close() + + def handle_stream(self, stream, address): + """Override to handle a new `IOStream` from an incoming connection.""" + raise NotImplementedError() + + def _handle_connection(self, connection, address): + if self.ssl_options is not None: + assert ssl, "Python 2.6+ and OpenSSL required for SSL" + try: + connection = ssl.wrap_socket(connection, + server_side=True, + do_handshake_on_connect=False, + **self.ssl_options) + except ssl.SSLError, err: + if err.args[0] == ssl.SSL_ERROR_EOF: + return connection.close() + else: + raise + except socket.error, err: + if err.args[0] == errno.ECONNABORTED: + return connection.close() + else: + raise + try: + if self.ssl_options is not None: + stream = SSLIOStream(connection, io_loop=self.io_loop) + else: + stream = IOStream(connection, io_loop=self.io_loop) + self.handle_stream(stream, address) + except Exception: + logging.error("Error in connection callback", exc_info=True) + + +def bind_sockets(port, address=None, family=socket.AF_UNSPEC, backlog=128): + """Creates listening sockets bound to the given port and address. + + Returns a list of socket objects (multiple sockets are returned if + the given address maps to multiple IP addresses, which is most common + for mixed IPv4 and IPv6 use). + + Address may be either an IP address or hostname. If it's a hostname, + the server will listen on all IP addresses associated with the + name. Address may be an empty string or None to listen on all + available interfaces. Family may be set to either socket.AF_INET + or socket.AF_INET6 to restrict to ipv4 or ipv6 addresses, otherwise + both will be used if available. + + The ``backlog`` argument has the same meaning as for + ``socket.listen()``. + """ + sockets = [] + if address == "": + address = None + flags = socket.AI_PASSIVE + if hasattr(socket, "AI_ADDRCONFIG"): + # AI_ADDRCONFIG ensures that we only try to bind on ipv6 + # if the system is configured for it, but the flag doesn't + # exist on some platforms (specifically WinXP, although + # newer versions of windows have it) + flags |= socket.AI_ADDRCONFIG + for res in socket.getaddrinfo(address, port, family, socket.SOCK_STREAM, + 0, flags): + af, socktype, proto, canonname, sockaddr = res + sock = socket.socket(af, socktype, proto) + set_close_exec(sock.fileno()) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + if af == socket.AF_INET6: + # On linux, ipv6 sockets accept ipv4 too by default, + # but this makes it impossible to bind to both + # 0.0.0.0 in ipv4 and :: in ipv6. On other systems, + # separate sockets *must* be used to listen for both ipv4 + # and ipv6. For consistency, always disable ipv4 on our + # ipv6 sockets and use a separate ipv4 socket when needed. + # + # Python 2.x on windows doesn't have IPPROTO_IPV6. + if hasattr(socket, "IPPROTO_IPV6"): + sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1) + sock.setblocking(0) + sock.bind(sockaddr) + sock.listen(backlog) + sockets.append(sock) + return sockets + +if hasattr(socket, 'AF_UNIX'): + def bind_unix_socket(file, mode=0600, backlog=128): + """Creates a listening unix socket. + + If a socket with the given name already exists, it will be deleted. + If any other file with that name exists, an exception will be + raised. + + Returns a socket object (not a list of socket objects like + `bind_sockets`) + """ + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + set_close_exec(sock.fileno()) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.setblocking(0) + try: + st = os.stat(file) + except OSError, err: + if err.errno != errno.ENOENT: + raise + else: + if stat.S_ISSOCK(st.st_mode): + os.remove(file) + else: + raise ValueError("File %s exists and is not a socket", file) + sock.bind(file) + os.chmod(file, mode) + sock.listen(backlog) + return sock + +def add_accept_handler(sock, callback, io_loop=None): + """Adds an ``IOLoop`` event handler to accept new connections on ``sock``. + + When a connection is accepted, ``callback(connection, address)`` will + be run (``connection`` is a socket object, and ``address`` is the + address of the other end of the connection). Note that this signature + is different from the ``callback(fd, events)`` signature used for + ``IOLoop`` handlers. + """ + if io_loop is None: + io_loop = IOLoop.instance() + def accept_handler(fd, events): + while True: + try: + connection, address = sock.accept() + except socket.error, e: + if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN): + return + raise + callback(connection, address) + io_loop.add_handler(sock.fileno(), accept_handler, IOLoop.READ) diff --git a/interactive-mining-madoap/madoap/src/tornado/options.py b/interactive-mining-madoap/madoap/src/tornado/options.py new file mode 100644 index 0000000..a230347 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/options.py @@ -0,0 +1,417 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""A command line parsing module that lets modules define their own options. + +Each module defines its own options, e.g.:: + + from tornado.options import define, options + + define("mysql_host", default="127.0.0.1:3306", help="Main user DB") + define("memcache_hosts", default="127.0.0.1:11011", multiple=True, + help="Main user memcache servers") + + def connect(): + db = database.Connection(options.mysql_host) + ... + +The main() method of your application does not need to be aware of all of +the options used throughout your program; they are all automatically loaded +when the modules are loaded. Your main() method can parse the command line +or parse a config file with:: + + import tornado.options + tornado.options.parse_config_file("/etc/server.conf") + tornado.options.parse_command_line() + +Command line formats are what you would expect ("--myoption=myvalue"). +Config files are just Python files. Global names become options, e.g.:: + + myoption = "myvalue" + myotheroption = "myothervalue" + +We support datetimes, timedeltas, ints, and floats (just pass a 'type' +kwarg to define). We also accept multi-value options. See the documentation +for define() below. +""" + +import datetime +import logging +import logging.handlers +import re +import sys +import time + +from tornado.escape import _unicode + +# For pretty log messages, if available +try: + import curses +except ImportError: + curses = None + + +def define(name, default=None, type=None, help=None, metavar=None, + multiple=False, group=None): + """Defines a new command line option. + + If type is given (one of str, float, int, datetime, or timedelta) + or can be inferred from the default, we parse the command line + arguments based on the given type. If multiple is True, we accept + comma-separated values, and the option value is always a list. + + For multi-value integers, we also accept the syntax x:y, which + turns into range(x, y) - very useful for long integer ranges. + + help and metavar are used to construct the automatically generated + command line help string. The help message is formatted like:: + + --name=METAVAR help string + + group is used to group the defined options in logical groups. By default, + command line options are grouped by the defined file. + + Command line option names must be unique globally. They can be parsed + from the command line with parse_command_line() or parsed from a + config file with parse_config_file. + """ + if name in options: + raise Error("Option %r already defined in %s", name, + options[name].file_name) + frame = sys._getframe(0) + options_file = frame.f_code.co_filename + file_name = frame.f_back.f_code.co_filename + if file_name == options_file: file_name = "" + if type is None: + if not multiple and default is not None: + type = default.__class__ + else: + type = str + if group: + group_name = group + else: + group_name = file_name + options[name] = _Option(name, file_name=file_name, default=default, + type=type, help=help, metavar=metavar, + multiple=multiple, group_name=group_name) + + +def parse_command_line(args=None): + """Parses all options given on the command line. + + We return all command line arguments that are not options as a list. + """ + if args is None: args = sys.argv + remaining = [] + for i in xrange(1, len(args)): + # All things after the last option are command line arguments + if not args[i].startswith("-"): + remaining = args[i:] + break + if args[i] == "--": + remaining = args[i+1:] + break + arg = args[i].lstrip("-") + name, equals, value = arg.partition("=") + name = name.replace('-', '_') + if not name in options: + print_help() + raise Error('Unrecognized command line option: %r' % name) + option = options[name] + if not equals: + if option.type == bool: + value = "true" + else: + raise Error('Option %r requires a value' % name) + option.parse(value) + if options.help: + print_help() + sys.exit(0) + + # Set up log level and pretty console logging by default + if options.logging != 'none': + logging.getLogger().setLevel(getattr(logging, options.logging.upper())) + enable_pretty_logging() + + return remaining + + +def parse_config_file(path): + """Parses and loads the Python config file at the given path.""" + config = {} + execfile(path, config, config) + for name in config: + if name in options: + options[name].set(config[name]) + + +def print_help(file=sys.stdout): + """Prints all the command line options to stdout.""" + print >> file, "Usage: %s [OPTIONS]" % sys.argv[0] + print >> file, "" + print >> file, "Options:" + by_group = {} + for option in options.itervalues(): + by_group.setdefault(option.group_name, []).append(option) + + for filename, o in sorted(by_group.items()): + if filename: print >> file, filename + o.sort(key=lambda option: option.name) + for option in o: + prefix = option.name + if option.metavar: + prefix += "=" + option.metavar + print >> file, " --%-30s %s" % (prefix, option.help or "") + print >> file + + +class _Options(dict): + """Our global program options, an dictionary with object-like access.""" + @classmethod + def instance(cls): + if not hasattr(cls, "_instance"): + cls._instance = cls() + return cls._instance + + def __getattr__(self, name): + if isinstance(self.get(name), _Option): + return self[name].value() + raise AttributeError("Unrecognized option %r" % name) + + +class _Option(object): + def __init__(self, name, default=None, type=str, help=None, metavar=None, + multiple=False, file_name=None, group_name=None): + if default is None and multiple: + default = [] + self.name = name + self.type = type + self.help = help + self.metavar = metavar + self.multiple = multiple + self.file_name = file_name + self.group_name = group_name + self.default = default + self._value = None + + def value(self): + return self.default if self._value is None else self._value + + def parse(self, value): + _parse = { + datetime.datetime: self._parse_datetime, + datetime.timedelta: self._parse_timedelta, + bool: self._parse_bool, + str: self._parse_string, + }.get(self.type, self.type) + if self.multiple: + if self._value is None: + self._value = [] + for part in value.split(","): + if self.type in (int, long): + # allow ranges of the form X:Y (inclusive at both ends) + lo, _, hi = part.partition(":") + lo = _parse(lo) + hi = _parse(hi) if hi else lo + self._value.extend(range(lo, hi+1)) + else: + self._value.append(_parse(part)) + else: + self._value = _parse(value) + return self.value() + + def set(self, value): + if self.multiple: + if not isinstance(value, list): + raise Error("Option %r is required to be a list of %s" % + (self.name, self.type.__name__)) + for item in value: + if item != None and not isinstance(item, self.type): + raise Error("Option %r is required to be a list of %s" % + (self.name, self.type.__name__)) + else: + if value != None and not isinstance(value, self.type): + raise Error("Option %r is required to be a %s" % + (self.name, self.type.__name__)) + self._value = value + + # Supported date/time formats in our options + _DATETIME_FORMATS = [ + "%a %b %d %H:%M:%S %Y", + "%Y-%m-%d %H:%M:%S", + "%Y-%m-%d %H:%M", + "%Y-%m-%dT%H:%M", + "%Y%m%d %H:%M:%S", + "%Y%m%d %H:%M", + "%Y-%m-%d", + "%Y%m%d", + "%H:%M:%S", + "%H:%M", + ] + + def _parse_datetime(self, value): + for format in self._DATETIME_FORMATS: + try: + return datetime.datetime.strptime(value, format) + except ValueError: + pass + raise Error('Unrecognized date/time format: %r' % value) + + _TIMEDELTA_ABBREVS = [ + ('hours', ['h']), + ('minutes', ['m', 'min']), + ('seconds', ['s', 'sec']), + ('milliseconds', ['ms']), + ('microseconds', ['us']), + ('days', ['d']), + ('weeks', ['w']), + ] + + _TIMEDELTA_ABBREV_DICT = dict( + (abbrev, full) for full, abbrevs in _TIMEDELTA_ABBREVS + for abbrev in abbrevs) + + _FLOAT_PATTERN = r'[-+]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][-+]?\d+)?' + + _TIMEDELTA_PATTERN = re.compile( + r'\s*(%s)\s*(\w*)\s*' % _FLOAT_PATTERN, re.IGNORECASE) + + def _parse_timedelta(self, value): + try: + sum = datetime.timedelta() + start = 0 + while start < len(value): + m = self._TIMEDELTA_PATTERN.match(value, start) + if not m: + raise Exception() + num = float(m.group(1)) + units = m.group(2) or 'seconds' + units = self._TIMEDELTA_ABBREV_DICT.get(units, units) + sum += datetime.timedelta(**{units: num}) + start = m.end() + return sum + except Exception: + raise + + def _parse_bool(self, value): + return value.lower() not in ("false", "0", "f") + + def _parse_string(self, value): + return _unicode(value) + + +class Error(Exception): + """Exception raised by errors in the options module.""" + pass + + +def enable_pretty_logging(): + """Turns on formatted logging output as configured. + + This is called automatically by `parse_command_line`. + """ + root_logger = logging.getLogger() + if options.log_file_prefix: + channel = logging.handlers.RotatingFileHandler( + filename=options.log_file_prefix, + maxBytes=options.log_file_max_size, + backupCount=options.log_file_num_backups) + channel.setFormatter(_LogFormatter(color=False)) + root_logger.addHandler(channel) + + if (options.log_to_stderr or + (options.log_to_stderr is None and not root_logger.handlers)): + # Set up color if we are in a tty and curses is installed + color = False + if curses and sys.stderr.isatty(): + try: + curses.setupterm() + if curses.tigetnum("colors") > 0: + color = True + except Exception: + pass + channel = logging.StreamHandler() + channel.setFormatter(_LogFormatter(color=color)) + root_logger.addHandler(channel) + + + +class _LogFormatter(logging.Formatter): + def __init__(self, color, *args, **kwargs): + logging.Formatter.__init__(self, *args, **kwargs) + self._color = color + if color: + # The curses module has some str/bytes confusion in python3. + # Most methods return bytes, but only accept strings. + # The explict calls to unicode() below are harmless in python2, + # but will do the right conversion in python3. + fg_color = unicode(curses.tigetstr("setaf") or + curses.tigetstr("setf") or "", "ascii") + self._colors = { + logging.DEBUG: unicode(curses.tparm(fg_color, 4), # Blue + "ascii"), + logging.INFO: unicode(curses.tparm(fg_color, 2), # Green + "ascii"), + logging.WARNING: unicode(curses.tparm(fg_color, 3), # Yellow + "ascii"), + logging.ERROR: unicode(curses.tparm(fg_color, 1), # Red + "ascii"), + } + self._normal = unicode(curses.tigetstr("sgr0"), "ascii") + + def format(self, record): + try: + record.message = record.getMessage() + except Exception, e: + record.message = "Bad message (%r): %r" % (e, record.__dict__) + record.asctime = time.strftime( + "%y%m%d %H:%M:%S", self.converter(record.created)) + prefix = '[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d]' % \ + record.__dict__ + if self._color: + prefix = (self._colors.get(record.levelno, self._normal) + + prefix + self._normal) + formatted = prefix + " " + record.message + if record.exc_info: + if not record.exc_text: + record.exc_text = self.formatException(record.exc_info) + if record.exc_text: + formatted = formatted.rstrip() + "\n" + record.exc_text + return formatted.replace("\n", "\n ") + + +options = _Options.instance() + + +# Default options +define("help", type=bool, help="show this help information") +define("logging", default="info", + help=("Set the Python log level. If 'none', tornado won't touch the " + "logging configuration."), + metavar="info|warning|error|none") +define("log_to_stderr", type=bool, default=None, + help=("Send log output to stderr (colorized if possible). " + "By default use stderr if --log_file_prefix is not set and " + "no other logging is configured.")) +define("log_file_prefix", type=str, default=None, metavar="PATH", + help=("Path prefix for log files. " + "Note that if you are running multiple tornado processes, " + "log_file_prefix must be different for each of them (e.g. " + "include the port number)")) +define("log_file_max_size", type=int, default=100 * 1000 * 1000, + help="max size of log files before rollover") +define("log_file_num_backups", type=int, default=10, + help="number of log files to keep") diff --git a/interactive-mining-madoap/madoap/src/tornado/platform/__init__.py b/interactive-mining-madoap/madoap/src/tornado/platform/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/interactive-mining-madoap/madoap/src/tornado/platform/auto.py b/interactive-mining-madoap/madoap/src/tornado/platform/auto.py new file mode 100644 index 0000000..e76d731 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/platform/auto.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# +# Copyright 2011 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Implementation of platform-specific functionality. + +For each function or class described in `tornado.platform.interface`, +the appropriate platform-specific implementation exists in this module. +Most code that needs access to this functionality should do e.g.:: + + from tornado.platform.auto import set_close_exec +""" + +import os + +if os.name == 'nt': + from tornado.platform.windows import set_close_exec, Waker +else: + from tornado.platform.posix import set_close_exec, Waker diff --git a/interactive-mining-madoap/madoap/src/tornado/platform/interface.py b/interactive-mining-madoap/madoap/src/tornado/platform/interface.py new file mode 100644 index 0000000..20f0f71 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/platform/interface.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# +# Copyright 2011 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Interfaces for platform-specific functionality. + +This module exists primarily for documentation purposes and as base classes +for other tornado.platform modules. Most code should import the appropriate +implementation from `tornado.platform.auto`. +""" + +def set_close_exec(fd): + """Sets the close-on-exec bit (``FD_CLOEXEC``)for a file descriptor.""" + raise NotImplementedError() + +class Waker(object): + """A socket-like object that can wake another thread from ``select()``. + + The `~tornado.ioloop.IOLoop` will add the Waker's `fileno()` to + its ``select`` (or ``epoll`` or ``kqueue``) calls. When another + thread wants to wake up the loop, it calls `wake`. Once it has woken + up, it will call `consume` to do any necessary per-wake cleanup. When + the ``IOLoop`` is closed, it closes its waker too. + """ + def fileno(self): + """Returns a file descriptor for this waker. + + Must be suitable for use with ``select()`` or equivalent on the + local platform. + """ + raise NotImplementedError() + + def wake(self): + """Triggers activity on the waker's file descriptor.""" + raise NotImplementedError() + + def consume(self): + """Called after the listen has woken up to do any necessary cleanup.""" + raise NotImplementedError() + + def close(self): + """Closes the waker's file descriptor(s).""" + raise NotImplementedError() + + diff --git a/interactive-mining-madoap/madoap/src/tornado/platform/posix.py b/interactive-mining-madoap/madoap/src/tornado/platform/posix.py new file mode 100644 index 0000000..aa09b31 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/platform/posix.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# +# Copyright 2011 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Posix implementations of platform-specific functionality.""" + +import fcntl +import os + +from tornado.platform import interface +from tornado.util import b + +def set_close_exec(fd): + flags = fcntl.fcntl(fd, fcntl.F_GETFD) + fcntl.fcntl(fd, fcntl.F_SETFD, flags | fcntl.FD_CLOEXEC) + +def _set_nonblocking(fd): + flags = fcntl.fcntl(fd, fcntl.F_GETFL) + fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK) + +class Waker(interface.Waker): + def __init__(self): + r, w = os.pipe() + _set_nonblocking(r) + _set_nonblocking(w) + set_close_exec(r) + set_close_exec(w) + self.reader = os.fdopen(r, "rb", 0) + self.writer = os.fdopen(w, "wb", 0) + + def fileno(self): + return self.reader.fileno() + + def wake(self): + try: + self.writer.write(b("x")) + except IOError: + pass + + def consume(self): + try: + while True: + result = self.reader.read() + if not result: break; + except IOError: + pass + + def close(self): + self.reader.close() + self.writer.close() diff --git a/interactive-mining-madoap/madoap/src/tornado/platform/twisted.py b/interactive-mining-madoap/madoap/src/tornado/platform/twisted.py new file mode 100644 index 0000000..04a32de --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/platform/twisted.py @@ -0,0 +1,305 @@ +# Author: Ovidiu Predescu +# Date: July 2011 +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +A twisted-style reactor for the Tornado IOLoop. + +To use it, add the following to your twisted application: + +import tornado.platform.twisted +tornado.platform.twisted.install() +from twisted.internet import reactor +""" + +from __future__ import with_statement, absolute_import + +import functools +import logging +import time + +from twisted.internet.posixbase import PosixReactorBase +from twisted.internet.interfaces import \ + IReactorFDSet, IDelayedCall, IReactorTime + +from zope.interface import implements + +import tornado +import tornado.ioloop +from tornado.stack_context import NullContext +from tornado.ioloop import IOLoop + +class TornadoDelayedCall(object): + """ + DelayedCall object for Tornado. + """ + implements(IDelayedCall) + + def __init__(self, reactor, seconds, f, *args, **kw): + self._reactor = reactor + self._func = functools.partial(f, *args, **kw) + self._time = self._reactor.seconds() + seconds + self._timeout = self._reactor._io_loop.add_timeout(self._time, + self._called) + self._active = True + + def _called(self): + self._active = False + self._reactor._removeDelayedCall(self) + try: + self._func() + except: + logging.error("_called caught exception", exc_info=True) + + def getTime(self): + return self._time + + def cancel(self): + self._active = False + self._reactor._io_loop.remove_timeout(self._timeout) + self._reactor._removeDelayedCall(self) + + def delay(self, seconds): + self._reactor._io_loop.remove_timeout(self._timeout) + self._time += seconds + self._timeout = self._reactor._io_loop.add_timeout(self._time, + self._called) + + def reset(self, seconds): + self._reactor._io_loop.remove_timeout(self._timeout) + self._time = self._reactor.seconds() + seconds + self._timeout = self._reactor._io_loop.add_timeout(self._time, + self._called) + + def active(self): + return self._active + +class TornadoReactor(PosixReactorBase): + """ + Twisted style reactor for Tornado. + """ + implements(IReactorTime, IReactorFDSet) + + def __init__(self, io_loop=None): + if not io_loop: + io_loop = tornado.ioloop.IOLoop.instance() + self._io_loop = io_loop + self._readers = {} + self._writers = {} + self._fds = {} # a map of fd to a (reader, writer) tuple + self._delayedCalls = {} + self._running = False + self._closed = False + PosixReactorBase.__init__(self) + + # IReactorTime + def seconds(self): + return time.time() + + def callLater(self, seconds, f, *args, **kw): + dc = TornadoDelayedCall(self, seconds, f, *args, **kw) + self._delayedCalls[dc] = True + return dc + + def getDelayedCalls(self): + return [x for x in self._delayedCalls if x._active] + + def _removeDelayedCall(self, dc): + if dc in self._delayedCalls: + del self._delayedCalls[dc] + + # IReactorThreads + def callFromThread(self, f, *args, **kw): + """ + See L{twisted.internet.interfaces.IReactorThreads.callFromThread}. + """ + assert callable(f), "%s is not callable" % f + p = functools.partial(f, *args, **kw) + self._io_loop.add_callback(p) + + # We don't need the waker code from the super class, Tornado uses + # its own waker. + def installWaker(self): + pass + + def wakeUp(self): + pass + + # IReactorFDSet + def _invoke_callback(self, fd, events): + (reader, writer) = self._fds[fd] + if events | IOLoop.READ and reader: + reader.doRead() + if events | IOLoop.WRITE and writer: + writer.doWrite() + + def addReader(self, reader): + """ + Add a FileDescriptor for notification of data available to read. + """ + if reader in self._readers: + # Don't add the reader if it's already there + return + self._readers[reader] = True + fd = reader.fileno() + if fd in self._fds: + (_, writer) = self._fds[fd] + self._fds[fd] = (reader, writer) + if writer: + # We already registered this fd for write events, + # update it for read events as well. + self._io_loop.update_handler(fd, IOLoop.READ | IOLoop.WRITE) + else: + with NullContext(): + self._fds[fd] = (reader, None) + self._io_loop.add_handler(fd, self._invoke_callback, + IOLoop.READ) + + def addWriter(self, writer): + """ + Add a FileDescriptor for notification of data available to write. + """ + if writer in self._writers: + return + self._writers[writer] = True + fd = writer.fileno() + if fd in self._fds: + (reader, _) = self._fds[fd] + self._fds[fd] = (reader, writer) + if reader: + # We already registered this fd for read events, + # update it for write events as well. + self._io_loop.update_handler(fd, IOLoop.READ | IOLoop.WRITE) + else: + with NullContext(): + self._fds[fd] = (None, writer) + self._io_loop.add_handler(fd, self._invoke_callback, + IOLoop.WRITE) + + def removeReader(self, reader): + """ + Remove a Selectable for notification of data available to read. + """ + fd = reader.fileno() + if reader in self._readers: + del self._readers[reader] + if self._closed: return + (_, writer) = self._fds[fd] + if writer: + # We have a writer so we need to update the IOLoop for + # write events only. + self._fds[fd] = (None, writer) + self._io_loop.update_handler(fd, IOLoop.WRITE) + else: + # Since we have no writer registered, we remove the + # entry from _fds and unregister the handler from the + # IOLoop + del self._fds[fd] + self._io_loop.remove_handler(fd) + + def removeWriter(self, writer): + """ + Remove a Selectable for notification of data available to write. + """ + fd = writer.fileno() + if writer in self._writers: + del self._writers[writer] + if self._closed: return + (reader, _) = self._fds[fd] + if reader: + # We have a reader so we need to update the IOLoop for + # read events only. + self._fds[fd] = (reader, None) + self._io_loop.update_handler(fd, IOLoop.READ) + else: + # Since we have no reader registered, we remove the + # entry from the _fds and unregister the handler from + # the IOLoop. + del self._fds[fd] + self._io_loop.remove_handler(fd) + + def removeAll(self): + return self._removeAll(self._readers, self._writers) + + def getReaders(self): + return self._readers.keys() + + def getWriters(self): + return self._writers.keys() + + def stop(self): + """ + Implement L{IReactorCore.stop}. + """ + self._running = False + PosixReactorBase.stop(self) + self.runUntilCurrent() + try: + self._io_loop.stop() + self._io_loop.close() + except: + # Ignore any exceptions thrown by IOLoop + pass + self._closed = True + + def crash(self): + if not self._running: + return + self._running = False + PosixReactorBase.crash(self) + self.runUntilCurrent() + try: + self._io_loop.stop() + self._io_loop.close() + except: + # Ignore any exceptions thrown by IOLoop + pass + self._closed = True + + def doIteration(self, delay): + raise NotImplementedError("doIteration") + + def mainLoop(self): + self._running = True + self._io_loop.start() + +class _TestReactor(TornadoReactor): + """Subclass of TornadoReactor for use in unittests. + + This can't go in the test.py file because of import-order dependencies + with the twisted reactor test builder. + """ + def __init__(self): + # always use a new ioloop + super(_TestReactor, self).__init__(IOLoop()) + + def listenTCP(self, port, factory, backlog=50, interface=''): + # default to localhost to avoid firewall prompts on the mac + if not interface: + interface = '127.0.0.1' + return super(_TestReactor, self).listenTCP( + port, factory, backlog=backlog, interface=interface) + + + +def install(io_loop=None): + """ + Install the Tornado reactor. + """ + if not io_loop: + io_loop = tornado.ioloop.IOLoop.instance() + reactor = TornadoReactor(io_loop) + from twisted.internet.main import installReactor + installReactor(reactor) + return reactor diff --git a/interactive-mining-madoap/madoap/src/tornado/platform/windows.py b/interactive-mining-madoap/madoap/src/tornado/platform/windows.py new file mode 100644 index 0000000..1735f1b --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/platform/windows.py @@ -0,0 +1,97 @@ +# NOTE: win32 support is currently experimental, and not recommended +# for production use. + +import ctypes +import ctypes.wintypes +import socket +import errno + +from tornado.platform import interface +from tornado.util import b + +# See: http://msdn.microsoft.com/en-us/library/ms724935(VS.85).aspx +SetHandleInformation = ctypes.windll.kernel32.SetHandleInformation +SetHandleInformation.argtypes = (ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD, ctypes.wintypes.DWORD) +SetHandleInformation.restype = ctypes.wintypes.BOOL + +HANDLE_FLAG_INHERIT = 0x00000001 + + +def set_close_exec(fd): + success = SetHandleInformation(fd, HANDLE_FLAG_INHERIT, 0) + if not success: + raise ctypes.GetLastError() + + +class Waker(interface.Waker): + """Create an OS independent asynchronous pipe""" + def __init__(self): + # Based on Zope async.py: http://svn.zope.org/zc.ngi/trunk/src/zc/ngi/async.py + + self.writer = socket.socket() + # Disable buffering -- pulling the trigger sends 1 byte, + # and we want that sent immediately, to wake up ASAP. + self.writer.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + + count = 0 + while 1: + count += 1 + # Bind to a local port; for efficiency, let the OS pick + # a free port for us. + # Unfortunately, stress tests showed that we may not + # be able to connect to that port ("Address already in + # use") despite that the OS picked it. This appears + # to be a race bug in the Windows socket implementation. + # So we loop until a connect() succeeds (almost always + # on the first try). See the long thread at + # http://mail.zope.org/pipermail/zope/2005-July/160433.html + # for hideous details. + a = socket.socket() + a.bind(("127.0.0.1", 0)) + connect_address = a.getsockname() # assigned (host, port) pair + a.listen(1) + try: + self.writer.connect(connect_address) + break # success + except socket.error, detail: + if detail[0] != errno.WSAEADDRINUSE: + # "Address already in use" is the only error + # I've seen on two WinXP Pro SP2 boxes, under + # Pythons 2.3.5 and 2.4.1. + raise + # (10048, 'Address already in use') + # assert count <= 2 # never triggered in Tim's tests + if count >= 10: # I've never seen it go above 2 + a.close() + self.writer.close() + raise socket.error("Cannot bind trigger!") + # Close `a` and try again. Note: I originally put a short + # sleep() here, but it didn't appear to help or hurt. + a.close() + + self.reader, addr = a.accept() + self.reader.setblocking(0) + self.writer.setblocking(0) + a.close() + self.reader_fd = self.reader.fileno() + + def fileno(self): + return self.reader.fileno() + + def wake(self): + try: + self.writer.send(b("x")) + except IOError: + pass + + def consume(self): + try: + while True: + result = self.reader.recv(1024) + if not result: break + except IOError: + pass + + def close(self): + self.reader.close() + self.writer.close() diff --git a/interactive-mining-madoap/madoap/src/tornado/process.py b/interactive-mining-madoap/madoap/src/tornado/process.py new file mode 100644 index 0000000..2672227 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/process.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python +# +# Copyright 2011 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Utilities for working with multiple processes.""" + +import errno +import logging +import os +import sys +import time + +from binascii import hexlify + +from tornado import ioloop + +try: + import multiprocessing # Python 2.6+ +except ImportError: + multiprocessing = None + +def cpu_count(): + """Returns the number of processors on this machine.""" + if multiprocessing is not None: + try: + return multiprocessing.cpu_count() + except NotImplementedError: + pass + try: + return os.sysconf("SC_NPROCESSORS_CONF") + except ValueError: + pass + logging.error("Could not detect number of processors; assuming 1") + return 1 + +def _reseed_random(): + if 'random' not in sys.modules: + return + import random + # If os.urandom is available, this method does the same thing as + # random.seed (at least as of python 2.6). If os.urandom is not + # available, we mix in the pid in addition to a timestamp. + try: + seed = long(hexlify(os.urandom(16)), 16) + except NotImplementedError: + seed(int(time.time() * 1000) ^ os.getpid()) + random.seed(seed) + + +_task_id = None + +def fork_processes(num_processes, max_restarts=100): + """Starts multiple worker processes. + + If ``num_processes`` is None or <= 0, we detect the number of cores + available on this machine and fork that number of child + processes. If ``num_processes`` is given and > 0, we fork that + specific number of sub-processes. + + Since we use processes and not threads, there is no shared memory + between any server code. + + Note that multiple processes are not compatible with the autoreload + module (or the debug=True option to `tornado.web.Application`). + When using multiple processes, no IOLoops can be created or + referenced until after the call to ``fork_processes``. + + In each child process, ``fork_processes`` returns its *task id*, a + number between 0 and ``num_processes``. Processes that exit + abnormally (due to a signal or non-zero exit status) are restarted + with the same id (up to ``max_restarts`` times). In the parent + process, ``fork_processes`` returns None if all child processes + have exited normally, but will otherwise only exit by throwing an + exception. + """ + global _task_id + assert _task_id is None + if num_processes is None or num_processes <= 0: + num_processes = cpu_count() + if ioloop.IOLoop.initialized(): + raise RuntimeError("Cannot run in multiple processes: IOLoop instance " + "has already been initialized. You cannot call " + "IOLoop.instance() before calling start_processes()") + logging.info("Starting %d processes", num_processes) + children = {} + def start_child(i): + pid = os.fork() + if pid == 0: + # child process + _reseed_random() + global _task_id + _task_id = i + return i + else: + children[pid] = i + return None + for i in range(num_processes): + id = start_child(i) + if id is not None: return id + num_restarts = 0 + while children: + try: + pid, status = os.wait() + except OSError, e: + if e.errno == errno.EINTR: + continue + raise + if pid not in children: + continue + id = children.pop(pid) + if os.WIFSIGNALED(status): + logging.warning("child %d (pid %d) killed by signal %d, restarting", + id, pid, os.WTERMSIG(status)) + elif os.WEXITSTATUS(status) != 0: + logging.warning("child %d (pid %d) exited with status %d, restarting", + id, pid, os.WEXITSTATUS(status)) + else: + logging.info("child %d (pid %d) exited normally", id, pid) + continue + num_restarts += 1 + if num_restarts > max_restarts: + raise RuntimeError("Too many child restarts, giving up") + new_id = start_child(id) + if new_id is not None: return new_id + +def task_id(): + """Returns the current task id, if any. + + Returns None if this process was not created by `fork_processes`. + """ + global _task_id + return _task_id diff --git a/interactive-mining-madoap/madoap/src/tornado/simple_httpclient.py b/interactive-mining-madoap/madoap/src/tornado/simple_httpclient.py new file mode 100644 index 0000000..a98eb54 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/simple_httpclient.py @@ -0,0 +1,458 @@ +#!/usr/bin/env python +from __future__ import with_statement + +from tornado.escape import utf8, _unicode, native_str +from tornado.httpclient import HTTPRequest, HTTPResponse, HTTPError, AsyncHTTPClient, main +from tornado.httputil import HTTPHeaders +from tornado.iostream import IOStream, SSLIOStream +from tornado import stack_context +from tornado.util import b + +import base64 +import collections +import contextlib +import copy +import functools +import logging +import os.path +import re +import socket +import time +import urlparse +import zlib + +try: + from io import BytesIO # python 3 +except ImportError: + from cStringIO import StringIO as BytesIO # python 2 + +try: + import ssl # python 2.6+ +except ImportError: + ssl = None + +_DEFAULT_CA_CERTS = os.path.dirname(__file__) + '/ca-certificates.crt' + +class SimpleAsyncHTTPClient(AsyncHTTPClient): + """Non-blocking HTTP client with no external dependencies. + + This class implements an HTTP 1.1 client on top of Tornado's IOStreams. + It does not currently implement all applicable parts of the HTTP + specification, but it does enough to work with major web service APIs + (mostly tested against the Twitter API so far). + + This class has not been tested extensively in production and + should be considered somewhat experimental as of the release of + tornado 1.2. It is intended to become the default AsyncHTTPClient + implementation in a future release. It may either be used + directly, or to facilitate testing of this class with an existing + application, setting the environment variable + USE_SIMPLE_HTTPCLIENT=1 will cause this class to transparently + replace tornado.httpclient.AsyncHTTPClient. + + Some features found in the curl-based AsyncHTTPClient are not yet + supported. In particular, proxies are not supported, connections + are not reused, and callers cannot select the network interface to be + used. + + Python 2.6 or higher is required for HTTPS support. Users of Python 2.5 + should use the curl-based AsyncHTTPClient if HTTPS support is required. + + """ + def initialize(self, io_loop=None, max_clients=10, + max_simultaneous_connections=None, + hostname_mapping=None, max_buffer_size=104857600): + """Creates a AsyncHTTPClient. + + Only a single AsyncHTTPClient instance exists per IOLoop + in order to provide limitations on the number of pending connections. + force_instance=True may be used to suppress this behavior. + + max_clients is the number of concurrent requests that can be in + progress. max_simultaneous_connections has no effect and is accepted + only for compatibility with the curl-based AsyncHTTPClient. Note + that these arguments are only used when the client is first created, + and will be ignored when an existing client is reused. + + hostname_mapping is a dictionary mapping hostnames to IP addresses. + It can be used to make local DNS changes when modifying system-wide + settings like /etc/hosts is not possible or desirable (e.g. in + unittests). + + max_buffer_size is the number of bytes that can be read by IOStream. It + defaults to 100mb. + """ + self.io_loop = io_loop + self.max_clients = max_clients + self.queue = collections.deque() + self.active = {} + self.hostname_mapping = hostname_mapping + self.max_buffer_size = max_buffer_size + + def fetch(self, request, callback, **kwargs): + if not isinstance(request, HTTPRequest): + request = HTTPRequest(url=request, **kwargs) + if not isinstance(request.headers, HTTPHeaders): + request.headers = HTTPHeaders(request.headers) + callback = stack_context.wrap(callback) + self.queue.append((request, callback)) + self._process_queue() + if self.queue: + logging.debug("max_clients limit reached, request queued. " + "%d active, %d queued requests." % ( + len(self.active), len(self.queue))) + + def _process_queue(self): + with stack_context.NullContext(): + while self.queue and len(self.active) < self.max_clients: + request, callback = self.queue.popleft() + key = object() + self.active[key] = (request, callback) + _HTTPConnection(self.io_loop, self, request, + functools.partial(self._release_fetch, key), + callback, + self.max_buffer_size) + + def _release_fetch(self, key): + del self.active[key] + self._process_queue() + + + +class _HTTPConnection(object): + _SUPPORTED_METHODS = set(["GET", "HEAD", "POST", "PUT", "DELETE"]) + + def __init__(self, io_loop, client, request, release_callback, + final_callback, max_buffer_size): + self.start_time = time.time() + self.io_loop = io_loop + self.client = client + self.request = request + self.release_callback = release_callback + self.final_callback = final_callback + self.code = None + self.headers = None + self.chunks = None + self._decompressor = None + # Timeout handle returned by IOLoop.add_timeout + self._timeout = None + with stack_context.StackContext(self.cleanup): + parsed = urlparse.urlsplit(_unicode(self.request.url)) + if ssl is None and parsed.scheme == "https": + raise ValueError("HTTPS requires either python2.6+ or " + "curl_httpclient") + if parsed.scheme not in ("http", "https"): + raise ValueError("Unsupported url scheme: %s" % + self.request.url) + # urlsplit results have hostname and port results, but they + # didn't support ipv6 literals until python 2.7. + netloc = parsed.netloc + if "@" in netloc: + userpass, _, netloc = netloc.rpartition("@") + match = re.match(r'^(.+):(\d+)$', netloc) + if match: + host = match.group(1) + port = int(match.group(2)) + else: + host = netloc + port = 443 if parsed.scheme == "https" else 80 + if re.match(r'^\[.*\]$', host): + # raw ipv6 addresses in urls are enclosed in brackets + host = host[1:-1] + if self.client.hostname_mapping is not None: + host = self.client.hostname_mapping.get(host, host) + + if request.allow_ipv6: + af = socket.AF_UNSPEC + else: + # We only try the first IP we get from getaddrinfo, + # so restrict to ipv4 by default. + af = socket.AF_INET + + addrinfo = socket.getaddrinfo(host, port, af, socket.SOCK_STREAM, + 0, 0) + af, socktype, proto, canonname, sockaddr = addrinfo[0] + + if parsed.scheme == "https": + ssl_options = {} + if request.validate_cert: + ssl_options["cert_reqs"] = ssl.CERT_REQUIRED + if request.ca_certs is not None: + ssl_options["ca_certs"] = request.ca_certs + else: + ssl_options["ca_certs"] = _DEFAULT_CA_CERTS + if request.client_key is not None: + ssl_options["keyfile"] = request.client_key + if request.client_cert is not None: + ssl_options["certfile"] = request.client_cert + self.stream = SSLIOStream(socket.socket(af, socktype, proto), + io_loop=self.io_loop, + ssl_options=ssl_options, + max_buffer_size=max_buffer_size) + else: + self.stream = IOStream(socket.socket(af, socktype, proto), + io_loop=self.io_loop, + max_buffer_size=max_buffer_size) + timeout = min(request.connect_timeout, request.request_timeout) + if timeout: + self._timeout = self.io_loop.add_timeout( + self.start_time + timeout, + self._on_timeout) + self.stream.set_close_callback(self._on_close) + self.stream.connect(sockaddr, + functools.partial(self._on_connect, parsed)) + + def _on_timeout(self): + self._timeout = None + self._run_callback(HTTPResponse(self.request, 599, + request_time=time.time() - self.start_time, + error=HTTPError(599, "Timeout"))) + self.stream.close() + + def _on_connect(self, parsed): + if self._timeout is not None: + self.io_loop.remove_timeout(self._timeout) + self._timeout = None + if self.request.request_timeout: + self._timeout = self.io_loop.add_timeout( + self.start_time + self.request.request_timeout, + self._on_timeout) + if (self.request.validate_cert and + isinstance(self.stream, SSLIOStream)): + match_hostname(self.stream.socket.getpeercert(), + parsed.hostname) + if (self.request.method not in self._SUPPORTED_METHODS and + not self.request.allow_nonstandard_methods): + raise KeyError("unknown method %s" % self.request.method) + for key in ('network_interface', + 'proxy_host', 'proxy_port', + 'proxy_username', 'proxy_password'): + if getattr(self.request, key, None): + raise NotImplementedError('%s not supported' % key) + if "Host" not in self.request.headers: + self.request.headers["Host"] = parsed.netloc + username, password = None, None + if parsed.username is not None: + username, password = parsed.username, parsed.password + elif self.request.auth_username is not None: + username = self.request.auth_username + password = self.request.auth_password + if username is not None: + auth = utf8(username) + b(":") + utf8(password) + self.request.headers["Authorization"] = (b("Basic ") + + base64.b64encode(auth)) + if self.request.user_agent: + self.request.headers["User-Agent"] = self.request.user_agent + if not self.request.allow_nonstandard_methods: + if self.request.method in ("POST", "PUT"): + assert self.request.body is not None + else: + assert self.request.body is None + if self.request.body is not None: + self.request.headers["Content-Length"] = str(len( + self.request.body)) + if (self.request.method == "POST" and + "Content-Type" not in self.request.headers): + self.request.headers["Content-Type"] = "application/x-www-form-urlencoded" + if self.request.use_gzip: + self.request.headers["Accept-Encoding"] = "gzip" + req_path = ((parsed.path or '/') + + (('?' + parsed.query) if parsed.query else '')) + request_lines = [utf8("%s %s HTTP/1.1" % (self.request.method, + req_path))] + for k, v in self.request.headers.get_all(): + line = utf8(k) + b(": ") + utf8(v) + if b('\n') in line: + raise ValueError('Newline in header: ' + repr(line)) + request_lines.append(line) + self.stream.write(b("\r\n").join(request_lines) + b("\r\n\r\n")) + if self.request.body is not None: + self.stream.write(self.request.body) + self.stream.read_until_regex(b("\r?\n\r?\n"), self._on_headers) + + def _release(self): + if self.release_callback is not None: + release_callback = self.release_callback + self.release_callback = None + release_callback() + + def _run_callback(self, response): + self._release() + if self.final_callback is not None: + final_callback = self.final_callback + self.final_callback = None + final_callback(response) + + @contextlib.contextmanager + def cleanup(self): + try: + yield + except Exception, e: + logging.warning("uncaught exception", exc_info=True) + self._run_callback(HTTPResponse(self.request, 599, error=e, + request_time=time.time() - self.start_time, + )) + + def _on_close(self): + self._run_callback(HTTPResponse( + self.request, 599, + request_time=time.time() - self.start_time, + error=HTTPError(599, "Connection closed"))) + + def _on_headers(self, data): + data = native_str(data.decode("latin1")) + first_line, _, header_data = data.partition("\n") + match = re.match("HTTP/1.[01] ([0-9]+)", first_line) + assert match + self.code = int(match.group(1)) + self.headers = HTTPHeaders.parse(header_data) + if self.request.header_callback is not None: + for k, v in self.headers.get_all(): + self.request.header_callback("%s: %s\r\n" % (k, v)) + if (self.request.use_gzip and + self.headers.get("Content-Encoding") == "gzip"): + # Magic parameter makes zlib module understand gzip header + # http://stackoverflow.com/questions/1838699/how-can-i-decompress-a-gzip-stream-with-zlib + self._decompressor = zlib.decompressobj(16+zlib.MAX_WBITS) + if self.headers.get("Transfer-Encoding") == "chunked": + self.chunks = [] + self.stream.read_until(b("\r\n"), self._on_chunk_length) + elif "Content-Length" in self.headers: + if "," in self.headers["Content-Length"]: + # Proxies sometimes cause Content-Length headers to get + # duplicated. If all the values are identical then we can + # use them but if they differ it's an error. + pieces = re.split(r',\s*', self.headers["Content-Length"]) + if any(i != pieces[0] for i in pieces): + raise ValueError("Multiple unequal Content-Lengths: %r" % + self.headers["Content-Length"]) + self.headers["Content-Length"] = pieces[0] + self.stream.read_bytes(int(self.headers["Content-Length"]), + self._on_body) + else: + self.stream.read_until_close(self._on_body) + + def _on_body(self, data): + if self._timeout is not None: + self.io_loop.remove_timeout(self._timeout) + self._timeout = None + if self._decompressor: + data = self._decompressor.decompress(data) + if self.request.streaming_callback: + if self.chunks is None: + # if chunks is not None, we already called streaming_callback + # in _on_chunk_data + self.request.streaming_callback(data) + buffer = BytesIO() + else: + buffer = BytesIO(data) # TODO: don't require one big string? + original_request = getattr(self.request, "original_request", + self.request) + if (self.request.follow_redirects and + self.request.max_redirects > 0 and + self.code in (301, 302)): + new_request = copy.copy(self.request) + new_request.url = urlparse.urljoin(self.request.url, + self.headers["Location"]) + new_request.max_redirects -= 1 + del new_request.headers["Host"] + new_request.original_request = original_request + final_callback = self.final_callback + self.final_callback = None + self._release() + self.client.fetch(new_request, final_callback) + self.stream.close() + return + response = HTTPResponse(original_request, + self.code, headers=self.headers, + request_time=time.time() - self.start_time, + buffer=buffer, + effective_url=self.request.url) + self._run_callback(response) + self.stream.close() + + def _on_chunk_length(self, data): + # TODO: "chunk extensions" http://tools.ietf.org/html/rfc2616#section-3.6.1 + length = int(data.strip(), 16) + if length == 0: + # all the data has been decompressed, so we don't need to + # decompress again in _on_body + self._decompressor = None + self._on_body(b('').join(self.chunks)) + else: + self.stream.read_bytes(length + 2, # chunk ends with \r\n + self._on_chunk_data) + + def _on_chunk_data(self, data): + assert data[-2:] == b("\r\n") + chunk = data[:-2] + if self._decompressor: + chunk = self._decompressor.decompress(chunk) + if self.request.streaming_callback is not None: + self.request.streaming_callback(chunk) + else: + self.chunks.append(chunk) + self.stream.read_until(b("\r\n"), self._on_chunk_length) + + +# match_hostname was added to the standard library ssl module in python 3.2. +# The following code was backported for older releases and copied from +# https://bitbucket.org/brandon/backports.ssl_match_hostname +class CertificateError(ValueError): + pass + +def _dnsname_to_pat(dn): + pats = [] + for frag in dn.split(r'.'): + if frag == '*': + # When '*' is a fragment by itself, it matches a non-empty dotless + # fragment. + pats.append('[^.]+') + else: + # Otherwise, '*' matches any dotless fragment. + frag = re.escape(frag) + pats.append(frag.replace(r'\*', '[^.]*')) + return re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) + +def match_hostname(cert, hostname): + """Verify that *cert* (in decoded format as returned by + SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 rules + are mostly followed, but IP addresses are not accepted for *hostname*. + + CertificateError is raised on failure. On success, the function + returns nothing. + """ + if not cert: + raise ValueError("empty or no certificate") + dnsnames = [] + san = cert.get('subjectAltName', ()) + for key, value in san: + if key == 'DNS': + if _dnsname_to_pat(value).match(hostname): + return + dnsnames.append(value) + if not san: + # The subject is only checked when subjectAltName is empty + for sub in cert.get('subject', ()): + for key, value in sub: + # XXX according to RFC 2818, the most specific Common Name + # must be used. + if key == 'commonName': + if _dnsname_to_pat(value).match(hostname): + return + dnsnames.append(value) + if len(dnsnames) > 1: + raise CertificateError("hostname %r " + "doesn't match either of %s" + % (hostname, ', '.join(map(repr, dnsnames)))) + elif len(dnsnames) == 1: + raise CertificateError("hostname %r " + "doesn't match %r" + % (hostname, dnsnames[0])) + else: + raise CertificateError("no appropriate commonName or " + "subjectAltName fields were found") + +if __name__ == "__main__": + AsyncHTTPClient.configure(SimpleAsyncHTTPClient) + main() diff --git a/interactive-mining-madoap/madoap/src/tornado/stack_context.py b/interactive-mining-madoap/madoap/src/tornado/stack_context.py new file mode 100644 index 0000000..d64e3cf --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/stack_context.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python +# +# Copyright 2010 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +'''StackContext allows applications to maintain threadlocal-like state +that follows execution as it moves to other execution contexts. + +The motivating examples are to eliminate the need for explicit +async_callback wrappers (as in tornado.web.RequestHandler), and to +allow some additional context to be kept for logging. + +This is slightly magic, but it's an extension of the idea that an exception +handler is a kind of stack-local state and when that stack is suspended +and resumed in a new context that state needs to be preserved. StackContext +shifts the burden of restoring that state from each call site (e.g. +wrapping each AsyncHTTPClient callback in async_callback) to the mechanisms +that transfer control from one context to another (e.g. AsyncHTTPClient +itself, IOLoop, thread pools, etc). + +Example usage:: + + @contextlib.contextmanager + def die_on_error(): + try: + yield + except Exception: + logging.error("exception in asynchronous operation",exc_info=True) + sys.exit(1) + + with StackContext(die_on_error): + # Any exception thrown here *or in callback and its desendents* + # will cause the process to exit instead of spinning endlessly + # in the ioloop. + http_client.fetch(url, callback) + ioloop.start() +''' + +from __future__ import with_statement + +import contextlib +import functools +import itertools +import sys +import threading + +class _State(threading.local): + def __init__(self): + self.contexts = () +_state = _State() + +class StackContext(object): + '''Establishes the given context as a StackContext that will be transferred. + + Note that the parameter is a callable that returns a context + manager, not the context itself. That is, where for a + non-transferable context manager you would say:: + + with my_context(): + + StackContext takes the function itself rather than its result:: + + with StackContext(my_context): + ''' + def __init__(self, context_factory): + self.context_factory = context_factory + + # Note that some of this code is duplicated in ExceptionStackContext + # below. ExceptionStackContext is more common and doesn't need + # the full generality of this class. + def __enter__(self): + self.old_contexts = _state.contexts + # _state.contexts is a tuple of (class, arg) pairs + _state.contexts = (self.old_contexts + + ((StackContext, self.context_factory),)) + try: + self.context = self.context_factory() + self.context.__enter__() + except Exception: + _state.contexts = self.old_contexts + raise + + def __exit__(self, type, value, traceback): + try: + return self.context.__exit__(type, value, traceback) + finally: + _state.contexts = self.old_contexts + +class ExceptionStackContext(object): + '''Specialization of StackContext for exception handling. + + The supplied exception_handler function will be called in the + event of an uncaught exception in this context. The semantics are + similar to a try/finally clause, and intended use cases are to log + an error, close a socket, or similar cleanup actions. The + exc_info triple (type, value, traceback) will be passed to the + exception_handler function. + + If the exception handler returns true, the exception will be + consumed and will not be propagated to other exception handlers. + ''' + def __init__(self, exception_handler): + self.exception_handler = exception_handler + + def __enter__(self): + self.old_contexts = _state.contexts + _state.contexts = (self.old_contexts + + ((ExceptionStackContext, self.exception_handler),)) + + def __exit__(self, type, value, traceback): + try: + if type is not None: + return self.exception_handler(type, value, traceback) + finally: + _state.contexts = self.old_contexts + +class NullContext(object): + '''Resets the StackContext. + + Useful when creating a shared resource on demand (e.g. an AsyncHTTPClient) + where the stack that caused the creating is not relevant to future + operations. + ''' + def __enter__(self): + self.old_contexts = _state.contexts + _state.contexts = () + + def __exit__(self, type, value, traceback): + _state.contexts = self.old_contexts + +class _StackContextWrapper(functools.partial): + pass + +def wrap(fn): + '''Returns a callable object that will restore the current StackContext + when executed. + + Use this whenever saving a callback to be executed later in a + different execution context (either in a different thread or + asynchronously in the same thread). + ''' + if fn is None or fn.__class__ is _StackContextWrapper: + return fn + # functools.wraps doesn't appear to work on functools.partial objects + #@functools.wraps(fn) + def wrapped(callback, contexts, *args, **kwargs): + if contexts is _state.contexts or not contexts: + callback(*args, **kwargs) + return + if not _state.contexts: + new_contexts = [cls(arg) for (cls, arg) in contexts] + # If we're moving down the stack, _state.contexts is a prefix + # of contexts. For each element of contexts not in that prefix, + # create a new StackContext object. + # If we're moving up the stack (or to an entirely different stack), + # _state.contexts will have elements not in contexts. Use + # NullContext to clear the state and then recreate from contexts. + elif (len(_state.contexts) > len(contexts) or + any(a[1] is not b[1] + for a, b in itertools.izip(_state.contexts, contexts))): + # contexts have been removed or changed, so start over + new_contexts = ([NullContext()] + + [cls(arg) for (cls,arg) in contexts]) + else: + new_contexts = [cls(arg) + for (cls, arg) in contexts[len(_state.contexts):]] + if len(new_contexts) > 1: + with _nested(*new_contexts): + callback(*args, **kwargs) + elif new_contexts: + with new_contexts[0]: + callback(*args, **kwargs) + else: + callback(*args, **kwargs) + if _state.contexts: + return _StackContextWrapper(wrapped, fn, _state.contexts) + else: + return _StackContextWrapper(fn) + +@contextlib.contextmanager +def _nested(*managers): + """Support multiple context managers in a single with-statement. + + Copied from the python 2.6 standard library. It's no longer present + in python 3 because the with statement natively supports multiple + context managers, but that doesn't help if the list of context + managers is not known until runtime. + """ + exits = [] + vars = [] + exc = (None, None, None) + try: + for mgr in managers: + exit = mgr.__exit__ + enter = mgr.__enter__ + vars.append(enter()) + exits.append(exit) + yield vars + except: + exc = sys.exc_info() + finally: + while exits: + exit = exits.pop() + try: + if exit(*exc): + exc = (None, None, None) + except: + exc = sys.exc_info() + if exc != (None, None, None): + # Don't rely on sys.exc_info() still containing + # the right information. Another exception may + # have been raised and caught by an exit method + raise exc[0], exc[1], exc[2] + diff --git a/interactive-mining-madoap/madoap/src/tornado/template.py b/interactive-mining-madoap/madoap/src/tornado/template.py new file mode 100644 index 0000000..f28f403 --- /dev/null +++ b/interactive-mining-madoap/madoap/src/tornado/template.py @@ -0,0 +1,767 @@ +#!/usr/bin/env python +# +# Copyright 2009 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""A simple template system that compiles templates to Python code. + +Basic usage looks like:: + + t = template.Template("{{ myvalue }}") + print t.generate(myvalue="XXX") + +Loader is a class that loads templates from a root directory and caches +the compiled templates:: + + loader = template.Loader("/home/btaylor") + print loader.load("test.html").generate(myvalue="XXX") + +We compile all templates to raw Python. Error-reporting is currently... uh, +interesting. Syntax for the templates:: + + ### base.html + + + {% block title %}Default title{% end %} + + +
    + {% for student in students %} + {% block student %} +
  • {{ escape(student.name) }}
  • + {% end %} + {% end %} +
+ + + + ### bold.html + {% extends "base.html" %} + + {% block title %}A bolder title{% end %} + + {% block student %} +
  • {{ escape(student.name) }}
  • + {% end %} + +Unlike most other template systems, we do not put any restrictions on the +expressions you can include in your statements. if and for blocks get +translated exactly into Python, you can do complex expressions like:: + + {% for student in [p for p in people if p.student and p.age > 23] %} +
  • {{ escape(student.name) }}
  • + {% end %} + +Translating directly to Python means you can apply functions to expressions +easily, like the escape() function in the examples above. You can pass +functions in to your template just like any other variable:: + + ### Python code + def add(x, y): + return x + y + template.execute(add=add) + + ### The template + {{ add(1, 2) }} + +We provide the functions escape(), url_escape(), json_encode(), and squeeze() +to all templates by default. + +Typical applications do not create `Template` or `Loader` instances by +hand, but instead use the `render` and `render_string` methods of +`tornado.web.RequestHandler`, which load templates automatically based +on the ``template_path`` `Application` setting. + +Syntax Reference +---------------- + +Template expressions are surrounded by double curly braces: ``{{ ... }}``. +The contents may be any python expression, which will be escaped according +to the current autoescape setting and inserted into the output. Other +template directives use ``{% %}``. These tags may be escaped as ``{{!`` +and ``{%!`` if you need to include a literal ``{{`` or ``{%`` in the output. + +``{% apply *function* %}...{% end %}`` + Applies a function to the output of all template code between ``apply`` + and ``end``:: + + {% apply linkify %}{{name}} said: {{message}}{% end %} + +``{% autoescape *function* %}`` + Sets the autoescape mode for the current file. This does not affect + other files, even those referenced by ``{% include %}``. Note that + autoescaping can also be configured globally, at the `Application` + or `Loader`.:: + + {% autoescape xhtml_escape %} + {% autoescape None %} + +``{% block *name* %}...{% end %}`` + Indicates a named, replaceable block for use with ``{% extends %}``. + Blocks in the parent template will be replaced with the contents of + the same-named block in a child template.:: + + + {% block title %}Default title{% end %} + + + {% extends "base.html" %} + {% block title %}My page title{% end %} + +``{% comment ... %}`` + A comment which will be removed from the template output. Note that + there is no ``{% end %}`` tag; the comment goes from the word ``comment`` + to the closing ``%}`` tag. + +``{% extends *filename* %}`` + Inherit from another template. Templates that use ``extends`` should + contain one or more ``block`` tags to replace content from the parent + template. Anything in the child template not contained in a ``block`` + tag will be ignored. For an example, see the ``{% block %}`` tag. + +``{% for *var* in *expr* %}...{% end %}`` + Same as the python ``for`` statement. + +``{% from *x* import *y* %}`` + Same as the python ``import`` statement. + +``{% if *condition* %}...{% elif *condition* %}...{% else %}...{% end %}`` + Conditional statement - outputs the first section whose condition is + true. (The ``elif`` and ``else`` sections are optional) + +``{% import *module* %}`` + Same as the python ``import`` statement. + +``{% include *filename* %}`` + Includes another template file. The included file can see all the local + variables as if it were copied directly to the point of the ``include`` + directive (the ``{% autoescape %}`` directive is an exception). + Alternately, ``{% module Template(filename, **kwargs) %}`` may be used + to include another template with an isolated namespace. + +``{% module *expr* %}`` + Renders a `~tornado.web.UIModule`. The output of the ``UIModule`` is + not escaped:: + + {% module Template("foo.html", arg=42) %} + +``{% raw *expr* %}`` + Outputs the result of the given expression without autoescaping. + +``{% set *x* = *y* %}`` + Sets a local variable. + +``{% try %}...{% except %}...{% finally %}...{% end %}`` + Same as the python ``try`` statement. + +``{% while *condition* %}... {% end %}`` + Same as the python ``while`` statement. +""" + +from __future__ import with_statement + +import cStringIO +import datetime +import logging +import os.path +import posixpath +import re + +from tornado import escape +from tornado.util import bytes_type + +_DEFAULT_AUTOESCAPE = "xhtml_escape" +_UNSET = object() + +class Template(object): + """A compiled template. + + We compile into Python from the given template_string. You can generate + the template from variables with generate(). + """ + def __init__(self, template_string, name="", loader=None, + compress_whitespace=None, autoescape=_UNSET): + self.name = name + if compress_whitespace is None: + compress_whitespace = name.endswith(".html") or \ + name.endswith(".js") + if autoescape is not _UNSET: + self.autoescape = autoescape + elif loader: + self.autoescape = loader.autoescape + else: + self.autoescape = _DEFAULT_AUTOESCAPE + self.namespace = loader.namespace if loader else {} + reader = _TemplateReader(name, escape.native_str(template_string)) + self.file = _File(_parse(reader, self)) + self.code = self._generate_python(loader, compress_whitespace) + try: + self.compiled = compile(escape.to_unicode(self.code), + "