diff options
Diffstat (limited to 'src')
87 files changed, 5593 insertions, 0 deletions
diff --git a/src/neuralnetwork/clean_data.py b/src/neuralnetwork/clean_data.py new file mode 100644 index 0000000..345218e --- /dev/null +++ b/src/neuralnetwork/clean_data.py @@ -0,0 +1,59 @@ +import training +import os +import sys + +if __name__ == "__main__": + + countries = training.get_countries() + + for c, country in countries.items(): + if c == "uk" or c == "usa": + + # iterate through each dataset separately + for dataset, path in country.datasets.items(): + + # print information + print(f"filtering through {c}'s {dataset}...") + sys.stdout.flush() + + names = country.get_names(dataset) + + # store the names that are valid in a seperate list + names_output = [] + + # load the alphabet file for the country + alphabet = [] + + with open(os.path.join(country.path, "alphabet.txt"), "r") as file: + for l in file.read().split("\n"): + alphabet.append(l) + + c = 0 + t = len(names) + # iterate through names in the dataset + for name in names: + name = country.preprocess(name) + + valid = True + + # invalidate the name if a single letter is not in the alphabet + for letter in name: + if not letter in alphabet: + valid = False + break + + if valid: + names_output.append(name) + + c += 1 + if c % 128 == 0: + print(f"\r{c}/{t}", end="") + + # print how many names are left + print(f"kept {len(names_output)}/{len(names)} names") + + # save dataset + with open(path, "w") as file: + for name in names_output: + file.write(name) + file.write("\n") diff --git a/src/neuralnetwork/data/ipa.csv b/src/neuralnetwork/data/ipa.csv new file mode 100644 index 0000000..6965ce5 --- /dev/null +++ b/src/neuralnetwork/data/ipa.csv @@ -0,0 +1,174 @@ +p,p,vl bilabial plosive +b,b,vd bilabial plosive +t,t,vl alveolar plosive +d,d,vd alveolar plosive +ʈ,t`,vl retroflex plosive +ɖ,d`,vd retroflex plosive +c,c,vl palatal plosive +ɟ,J\,vd palatal plosive +k,k,ld velar plosive +ɡ,g,vd velar plosive +q,q,vl uvular plosive +ɢ,G\,vd uvular plosive +ʔ,?,glottal plosive +m,m,bilabial nasal +ɱ,F,vl labiodental nasal +n,n,alveolar nasal +ɳ,n`,vl retroflex nasal +ɲ,J,vl palatal nasal +ŋ,N,vl velar nasal +ɴ,N\,vl uvular nasal +ʙ,B\,vd bilabial trill +r,r,vd alveolar trill +ʀ,R\,vl uvular trill +ɾ,4,vl alveolar tap +ɽ,r`,vl retroflex flap +ɸ,p\,vl bilabial fricative +β,B,vd bilabial fricative +f,f,vl labiodental fricative +v,v,vd labiodental fricative +θ,T,vl dental fricative +ð,D,vd dental fricative +s,s,vl alveolar fricative +z,z,vd alveolar fricative +ʃ,S,vl postalveolar fricative +ʒ,Z,vd postalveolar fricative +ʂ,s`,vl retroflex fricative +ʐ,z`,vd retroflex fricative +ç,C,vl palatal fricative +ʝ,j\,vd palatal fricative +x,x,vl velar fricative +ɣ,G,vd velar fricative +χ,X,vl uvular fricative +ʁ,R,vd uvular fricative +ħ,X\,vl pharyngeal fricative +ʕ,?\,vd pharyngeal fricative +h,h,vl glottal fricative +ʔ,?,glottal plosive +ɬ,K,vl alveolar lateral fricative +ɮ,K\,vd alveolar lateral fricative +ʋ,P,vd labiodental approximant +ɹ,r\,vd (post)alveolar approximant +ɻ,r\`,vd retroflex approximant +j,j,vd palatal approximant +ɰ,M\,vd velar approximant +l,l,vd alveolar lateral approximant +ɭ,l`,vd retroflex lateral approximant +ʎ,L,vd palatal lateral approximant +ʟ,L\,vd velar lateral approximant +pʼ,p_>,ejective +tʼ,t_>,ejective +ʈʼ,t`_>,ejective +cʼ,c_>,ejective +kʼ,k_>,ejective +qʼ,q_>,ejective +ɓ,b_<,vl bilabial implosive +ɗ,d_<,vl alveolar implosive +ƙ,k_<,vl velar implosive +ɠ,g_<,vl velar implosive +i,i,close front unrounded +y,y,close front rounded +ɨ,1,close central unrounded +ʉ,},close central rounded +ɯ,M,close back unrounded +u,u,close back rounded +ɪ,I,lax close front unrounded +ʏ,Y,lax close front rounded +ʊ,U,lax close back rounded +e,e,close-mid front unrounded +ø,2,front close-mid rounded +ɤ,7,close-mid back unrounded +o,o,close-mid back rounded +ə,@,schwa +ɘ,@\,close-mid central unrounded vowel +ɵ,8,rounded schwa +ɛ,E,open-mid front unrounded +œ,9,front open-mid rounded +ʌ,V,open-mid back unrounded +ɔ,O,open-mid back rounded +æ,{,mid-open front unrounded vowel +ɐ,6,open-mid schwa +a,a,open front unrounded +ă,a_X,extra short open front unrounded +ɶ,&,front open rounded +ɑ,A,open back unrounded +ɒ,Q,open back rounded +̥,_0,voiceless +̬,_v,voiced +ʰ,_h,aspirated +̤,_t,breathy voiced +̰,_k,creaky voiced +̼,_N,linguolabial +̪,_d,dental +̺,_a,apical +̻,_m,laminal +̹,_O,more rounded +̜,_c,less rounded +̟,_+,advanced +̠,_-,retracted +̈,"_""",centralized +̽,_x,mid-centralized +̩,=,syllabic +̯,_^,non-syllabic +ʷ,_w,labialized +ʲ,',palatalized +ˠ,_G,velarized +ˤ,_?\,pharyngealized +̴,_e,velarized or pharyngealized +̝,_r,raised +̞,_o,lowered +̃,~,nasalized +ⁿ,_n,nasal release +ˡ,_l,lateral release +̚,_},not audibly released +̘,_A,advanced tongue root +̙,_q,retracted tongue root +̋,_T,extra high tone +́,_H,high tone +̄,_M,mid tone +̀,_L,low tone +̏,_B,extra low tone +ˈ,"""",(primary) stress mark +ˌ,%,secondary stress +ː,:,length mark +ˑ,:\,half-length +̆,_X,extra-short +.,.,syllable break +ʍ,W,vl labial-velar fricative +w,w,vd labio-velar approximant +ɥ,H,labial-palatal approximant +ʜ,H\,vl epiglottal fricative +ʢ,<\,vl epiglottal fricative +ʡ,>\,vl epiglottal plosive +ɕ,s\,vl alveolopalatal fricative +ʑ,z\,vl alveolopalatal fricative +ʘ,O\,bilabial click +ǀ,|\,dental click +ǃ,!\,click +ǂ,'=\,alveolar click +ǁ,|\|\,alveolar lateral click +ɺ,l\,vl alveolar lateral flap +ɜ,3,open-mid central +ʛ,G\_<,vl uvular implosive +ɚ,@`,rhotacized schwa +ɞ,3\,open-mid central rounded +ɦ,h\,vd glottal fricative +ɫ,5,velarized vl alveolar lateral +ʄ,J\_<,vl palatal implosive +ʼ,_>,ejective +ɝ,3`,rhotacized open-mid central +t͡ʃ,tS,vl postalveolar affricate +d͡ʒ,dZ,vd postalveolar affricate +t͡ɕ,ts\,vl alveolo-palatal affricate +d͡ʑ,dz\,vd alveolo-palatal affricate +t͡ɬ,tK,vl alveolar lateral affricate +k͡p,kp,vl labial-velar plosive +g͡b,gb,vd labial-velar plosive +ŋ͡m,Nm,labial-velar nasal stop +ʈ͡ʂ,ts`,vl retroflex affricate +ɖ͡ʐ,tz`,vd retroflex affricate +˩,_B,extra low tone +˨,_L,low tone +˧,_M,mid tone +˦,_H,high tone +˥,_T,extra high tone diff --git a/src/neuralnetwork/data/names/English.txt b/src/neuralnetwork/data/names/English.txt new file mode 100755 index 0000000..2b943a7 --- /dev/null +++ b/src/neuralnetwork/data/names/English.txt @@ -0,0 +1,3668 @@ +Abbas +Abbey +Abbott +Abdi +Abel +Abraham +Abrahams +Abrams +Ackary +Ackroyd +Acton +Adair +Adam +Adams +Adamson +Adanet +Addams +Adderley +Addinall +Addis +Addison +Addley +Aderson +Adey +Adkins +Adlam +Adler +Adrol +Adsett +Agar +Ahern +Aherne +Ahmad +Ahmed +Aikman +Ainley +Ainsworth +Aird +Airey +Aitchison +Aitken +Akhtar +Akram +Alam +Alanson +Alber +Albert +Albrighton +Albutt +Alcock +Alden +Alder +Aldersley +Alderson +Aldred +Aldren +Aldridge +Aldworth +Alesbury +Alexandar +Alexander +Alexnader +Alford +Algar +Ali +Alker +Alladee +Allam +Allan +Allard +Allaway +Allcock +Allcott +Alldridge +Alldritt +Allen +Allgood +Allington +Alliott +Allison +Allkins +Allman +Allport +Allsop +Allum +Allwood +Almond +Alpin +Alsop +Altham +Althoff +Alves +Alvey +Alway +Ambrose +Amesbury +Amin +Amner +Amod +Amor +Amos +Anakin +Anderson +Andersson +Anderton +Andrew +Andrews +Angus +Anker +Anley +Annan +Anscombe +Ansell +Anstee +Anthony +Antic +Anton +Antony +Antram +Anwar +Appleby +Appleton +Appleyard +Apsley +Arah +Archer +Ardern +Arkins +Armer +Armitage +Armour +Armsden +Armstrong +Arnall +Arnett +Arnold +Arnott +Arrowsmith +Arscott +Arthur +Artliff +Ashbridge +Ashbrook +Ashby +Ashcroft +Ashdown +Ashe +Asher +Ashford +Ashley +Ashman +Ashton +Ashurst +Ashwell +Ashworth +Askew +Aslam +Asom +Aspey +Aspin +Aspinall +Astbury +Astle +Astley +Aston +Atherley +Atherstone +Atherton +Atkin +Atkins +Atkinson +Attard +Atter +Atterbury +Atterton +Attewell +Attrill +Attwood +Auberton +Auborn +Aubrey +Austen +Austin +Auton +Avenue +Avery +Aves +Avis +Awad +Axon +Aylett +Ayley +Ayliffe +Ayling +Aylott +Aylward +Ayres +Ayton +Aziz +Bacon +Bailey +Bain +Bainbridge +Baines +Bains +Baird +Baker +Baldwin +Bale +Ball +Ballantyne +Ballard +Bamford +Bancroft +Banks +Banner +Bannister +Barber +Barclay +Barker +Barlow +Barnard +Barnes +Barnett +Baron +Barr +Barrett +Barron +Barrow +Barry +Bartlett +Barton +Bass +Bassett +Batchelor +Bate +Bateman +Bates +Batt +Batten +Batty +Baxter +Bayliss +Beadle +Beal +Beale +Beamish +Bean +Bear +Beattie +Beatty +Beaumont +Beck +Bedford +Beech +Beer +Begum +Bell +Bellamy +Benfield +Benjamin +Bennett +Benson +Bentley +Berger +Bernard +Berry +Best +Bethell +Betts +Bevan +Beveridge +Bickley +Biddle +Biggs +Bill +Bing +Bingham +Binnington +Birch +Bird +Bishop +Bithell +Black +Blackburn +Blackman +Blackmore +Blackwell +Blair +Blake +Blakeley +Blakey +Blanchard +Bland +Bloggs +Bloom +Blundell +Blythe +Bob +Boden +Boland +Bolton +Bond +Bone +Bonner +Boon +Booth +Borland +Bostock +Boulton +Bourne +Bouvet +Bowden +Bowen +Bower +Bowers +Bowes +Bowler +Bowles +Bowman +Boyce +Boyd +Boyle +Bracey +Bradbury +Bradley +Bradshaw +Brady +Brain +Braithwaite +Bramley +Brandrick +Bray +Breen +Brelsford +Brennan +Brett +Brewer +Bridges +Briggs +Bright +Bristow +Britton +Broadbent +Broadhurst +Broadley +Brock +Brook +Brooke +Brooker +Brookes +Brookfield +Brooks +Broomfield +Broughton +Brown +Browne +Browning +Bruce +Brunet +Brunton +Bryan +Bryant +Bryson +Buchan +Buchanan +Buck +Buckingham +Buckley +Budd +Bugg +Bull +Bullock +Burch +Burden +Burdett +Burford +Burge +Burgess +Burke +Burland +Burman +Burn +Burnett +Burns +Burr +Burrows +Burt +Burton +Busby +Bush +Butcher +Butler +Butt +Butter +Butterworth +Button +Buxton +Byrne +Caddy +Cadman +Cahill +Cain +Cairns +Caldwell +Callaghan +Callow +Calveley +Calvert +Cameron +Campbell +Cann +Cannon +Caplan +Capper +Carey +Carling +Carmichael +Carnegie +Carney +Carpenter +Carr +Carrington +Carroll +Carruthers +Carson +Carter +Cartwright +Carty +Casey +Cashmore +Cassidy +Caton +Cavanagh +Cawley +Chadwick +Chalmers +Chamberlain +Chambers +Chan +Chance +Chandler +Chantler +Chaplin +Chapman +Chappell +Chapple +Charge +Charles +Charlton +Charnock +Chase +Chatterton +Chauhan +Cheetham +Chelmy +Cherry +Cheshire +Chester +Cheung +Chidlow +Child +Childs +Chilvers +Chisholm +Chong +Christie +Christy +Chung +Church +Churchill +Clamp +Clancy +Clark +Clarke +Clarkson +Clay +Clayton +Cleary +Cleaver +Clegg +Clements +Cliff +Clifford +Clifton +Close +Clough +Clowes +Coates +Coburn +Cochrane +Cockburn +Cockle +Coffey +Cohen +Cole +Coleman +Coles +Coll +Collard +Collett +Colley +Collier +Collingwood +Collins +Collinson +Colman +Compton +Conneely +Connell +Connelly +Connolly +Connor +Conrad +Conroy +Conway +Cook +Cooke +Cookson +Coomber +Coombes +Cooper +Cope +Copeland +Copland +Copley +Corbett +Corcoran +Core +Corlett +Cormack +Corner +Cornish +Cornock +Corr +Corrigan +Cosgrove +Costa +Costello +Cotter +Cotterill +Cotton +Cottrell +Couch +Coulson +Coulter +Court +Cousin +Cousins +Cove +Cowan +Coward +Cowell +Cowie +Cowley +Cox +Coyle +Crabb +Crabtree +Cracknell +Craig +Crane +Craven +Crawford +Crawley +Creasey +Cresswell +Crew +Cripps +Crisp +Crocker +Croft +Crofts +Cronin +Crook +Crosby +Cross +Crossland +Crossley +Crouch +Croucher +Crow +Crowe +Crowley +Crown +Crowther +Crump +Cullen +Cumming +Cummings +Cummins +Cunningham +Curley +Curran +Currie +Curry +Curtis +Curwood +Cutts +D arcy +Dacey +Dack +Dalby +Dale +Daley +Dallas +Dalton +Daly +Dalzell +Damon +Danby +Dandy +Daniel +Daniells +Daniels +Danks +Dann +Darby +Darbyshire +Darcy +Dardenne +Darlington +Darr +Daugherty +Davenport +Davey +David +Davidson +Davie +Davies +Davis +Davison +Davy +Dawe +Dawes +Dawkins +Dawson +Day +Dayman +De ath +Deacon +Deakin +Dean +Deane +Deans +Debenham +Deegan +Deeley +Deighton +Delamarre +Delaney +Dell +Dempsey +Dempster +Denby +Denham +Denis +Denney +Dennis +Dent +Denton +Depp +Dermody +Derrick +Derrien +Dervish +Desai +Devaney +Devenish +Deverell +Devine +Devlin +Devon +Devonport +Dewar +Dexter +Diamond +Dibble +Dick +Dickens +Dickenson +Dicker +Dickinson +Dickson +Dillon +Dimmock +Dingle +Dipper +Dixon +Dobbin +Dobbins +Doble +Dobson +Docherty +Docker +Dodd +Dodds +Dodson +Doherty +Dolan +Dolcy +Dolman +Dolton +Donald +Donaldson +Donkin +Donlan +Donn +Donnachie +Donnelly +Donoghue +Donohoe +Donovan +Dooley +Doolin +Doon +Doors +Dora +Doran +Dorman +Dornan +Dorrian +Dorrington +Dougal +Dougherty +Doughty +Douglas +Douthwaite +Dove +Dover +Dowell +Dowler +Dowling +Down +Downer +Downes +Downey +Downie +Downing +Downs +Downton +Dowson +Doyle +Drabble +Drain +Drake +Draper +Drew +Drewett +Dreyer +Driffield +Drinkwater +Driscoll +Driver +Drummond +Drury +Drysdale +Dubois +Duck +Duckworth +Ducon +Dudley +Duff +Duffield +Duffin +Duffy +Dufour +Duggan +Duke +Dukes +Dumont +Duncan +Dundon +Dunford +Dunkley +Dunlop +Dunmore +Dunn +Dunne +Dunnett +Dunning +Dunsford +Dupont +Durand +Durant +Durber +Durham +Durrant +Dutt +Duval +Duvall +Dwyer +Dyde +Dyer +Dyerson +Dykes +Dymond +Dymott +Dyson +Eade +Eadie +Eagle +Eales +Ealham +Ealy +Eames +Eansworth +Earing +Earl +Earle +Earley +Easdale +Easdown +Easen +Eason +East +Eastaugh +Eastaway +Eastell +Easterbrook +Eastham +Easton +Eastwood +Eatherington +Eaton +Eaves +Ebbs +Ebden +Ebdon +Ebeling +Eburne +Eccles +Eccleston +Ecclestone +Eccott +Eckersall +Eckersley +Eddison +Eddleston +Eddy +Eden +Edeson +Edgar +Edge +Edgell +Edgerton +Edgley +Edgson +Edkins +Edler +Edley +Edlington +Edmond +Edmonds +Edmondson +Edmunds +Edmundson +Edney +Edon +Edwards +Edwick +Eedie +Egan +Egerton +Eggby +Eggison +Eggleston +Eglan +Egleton +Eglin +Eilers +Ekin +Elbutt +Elcock +Elder +Eldeston +Eldridge +Eley +Elfman +Elford +Elkin +Elkington +Ellam +Ellans +Ellard +Elleray +Ellerby +Ellershaw +Ellery +Elliman +Elling +Ellingham +Elliot +Elliott +Ellis +Ellison +Elliston +Ellrott +Ellwood +Elmer +Elmes +Elmhirst +Elmore +Elms +Elphick +Elsdon +Elsmore +Elson +Elston +Elstone +Eltis +Elven +Elvin +Elvins +Elwell +Elwood +Elworthy +Elzer +Emberey +Emberson +Embleton +Emerick +Emerson +Emery +Emmanuel +Emmerson +Emmery +Emmett +Emmings +Emmins +Emmons +Emmott +Emms +Emsden +Endroe +England +English +Ennis +Ennos +Enright +Enticott +Entwistle +Epsom +Epton +Ernest +Erridge +Errington +Errity +Esan +Escott +Eskins +Eslick +Espley +Essam +Essan +Essop +Estlick +Etchells +Etheridge +Etherington +Etherton +Ettrick +Evans +Evason +Evenden +Everdell +Everett +Everill +Everitt +Everson +Everton +Eveson +Evison +Evrard +Ewart +Ewin +Ewing +Ewles +Exley +Exon +Exton +Eyett +Eyles +Eyre +Eyres +Fabb +Fagan +Fagon +Fahy +Fairbairn +Fairbrace +Fairbrother +Fairchild +Fairclough +Fairhurst +Fairley +Fairlie +Fairweather +Falconer +Falk +Fall +Fallon +Fallows +Falsh +Farge +Fargher +Farhall +Farley +Farmer +Farnsworth +Farnum +Farnworth +Farr +Farrant +Farrar +Farre +Farrell +Farrelly +Farren +Farrer +Farrier +Farrington +Farrow +Faulkner +Faust +Fawcett +Fawn +Faye +Fearn +Fearnley +Fearns +Fearon +Featherstone +Feeney +Feetham +Felix +Fell +Fellmen +Fellows +Feltham +Felton +Fenlon +Fenn +Fenton +Fenwick +Ferdinand +Fereday +Ferguson +Fern +Fernandez +Ferns +Fernyhough +Ferreira +Ferrier +Ferris +Ferry +Fewtrell +Field +Fielder +Fielding +Fields +Fifield +Finan +Finbow +Finch +Findlay +Findley +Finlay +Finn +Finnegan +Finney +Finnigan +Finnimore +Firth +Fischer +Fish +Fisher +Fishlock +Fisk +Fitch +Fitchett +Fitton +Fitzgerald +Fitzpatrick +Fitzsimmons +Flack +Flaherty +Flanagan +Flanders +Flannery +Flavell +Flaxman +Fleetwood +Fleming +Fletcher +Flett +Florey +Floss +Flower +Flowers +Floyd +Flynn +Foden +Fogg +Foley +Fontaine +Foran +Forbes +Ford +Forde +Fordham +Foreman +Forester +Forman +Forrest +Forrester +Forshaw +Forster +Forsyth +Forsythe +Forth +Fortin +Foss +Fossard +Fosse +Foster +Foston +Fothergill +Fotheringham +Foucher +Foulkes +Fountain +Fowler +Fowley +Fox +Foxall +Foxley +Frame +Frampton +France +Francis +Franco +Frankish +Frankland +Franklin +Franks +Frary +Fraser +Frazer +Frederick +Frederikson +Freeburn +Freedman +Freeman +Freestone +Freeth +Freight +French +Fretwell +Frey +Fricker +Friel +Friend +Frith +Froggatt +Froggett +Frost +Frostick +Froy +Frusher +Fryer +Fulker +Fuller +Fulleron +Fullerton +Fulton +Funnell +Furey +Furlong +Furnell +Furness +Furnish +Furniss +Furse +Fyall +Gadsden +Gaffney +Galbraith +Gale +Gales +Gall +Gallacher +Gallagher +Galliford +Gallo +Galloway +Galvin +Gamble +Gammer +Gammon +Gander +Gandham +Ganivet +Garber +Garbett +Garbutt +Garcia +Gardener +Gardiner +Gardner +Garland +Garner +Garrard +Garratt +Garrett +Garside +Garvey +Gascoyne +Gaskell +Gately +Gates +Gaudin +Gaumont +Gauntlett +Gavin +Gaynor +Geaney +Geary +Geeson +Geldard +Geldart +Gell +Gemmell +Gene +George +Gerard +Gerrard +Geyer +Gibb +Gibbins +Gibbon +Gibbons +Gibbs +Giblin +Gibson +Gifford +Gilbert +Gilbey +Gilchrist +Gilder +Giles +Gilfillan +Gilks +Gill +Gillam +Gillan +Gillard +Gillen +Gillespie +Gillett +Gillies +Gilmartin +Gilmore +Gilmour +Ginty +Girdwood +Girling +Given +Gladwell +Glaister +Glasby +Glasgow +Glass +Gleave +Gledhill +Gleeson +Glen +Glencross +Glenn +Glennie +Glennon +Glew +Glossop +Glover +Glynn +Goble +Godby +Goddard +Godden +Godfrey +Godwin +Goff +Gold +Goldberg +Golding +Goldman +Goldsmith +Goldsworthy +Gomez +Gonzalez +Gooch +Good +Goodacre +Goodall +Goodchild +Goode +Gooding +Goodman +Goodridge +Goodson +Goodwin +Goodyear +Gordon +Goring +Gorman +Gosden +Gosling +Gough +Gould +Goulden +Goulding +Gourlay +Govender +Govier +Gower +Gowing +Grady +Graham +Grainger +Grange +Granger +Grant +Graves +Gray +Grayson +Greaves +Green +Greenall +Greenaway +Greene +Greener +Greenhill +Greening +Greenleaf +Greenshields +Greenslade +Greensmith +Greenway +Greenwood +Greer +Gregory +Greig +Grenard +Grennan +Gresham +Grey +Grierson +Griff +Griffin +Griffith +Griffiths +Griggs +Grimes +Grimshaw +Grinham +Grivet +Grogan +Groom +Grose +Grosvenor +Grout +Groves +Grundy +Guest +Guilmard +Guinard +Gulley +Gunby +Gunn +Gunning +Gunston +Gunter +Guthrie +Gutteridge +Guttridge +Hackett +Hadden +Haddock +Hadfield +Hagan +Haggett +Haigh +Haine +Haines +Hale +Halford +Hall +Hallam +Hallett +Halliday +Halliwell +Halstead +Hamer +Hamill +Hamilton +Hammond +Hamnett +Hampson +Hampton +Hancock +Hand +Handley +Hanlon +Hannam +Hansen +Hanson +Harden +Harding +Hardwick +Hardy +Hargreaves +Harker +Harkness +Harley +Harlow +Harman +Harness +Harper +Harries +Harrington +Harris +Harrison +Harrop +Harry +Hart +Hartley +Harvey +Harwood +Haslam +Hassan +Hassani +Hastings +Hatch +Hatton +Hawes +Hawker +Hawkes +Hawkins +Hawkridge +Hawley +Haworth +Hawtin +Hayes +Haynes +Hayward +Head +Healey +Healy +Heath +Heathcote +Heather +Heatley +Heaton +Hedley +Hegney +Helley +Hellier +Helm +Hemingway +Hemmings +Henderson +Hendry +Heneghan +Hennessy +Henry +Hepburn +Hepples +Herbert +Heritage +Heron +Herron +Hetherington +Hewitt +Hewlett +Heywood +Hibbert +Hickey +Hickman +Hicks +Higgins +Higginson +Higgs +Hill +Hills +Hilton +Hind +Hinde +Hindle +Hindley +Hinds +Hine +Hinton +Hirst +Hiscocks +Hitchcock +Hoare +Hobbs +Hobson +Hocking +Hodder +Hodge +Hodges +Hodgkins +Hodgkinson +Hodgson +Hodkinson +Hodson +Hogan +Hogg +Holden +Holder +Holding +Holdsworth +Hole +Holgate +Holl +Holland +Hollis +Holloway +Holman +Holmes +Holt +Homer +Hood +Hook +Hooper +Hooton +Hope +Hopes +Hopkins +Hopkinson +Hopwood +Horn +Horne +Horner +Horrocks +Horton +Hough +Houghton +Hoult +Houlton +Houston +Howard +Howarth +Howden +Howe +Howell +Howells +Howes +Howie +Hoyle +Hubbard +Hudson +Huggins +Hughes +Hull +Hulme +Hume +Humphrey +Humphreys +Humphries +Hunt +Hunter +Hurley +Hurrell +Hurst +Hussain +Hussein +Hussey +Hutchings +Hutchins +Hutchinson +Hutchison +Hutton +Hyde +Ianson +Ibbotson +Ibbs +Ibrahim +Iddon +Iggleden +Iles +Ilett +Illing +Illingworth +Ilsley +Impey +Imran +Ingermann +Ingham +Ingle +Ingleby +Ingledew +Inglefield +Ingles +Inglethorpe +Ingram +Inker +Inman +Innalls +Innes +Inson +Ireland +Ireson +Ironman +Ironmonger +Irvin +Irvine +Irving +Irwin +Isaac +Isaacs +Isbill +Isbitt +Isgate +Isherwod +Isherwood +Islam +Isman +Isnard +Issac +Ivory +Izzard +Jackman +Jacks +Jackson +Jacob +Jacobs +Jacobson +Jacques +Jaffray +Jagger +Jakeman +James +Jameson +Jamieson +Janes +Jansen +Jardine +Jarman +Jarram +Jarratt +Jarrett +Jarrold +Jarvis +Jasper +Jebson +Jeffcock +Jefferies +Jeffers +Jefferson +Jeffery +Jefford +Jeffrey +Jeffreys +Jeffries +Jeffs +Jems +Jenas +Jenkin +Jenkins +Jenkinson +Jenks +Jenkyns +Jenner +Jennings +Jennison +Jennson +Jensen +Jepson +Jermy +Jerome +Jerry +Jervis +Jesson +Jessop +Jevons +Jewell +Jewers +Jewett +Jewitt +Jewkes +Jewson +Jiggens +Jobson +Johannson +Johansen +Johanson +John +Johns +Johnson +Johnston +Johnstone +Jolley +Jolly +Jonas +Jones +Jonhson +Jopson +Jordan +Jordison +Jordon +Joseph +Joss +Jourdan +Jowett +Jowitt +Joyce +Joynson +Jubb +Judd +Judge +Jukes +Jupp +Jury +Kacy +Kaddour +Kamara +Kampfner +Kane +Kanes +Kapoor +Karim +Karne +Karras +Kassell +Kaufman +Kaul +Kaur +Kavanagh +Kay +Kaye +Kayes +Keable +Keal +Kealey +Keane +Kearney +Kearns +Kearsley +Kearton +Keating +Keaveney +Keay +Keeble +Keefe +Keegan +Keelan +Keeler +Keeley +Keeling +Keenan +Keene +Keetley +Keffler +Kehoe +Keighley +Keight +Keilty +Keir +Keith +Kelk +Kell +Kelland +Kellems +Kellie +Kelliher +Kelly +Kelsall +Kelsey +Kelso +Kemp +Kempson +Kempster +Kendall +Kendell +Kendrick +Kenley +Kennard +Kennedy +Kenneford +Kennell +Kenneth +Kennett +Kenney +Kenning +Kenny +Kenrick +Kensington +Kent +Kentwood +Kenward +Kenworthy +Kenyon +Keogh +Kerby +Kernick +Kerr +Kerrell +Kerridge +Kerrigan +Kerrighen +Kerrison +Kershaw +Ketley +Kett +Kettell +Ketteringham +Kettlewell +Keward +Kewley +Keys +Keyte +Keywood +Khalid +Khalifa +Khalil +Khan +Kibblewhite +Kidd +Kiddle +Kidman +Kidner +Kiely +Kiernan +Kilb +Kilbee +Kilbey +Kilbride +Kilburn +Kilford +Kill +Killeen +Killen +Killick +Killock +Kilminster +Kilmurry +Kilnan +Kilner +Kilroy +Kilshaw +Kimber +Kimble +Kinch +Kinchin +Kinder +King +Kingdon +Kinghorn +Kingman +Kings +Kingscott +Kingsley +Kingston +Kinnaird +Kinnear +Kinnersley +Kinniburgh +Kinnison +Kinrade +Kinsella +Kinsey +Kinsley +Kipling +Kirby +Kirk +Kirkbride +Kirkbright +Kirkby +Kirkland +Kirkman +Kirkpatrick +Kirkwood +Kirtley +Kirwan +Kirwin +Kitchen +Kitchin +Kitching +Kitson +Kitt +Klam +Klein +Knab +Knappett +Knibb +Knigge +Knight +Knightley +Knighton +Knights +Knott +Knowler +Knowles +Knox +Knoxville +Knuckles +Knutt +Koban +Kolt +Kone +Kore +Kouma +Kram +Kreyling +Kristensen +Kromberg +Kruger +Kumar +Kurian +Kurray +Kydd +Kyle +Kysel +Labbe +Lacey +Lacy +Laing +Laird +Lake +Lakey +Lakin +Lamb +Lambert +Lambton +Lame +Lamond +Lancaster +Lander +Lane +Lang +Langdon +Lange +Langford +Langley +Langridge +Langston +Langton +Lanham +Laraway +Large +Larkin +Larkings +Larsen +Larsson +Last +Latham +Lathan +Lathey +Lattimore +Laurie +Laver +Laverick +Lavery +Lawal +Lawler +Lawlor +Lawn +Lawrance +Lawrence +Lawrie +Laws +Lawson +Lawther +Lawton +Laycock +Layton +Le tissier +Leach +Leadley +Leahy +Leake +Leal +Leary +Leaver +Leck +Leckie +Ledger +Lee +Leech +Leedham +Leek +Leeming +Lees +Leese +Leeson +Legg +Legge +Leggett +Leigh +Leighton +Leitch +Leith +Lendon +Lenihan +Lennard +Lennon +Lennox +Leonard +Leroy +Leslie +Lester +Lethbridge +Levann +Levett +Levin +Levine +Levy +Lewin +Lewington +Lewins +Lewis +Lewry +Leyland +Leys +Leyshon +Liddell +Liddle +Lightfoot +Lilley +Lilly +Lilwall +Lincoln +Lind +Linden +Lindo +Lindop +Lindsay +Line +Lines +Linford +Ling +Linley +Linsby +Linton +Lister +Litchfield +Little +Littlewood +Livermore +Livingstone +Llewellyn +Lloyd +Loat +Lobb +Lock +Locke +Lockett +Lockhart +Lockie +Lockwood +Lockyer +Lodge +Loft +Lofthouse +Loftus +Logan +Lohan +Lois +Lomas +Lomax +London +Long +Longhurst +Longley +Longworth +Lonsdale +Lopes +Lopez +Lord +Loudon +Loughran +Louth +Lovatt +Love +Lovegrove +Lovell +Lovelock +Lovett +Lovey +Lowbridge +Lowdon +Lowe +Lowes +Lowis +Lowndes +Lowrie +Lowry +Lucas +Luce +Lucey +Luckhurst +Ludgrove +Ludkin +Ludlow +Luke +Luker +Lumb +Lumley +Lumsden +Lunn +Lunt +Luscombe +Luttrell +Luxton +Lyall +Lyes +Lyme +Lynas +Lynch +Lynes +Lynn +Lyon +Lyons +Mac +Macarthur +Macaulay +Macdonald +Mace +Macfarlane +Macgregor +Machin +Macintyre +Mack +Mackay +Mackenzie +Mackie +Maclean +Macleod +Macmillan +Macpherson +Macrae +Madden +Maddocks +Magee +Maguire +Maher +Mahoney +Main +Mair +Major +Makin +Malley +Mallinson +Malone +Maloney +Mangnall +Mann +Manning +Mansell +Mansfield +Manson +Markham +Marks +Marlow +Marr +Marriott +Marsden +Marsh +Marshall +Martin +Martinez +Martins +Mason +Masters +Mather +Mathers +Matheson +Mathews +Matthams +Matthews +Maughan +Mawson +Maxwell +May +Maynard +Mcarthur +Mcauley +Mcavoy +Mcbain +Mccabe +Mccaffrey +Mccall +Mccallum +Mccann +Mccarthy +Mccartney +Mccluskey +Mcclymont +Mcconnell +Mccormack +Mccormick +Mccourt +Mcculloch +Mccullough +Mcdermott +Mcdonagh +Mcdonald +Mcdonnell +Mcdougall +Mcelroy +Mcewan +Mcfadden +Mcfarlane +Mcgee +Mcghee +Mcgill +Mcginty +Mcgowan +Mcgrady +Mcgrath +Mcgregor +Mcgrory +Mcguinness +Mcguire +Mcintosh +Mcintyre +Mckay +Mckee +Mckenna +Mckenzie +Mckeown +Mckie +Mclaren +Mclaughlin +Mclean +Mclellan +Mcleod +Mcloughlin +Mcmahon +Mcmanus +Mcmillan +Mcnally +Mcnamara +Mcnaught +Mcneil +Mcneill +Mcnulty +Mcphail +Mcphee +Mcpherson +Mcrae +Mcshane +Mctaggart +Meadows +Meakin +Mears +Melia +Mellor +Meredith +Merritt +Metcalf +Metcalfe +Michael +Michel +Middleton +Miles +Milford +Mill +Millar +Millard +Miller +Millett +Milligan +Millington +Mills +Millward +Milne +Milner +Milward +Mistry +Mitchell +Moffat +Mohamed +Mohammed +Molloy +Molyneux +Monaghan +Montague +Montgomery +Moody +Moon +Mooney +Moore +Moorhouse +Moran +More +Moreno +Moreton +Morgan +Moriarty +Morley +Moroney +Morris +Morrison +Morrow +Mortimer +Morton +Moseley +Moss +Mottram +Mould +Muir +Mullen +Mulligan +Mullins +Mundy +Munro +Murphy +Murray +Murrell +Mustafa +Myatt +Myers +Nair +Nairn +Nandi +Nanson +Nanton +Napier +Napper +Nartey +Nash +Nason +Naughton +Naumann +Nayler +Naylor +Naysmith +Neal +Neale +Neary +Neave +Neaverson +Nedd +Needham +Neeson +Negros +Neighbour +Neill +Neilsen +Neilson +Neish +Nelmes +Nelms +Nelson +Nemeth +Nero +Nesbitt +Ness +Nessbert +Nettleton +Neville +Nevins +Nevis +Newall +Newberry +Newbold +Newbury +Newby +Newcombe +Newell +Newey +Newham +Newill +Newington +Newland +Newlands +Newman +Newsham +Newsome +Newson +Newstead +Newton +Neyland +Nichol +Nicholas +Nicholl +Nicholls +Nichols +Nicholson +Nickel +Nickolls +Nicks +Nicol +Nicolas +Nicoll +Nicolson +Nield +Nielsen +Nielson +Nightingale +Niles +Nilsen +Nineham +Nisbet +Nixon +Noach +Noakes +Nobbs +Noble +Noggins +Nokes +Nolan +Nood +Noon +Noonan +Norbert +Norburn +Norbury +Norcross +Nord +Norgate +Norgrove +Norm +Norman +Normington +Norris +Norsworthy +North +Northcott +Norton +Norville +Norwood +Notman +Nott +Nourse +Nova +Nowak +Nowell +Noyce +Noyes +Nugent +Number +Nunn +Nurse +Nurton +Nutella +Nutman +Nutt +Nuttall +Oakes +Oakey +Oakley +Oaks +Oakton +Oates +Oatridge +Oatway +Obrien +Ocallaghan +Oconnell +Oconnor +Odam +Oddie +Oddy +Odea +Odell +Odling +Odonnell +Odonoghue +Odriscoll +Oflynn +Ogden +Ogilvie +Ogilvy +Ogrady +Ohalloran +Ohara +Okeefe +Okey +Okten +Olan +Oldfield +Oldham +Olding +Oldland +Oldroyd +Olds +Oleary +Oliver +Olivier +Ollerhead +Olley +Oloughlin +Olsen +Olson +Omalley +Oman +Oneil +Oneill +Opayne +Openshaw +Oram +Orbell +Orchard +Oreilly +Oriley +Orman +Orme +Ormiston +Ormond +Ormsby +Ormston +Orrell +Orritt +Orton +Orvis +Orwin +Osborn +Osborne +Osman +Osmond +Ostcliffe +Ostler +Osullivan +Oswald +Otoole +Otten +Otter +Ottey +Ottley +Otton +Ould +Oulton +Overall +Overett +Overfield +Overing +Overson +Overton +Owen +Owens +Owings +Oxby +Oxenham +Oxley +Oxtoby +Pack +Packard +Packer +Pagan +Page +Paige +Pailing +Paine +Painter +Paisley +Palfrey +Palfreyman +Palin +Pallett +Palmer +Panesar +Pankhurst +Pannell +Parish +Park +Parker +Parkes +Parkin +Parkins +Parkinson +Parks +Parmar +Parnaby +Parnell +Parr +Parratt +Parrott +Parry +Parsons +Partington +Partlett +Partridge +Pascoe +Pasfield +Paskell +Passmore +Patchett +Patel +Pateman +Paterson +Paton +Patrick +Patten +Patterson +Pattinson +Pattison +Patton +Paul +Pavot +Pawson +Payne +Peace +Peach +Peacock +Peake +Peal +Peaper +Pearce +Pears +Pearson +Peat +Peck +Pedley +Peebles +Peel +Peers +Pegg +Peigne +Pell +Pelling +Pemberton +Pender +Pendlebury +Pendleton +Penfold +Penn +Pennell +Penney +Pennington +Percival +Pereira +Perez +Perkin +Perkins +Perks +Perowne +Perrett +Perrin +Perrins +Perry +Peters +Petersen +Peterson +Petrova +Pett +Petticrew +Peyton +Phelan +Phelps +Philip +Philips +Phillips +Philpott +Phipps +Phoenix +Pick +Pickard +Pickering +Pickersgill +Pickett +Pickford +Pickthall +Picot +Pierce +Piercey +Pierre +Pigott +Pike +Pilkington +Pillay +Pinder +Pine +Pinkney +Pinner +Pinnock +Pinsmail +Pipe +Piper +Pitcher +Pitchford +Pitt +Pitts +Plant +Plastow +Platt +Platts +Pledger +Plouvin +Plumb +Plummer +Pocock +Pointer +Pole +Pollard +Pollock +Polson +Pomeroy +Pomphrey +Pond +Pooke +Poole +Poon +Pope +Porter +Potter +Potts +Poulter +Poulton +Pounder +Povey +Powell +Power +Powers +Powis +Powles +Poyser +Pratt +Preece +Prendergast +Prentice +Prescott +Preston +Prevost +Price +Prime +Prince +Pringle +Prior +Pritchard +Privett +Probert +Procter +Proctor +Prosser +Provan +Pryor +Pugh +Pullen +Purcell +Purkis +Purnell +Purse +Purvis +Putt +Pyle +Quigley +Quinlivan +Quinn +Quinnell +Quinton +Quirk +Quirke +Rackham +Radcliffe +Radford +Radley +Raeburn +Rafferty +Rahman +Raine +Rainey +Rainford +Ralph +Ralston +Ramm +Rampling +Ramsay +Ramsden +Ramsey +Rand +Randall +Randle +Ranger +Rankin +Ranks +Rann +Ransom +Ranson +Rapson +Rashid +Ratcliffe +Raval +Raven +Ravenscroft +Rawlings +Rawlinson +Rawsthorne +Raymond +Rayner +Read +Reade +Reader +Reading +Readle +Readman +Reardon +Reasbeck +Reay +Redden +Redding +Reddy +Redfern +Redhead +Redin +Redman +Redmond +Redwood +Reed +Rees +Reese +Reeve +Reeves +Regan +Regent +Rehman +Reid +Reilly +Reisser +Render +Renna +Rennalls +Rennie +Renshaw +Renwick +Reveley +Reyes +Reygan +Reynolds +Rhoades +Rhodes +Rhys +Ricci +Rice +Rich +Richards +Richardson +Riches +Richman +Richmond +Richter +Rick +Rickard +Rickards +Rickett +Ricketts +Riddell +Riddle +Riddler +Ridge +Ridgway +Ridgwell +Ridle +Ridley +Rigby +Rigg +Rigley +Riley +Ring +Ripley +Rippin +Riseborough +Ritchie +Rivers +Rixon +Roach +Robb +Robbins +Robe +Robert +Roberts +Robertson +Robin +Robins +Robinson +Robishaw +Robotham +Robson +Roche +Rochford +Rockliffe +Rodden +Roden +Rodger +Rodgers +Rodham +Rodrigues +Rodriguez +Rodwell +Roebuck +Roff +Roffey +Rogan +Rogers +Rogerson +Roles +Rolfe +Rollinson +Roman +Romans +Ronald +Ronflard +Rook +Rooke +Roome +Rooney +Rootham +Roper +Ropple +Roscoe +Rose +Rosenblatt +Rosenbloom +Ross +Rosser +Rossi +Rosso +Roth +Rothery +Rothwell +Rouse +Roussel +Rousset +Routledge +Rowan +Rowe +Rowland +Rowlands +Rowley +Rowlinson +Rowson +Royall +Royle +Rudd +Ruff +Rugg +Rumbold +Rumsey +Ruscoe +Rush +Rushbrooke +Rushby +Rushton +Russel +Russell +Russon +Rust +Rutherford +Rutter +Ryan +Ryans +Rycroft +Ryder +Sadiq +Sadler +Said +Saleh +Salisbury +Sallis +Salmon +Salt +Salter +Sampson +Samuel +Samuels +Sanchez +Sanders +Sanderson +Sandison +Sands +Santos +Sargent +Saunders +Savage +Saville +Sawyer +Saxton +Sayers +Schmid +Schmidt +Schofield +Scott +Searle +Seddon +Seer +Selby +Sellars +Sellers +Senior +Sewell +Sexton +Seymour +Shackleton +Shah +Shakespeare +Shand +Shanks +Shannon +Sharkey +Sharma +Sharp +Sharpe +Sharples +Shaughnessy +Shaw +Shea +Shearer +Sheehan +Sheldon +Shelton +Shepherd +Sheppard +Sheridan +Sherman +Sherriff +Sherry +Sherwood +Shields +Shipley +Short +Shotton +Showell +Shuttleworth +Silcock +Silva +Simmonds +Simmons +Simms +Simon +Simons +Simpson +Sims +Sinclair +Singh +Singleton +Sinha +Sisson +Sissons +Skelly +Skelton +Skinner +Skipper +Slade +Slater +Slattery +Sloan +Slocombe +Small +Smallwood +Smart +Smit +Smith +Smithson +Smullen +Smyth +Smythe +Sneddon +Snell +Snelling +Snow +Snowden +Snowdon +Somerville +South +Southern +Southgate +Southwick +Sparkes +Sparrow +Spears +Speed +Speight +Spence +Spencer +Spicer +Spiller +Spinks +Spooner +Squire +Squires +Stacey +Stack +Staff +Stafford +Stainton +Stamp +Stanfield +Stanford +Stanley +Stannard +Stanton +Stark +Steadman +Stedman +Steel +Steele +Steer +Steere +Stenhouse +Stephen +Stephens +Stephenson +Sterling +Stevens +Stevenson +Steward +Stewart +Stock +Stocker +Stockley +Stoddart +Stokes +Stokoe +Stone +Stoppard +Storer +Storey +Storr +Stott +Stout +Strachan +Strange +Street +Stretton +Strickland +Stringer +Strong +Stroud +Stuart +Stubbs +Stuckey +Sturgess +Sturrock +Styles +Sugden +Sullivan +Summers +Sumner +Sunderland +Sutherland +Sutton +Swain +Swales +Swan +Swann +Swanson +Sweeney +Sweeting +Swift +Sykes +Sylvester +Symes +Symonds +Taggart +Tailor +Tait +Talbot +Tallett +Tamber +Tang +Tanner +Tansey +Tansley +Tappin +Tapping +Tapscott +Tarr +Tarrant +Tasker +Tate +Tatlock +Tatlow +Tatnell +Taurel +Tayler +Taylor +Teague +Teal +Teale +Teasdale +Tedd +Telford +Tell +Tellis +Tempest +Templar +Temple +Templeman +Templeton +Tennant +Terry +Thackeray +Thackray +Thake +Thatcher +Thelwell +Thirlwall +Thirlway +Thirlwell +Thistlethwaite +Thom +Thomas +Thomason +Thompson +Thoms +Thomson +Thonon +Thorley +Thorndyke +Thorne +Thornes +Thornhill +Thornley +Thornton +Thorp +Thorpe +Thurbon +Thurgood +Thurling +Thurlow +Thurman +Thurston +Tickner +Tidmarsh +Tierney +Till +Tillett +Tilley +Tilson +Tilston +Timberlake +Timmins +Timms +Timney +Timson +Tindall +Tindell +Tinker +Tinkler +Tinsley +Tipping +Tippins +Tips +Tisdall +Titmarsh +Titmus +Titmuss +Titterington +Toal +Tobin +Tocher +Todd +Tohill +Toland +Tolley +Tollis +Tolmay +Tomas +Tombs +Tomes +Tomkins +Tomlin +Tomlinson +Tompkin +Tompkins +Toms +Tong +Tonge +Tonks +Tonner +Toomer +Toomey +Topham +Topley +Topliss +Topp +Torney +Torrance +Torrens +Torres +Tosh +Totten +Toucet +Tovar +Tovey +Towell +Towers +Towle +Townend +Towns +Townsend +Townsley +Tozer +Trafford +Train +Trainor +Trattles +Travers +Travill +Travis +Traynor +Treble +Trennery +Trent +Treseder +Trevor +Trew +Trickett +Trigg +Trimble +Trinder +Trollope +Troon +Trotman +Trott +Trueman +Truman +Trump +Truscott +Tuck +Tucker +Tuckey +Tudor +Tuffnell +Tufnall +Tugwell +Tully +Tunks +Tunstall +Turford +Turke +Turkington +Turland +Turnbull +Turner +Turney +Turnham +Turnock +Turrell +Turton +Turvey +Tuthill +Tuttle +Tutton +Tweddle +Twigg +Twiggs +Twine +Tyler +Tyman +Tyne +Tyrer +Tyrrell +Uddin +Ullman +Ullmann +Ulyatt +Umney +Underdown +Underhill +Underwood +Unsworth +Unwin +Upfield +Upjohn +Upsdell +Upson +Upton +Urwin +Utley +Utterson +Uttley +Utton +Uttridge +Vale +Valentine +Vallance +Vallins +Vallory +Valmary +Vancoller +Vane +Vann +Vanstone +Vanwell +Vardy +Varey +Varley +Varndell +Vass +Vaughan +Vaughn +Veale +Veasey +Veevers +Veitch +Velds +Venables +Ventura +Verdon +Verell +Verney +Vernon +Vicary +Vicens +Vickars +Vickerman +Vickers +Vickery +Victor +Vikers +Villiger +Villis +Vince +Vincent +Vine +Viner +Vines +Viney +Vinicombe +Vinny +Vinton +Virgo +Voakes +Vockins +Vodden +Vollans +Voyse +Vyner +Wade +Wadham +Waghorn +Wagstaff +Wain +Wainwright +Waite +Wakefield +Wakeford +Wakeham +Wakelin +Waldron +Wale +Wales +Walkden +Walker +Wall +Wallace +Waller +Walling +Wallis +Walls +Walmsley +Walpole +Walsh +Walshe +Walter +Walters +Walton +Wane +Wang +Warburton +Warby +Ward +Warden +Wardle +Ware +Wareing +Waring +Warn +Warner +Warren +Warriner +Warrington +Warwick +Water +Waterfield +Waterhouse +Wateridge +Waterman +Waters +Waterson +Watkins +Watkinson +Watling +Watson +Watt +Watters +Watts +Waugh +Wears +Weasley +Weaver +Webb +Webber +Webster +Weeks +Weir +Welch +Weldon +Weller +Wellington +Wellman +Wells +Welsh +Welton +Were +Werner +Werrett +West +Western +Westgate +Westlake +Weston +Westwell +Westwood +Whalley +Wharton +Wheatcroft +Wheatley +Wheeldon +Wheeler +Whelan +Whitaker +Whitby +White +Whiteford +Whitehead +Whitehouse +Whitelaw +Whiteley +Whitfield +Whitham +Whiting +Whitley +Whitlock +Whitmore +Whittaker +Whittingham +Whittington +Whittle +Whittley +Whitworth +Whyte +Wickens +Wickham +Wicks +Widdows +Widdowson +Wiggins +Wigley +Wilcox +Wild +Wilde +Wildman +Wileman +Wiles +Wilkes +Wilkie +Wilkin +Wilkins +Wilkinson +Wilks +Wilkshire +Will +Willett +Willetts +Williams +Williamson +Willis +Wills +Willson +Wilmot +Wilson +Wilton +Wiltshire +Winder +Windsor +Winfer +Winfield +Winman +Winn +Winship +Winstanley +Winter +Wintersgill +Winward +Wise +Wiseman +Wither +Withers +Wolf +Wolfe +Wolstencroft +Wong +Wood +Woodcock +Woodford +Woodhall +Woodham +Woodhams +Woodhead +Woodhouse +Woodland +Woodley +Woods +Woodward +Wooldridge +Woollard +Woolley +Woolnough +Wootton +Worgan +Wormald +Worrall +Worsnop +Worth +Worthington +Wotherspoon +Wragg +Wraight +Wray +ren +Wrench +Wrenn +Wrigglesworth +Wright +Wrightson +Wyatt +Wyer +Yabsley +Yallop +Yang +Yapp +Yard +Yardley +Yarker +Yarlett +Yarnall +Yarnold +Yarwood +Yasmin +Yates +Yeadon +Yeardley +Yeardsley +Yeates +Yeatman +Yeldon +Yeoman +Yeomans +Yetman +Yeung +Yoman +Yomkins +York +Yorke +Yorston +Youlden +Young +Younge +Younis +Youssouf +Yule +Yusuf +Zaoui diff --git a/src/neuralnetwork/generate_alphabets.py b/src/neuralnetwork/generate_alphabets.py new file mode 100644 index 0000000..0b1e18e --- /dev/null +++ b/src/neuralnetwork/generate_alphabets.py @@ -0,0 +1,44 @@ +import training +import os +import sys + +if __name__ == "__main__": + + # List all the directories containing country datasets to populate the countries dictionary + countries = training.get_countries() + + for c, country in countries.items(): + print(f"processing {c}...", end="") + sys.stdout.flush() + + letters = {} + + # get all the names in a country's dataset + all_names = country.get_all() + + # iterate through all letters in the all of the names + for name in all_names: + + # preprocess the name + name = country.preprocess(name) + + for letter in name: + if letter in letters: + letters[letter] += 1 + else: + letters[letter] = 1 + + print(f" found {len(letters)} in {len(all_names)} names... ", end="") + sys.stdout.flush() + + # sort the letters by occurrence + letters_sorted = [l for l in letters] + letters_sorted.sort() + # output sorted letters to a file + with open(os.path.join(country.path, "alphabet.txt"), "w") as file: + for letter in letters_sorted: + file.write(letter) + file.write("\n") + + print("saved!") + sys.stdout.flush() diff --git a/src/neuralnetwork/rnn.py b/src/neuralnetwork/rnn.py new file mode 100644 index 0000000..0662394 --- /dev/null +++ b/src/neuralnetwork/rnn.py @@ -0,0 +1,329 @@ +import random +import time +import math +import torch +import torch.nn as nn + +import warnings +import sys + +import copy + +from util import AtomicNumber + +PRINT_INFORMATION_SECONDS = 2 +num_processes = 12 + +#ignore warnings +warnings.filterwarnings('ignore') + + +if "--disable-cuda" in sys.argv: + cuda = False +else: + cuda = torch.cuda.is_available() + +print(f"CUDA is {'enabled' if cuda else 'disabled'}") +if cuda: + print("CUDA devices:") + for device_index in range(torch.cuda.device_count()): + print(f"{device_index}|\t{torch.cuda.get_device_name(device_index)}") + +device = torch.device("cuda") if cuda else torch.device("cpu") + +class RNN(nn.Module): + def __init__(self, input_size, hidden_size, output_size): + super(RNN, self).__init__() + self.hidden_size = hidden_size + self.output_size = output_size + + # create the input, hidden and output linear transformation branches + self.input_to_hidden = nn.Linear(input_size + hidden_size, hidden_size, device=device) + self.input_to_output = nn.Linear(input_size + hidden_size, output_size, device=device) + self.output_to_output = nn.Linear(hidden_size + output_size, output_size, device=device) + + # initialise a dropout function to be used on output data + self.dropout = nn.Dropout(0.1) + + # initialise the softmax function to be used on output data + self.softmax = nn.LogSoftmax(dim=1) + + # do not introduce any randomness by default + self.random_factor = 0 + + + def forward(self, inputs, hidden): + # combine the input layer with the hidden layer to create the output layer and new hidden layer + input_combined = torch.cat((inputs, hidden), 1) + hidden = self.input_to_hidden(input_combined) + output = self.input_to_output(input_combined) + output_combined = torch.cat((hidden, output), 1) + + output = self.output_to_output(output_combined) + # apply the functions to the output data + output = self.dropout(output) + output = self.softmax(output) + + # add noise to the output, based on self.random_factor + if self.random_factor > 0: + # create a fully random tensor + random_tensor = torch.randn(self.output_size) + output = torch.add(output, random_tensor, alpha=self.random_factor) + + return output, hidden + + def initHidden(self): + # The hidden layer should be tensor with the length that we've specified + return torch.zeros(1, self.hidden_size, device=device) + +# instantiate the function to use to calculate loss +# we will use Mean Squared Error between the +criterion = nn.NLLLoss() + +# define the learning rate, to begin with, we can use 0.0005 +learning_rate = 0.0005 + +"""Train a neural network on a single input name + Args: + rnn: (RNN) the rnn to train + input_tensors: (tensor) The input tensor: a one-hot-encoding from the first letter to the last letter, excluding the end of string marker + output_tensors: (tensor) The input tensor: a one-hot-encoding from the second letter to the end of the input data + Returns: + output: (tensor) the output of the training + loss: (float) the loss of the training +""" +def train_rnn(rnn, input_tensor, target_tensor): + # unsqueeze the target tensor, + target_tensor.unsqueeze_(-1) + + # reset the parameters of the neural network + hidden = rnn.initHidden() + rnn.zero_grad() + + # initiate an float called loss, this will store the error between each iteration output and its target + loss = 0 + for i in range(input_tensor.size(0)): + output, hidden = rnn(input_tensor[i], hidden) + + # calculate the error and add it to the overall loss + l = criterion(output, target_tensor[i]) + loss += l + + loss.backward() + + # adjust the parameters of the rnn accordingly + for p in rnn.parameters(): + p.data.add_(-learning_rate, p.grad.data) + + return output, loss.item() / input_tensor.size(0) + +"""Create the input tensor for a name, a one hot matrix from the first letter to last letter (excluding EOS) + Args: + name: (str[]) an array of the letters in the name, can also be supplied as a string literal + alphabet: (str[]) The alphabet to use while encoding the name, an array starting with a "NULL" character and ending in an "EOS" character + value: (float) (default=1) The value to use for the "1" representing the letter + Returns: + tensor: (tensor) the input tensor for the given name +""" +def input_tensor(name, alphabet, value=1): + tensor = torch.zeros(len(name), 1, len(alphabet), device=device) + + #iterate through each letter in the name + for li in range(len(name)): + letter = name[li] + # If the letter isn't in the alphabet, use the first "NULL" character + index = alphabet.index(letter) if letter in alphabet else 0 + + tensor[li][0][index] = value + + return tensor + +"""Create the target tensor for a name, a long tensor from the second letter to the EOS + Args: + name: (str[]) an array of the letters in the name, can also be supplied as a string literal + alphabet: (str[]) The alphabet to use while encoding the name, an array starting with a "NULL" character and ending in an "EOS" character + Returns: + tensor: (tensor) the input tensor for the given name +""" +def target_tensor(name, alphabet): + indexes = [] + for li in range(1, len(name)): + letter = name[li] + index = alphabet.index(letter) if letter in alphabet else 0 + indexes.append(index) + + # and add the end of string character + indexes.append(len(alphabet) - 1) + + #legacy tensor needs to be made this way + if cuda: + return torch.cuda.LongTensor(indexes) + else: + return torch.LongTensor(indexes) + + +"""Train a neural network on a list of names with a given alphabet + Args: + rnn (RNN): the neural network to train on + names: (str[]) the list of names to train on + alphabet: (str[]) the alphabet to use to encode characters + iterations: (int) (default=10000) The number of iterations of training that should be done +""" +def learn_names(rnn, names, alphabet, iterations=100000, num_processes=12): + + # keep track of total time spent training by knowing when we started training + start = time.time() + + # define the number of iterations per process + iters_per_process = int(iterations/num_processes) + + processes = [] + + # keep track of the total loss + total_loss = AtomicNumber() + + # keep track of total number of completed iterations + completed_iterations = AtomicNumber() + + # keep track of the last time that the information was printed + # this way we can print every x seconds + last_print = AtomicNumber() + + print(f"Training on {len(names)} names...") + + # spawn processes, each running the _train function + torch.multiprocessing.spawn(_train, args=(rnn, names, alphabet, iters_per_process, + total_loss, completed_iterations, last_print, start, iterations), + nprocs=num_processes, + join=True) + print() + +"""Thread function to use when multiprocessing learn_names + +""" +def _train(rank, rnn, names, alphabet, iterations, + total_loss, completed_iterations, last_print, + start, total_iterations): + for i in range(1, iterations+1): + try: + # choose a random name to train on + name = random.choice(names) + + # create the input and trainint tensors + input_name_tensor = input_tensor(name, alphabet) + target_name_tensor = target_tensor(name, alphabet) + + # train the rnn on the input and target tensors + output, loss = train_rnn(rnn, input_name_tensor, target_name_tensor) + total_loss.increment(loss) + + # increment number of completed iterations + completed_iterations.increment() + + # to prevent overloading the console, potentially slowing down the training process, + # only print information every PRINT_INFORMATION_SECONDS + if time.time() - last_print.get() > PRINT_INFORMATION_SECONDS: + # set last print to now to prevent other threads from also printing + last_print.set(time.time()) + + # calculate and display information + seconds_elapsed = time.time() - start + time_elapsed = "%dm %ds" % (math.floor(seconds_elapsed / 60), seconds_elapsed % 60) + + percentage = completed_iterations.get() / total_iterations * 100 + + # print information on the same line as before + print("\r%s (%d %d%%) %.4f" % (time_elapsed, completed_iterations.get(), percentage, loss), end="") + except: + pass + + +"""Sample a random name from the network using a starting letter + Args: + rnn: (RNN) the neural network to sample from + alphabet: (str[]) the alphabet to use to decode the outputs from the network + start_letter: (str) the letter to use to start the neural network + max_length: (int) (default=50) the maximum length for a name + Returns: + output_name: (str) the characters that the rnn has generated from the starting letter +""" +def sample(rnn, alphabet, start_letter, max_length=50): + # disable gradient calculation + #with torch.no_grad(): + # create the input tensor from the start letter, using a randomized value + #random_value = random.random() + random_value = 1 + sample_input = input_tensor(start_letter, alphabet, value=random_value) + + rnn.dropout(sample_input) + + # reset hidden layer + hidden = rnn.initHidden() + + output_name = [start_letter] + + # use a max length to prevent names from being too long + for i in range(max_length): + # call the rnn for the next letter + output, hidden = rnn(sample_input[0], hidden) + + top_v, top_i = output.topk(1) + top_i = top_i[0][0] + + if top_i == len(alphabet)-1: # EOS has been reached + break; + else: + # append next letter to output + + letter = alphabet[top_i] + output_name.append(letter) + + sample_input = input_tensor(letter, alphabet) + + return output_name + + +import warnings +# testing +if __name__ == "__main__": + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + + english_alphabet = [c for c in " abcdefghijklmnopqrstuvwxyz"] + english_alphabet.append("") # add the EOS character + + + option = input("(t)rain or (s)ample?") + if option == "t": + + names = [] + with open("data/datasets/usa/surname.txt", "r") as datafile: + # convert all names to lowercase and remove newline character + names = [name[:-1].lower() for name in datafile.readlines()] + + # create the neural network with a hidden layer of size 128 + rnn = RNN(len(english_alphabet), 128, len(english_alphabet)) + + # transfer to cuda if cuda is enabled + if cuda: + rnn.cuda() + + def provide_name(): + return random.choice(names) + + learn_names(rnn, names, english_alphabet, iterations=100000, num_processes=12) + print() + + + torch.save(rnn, "data/english_names.pt") + elif option == "s": + rnn = torch.load("data/english_names.pt") + if cuda: + rnn.cuda() + rnn.eval() + rnn.random_factor = 0.7 + + for start_letter in [i for i in "abcdefghijklmnopqrstuvwxyz"]: + print(sample(rnn, english_alphabet, start_letter)) + else: + print("invalid option!") diff --git a/src/neuralnetwork/training.py b/src/neuralnetwork/training.py new file mode 100644 index 0000000..85c6dbd --- /dev/null +++ b/src/neuralnetwork/training.py @@ -0,0 +1,373 @@ +import os +import types +import json +import random + +from util import * +from rnn import * + +cuda = False +num_processes = 12 + + +class Country: + def __init__(self, path): + self.path = path + self.datasets = { + "female": os.path.join(path, "female.txt"), + "male": os.path.join(path, "male.txt"), + "surname": os.path.join(path, "surname.txt"), + } + + # initialise the pre and post proccess function lists + self.pre_process = [] + self.post_process = [] + + # load the data file + self.load_data() + + # load the alphabet file + self.alphabet = self.load_alphabet() + + # initialise the rnn models + hidden_size = 128 + self.rnn = {} + + for dataset in self.datasets: + self.rnn[dataset] = RNN( + len(self.alphabet), hidden_size, len(self.alphabet)) + + """ Load the alphabet from the alphabet file + Returns: + alphabet: (str[]) the list of the letters/characters to use while training + """ + + def load_alphabet(self): + alphabet_path = os.path.join(self.path, "alphabet.txt") + + # check if the alphabet file exists, if not, raise an exception + if os.path.exists(alphabet_path): + with open(alphabet_path, "r") as alphabet_file: + # Split the file by lines: on letter/character should be on each line + letters = alphabet_file.read().split("\n") + return letters + else: + raise Exception( + f"The alphabet file {alphabet_path} could not be found") + return [] + + """ load the data from the data file + """ + + def load_data(self): + data_path = os.path.join(self.path, "data.json") + if os.path.exists(data_path): + with open(data_path, "r") as data_file: + j = json.loads(data_file.read()) + + # match the imported global function with the ones listed in the json file + for pre in j["pre"]: + if pre in globals(): + func = globals()[pre] + + # check if the requested object is a function + if type(func) is types.FunctionType: + self.pre_process.append(func) + else: + raise Exception( + f"The function '{pre}' is not a function") + else: + # If the function was not loaded, throw an exception + raise Exception( + f"The function '{pre}' was not loaded or does not exist") + + for post in j["post"]: + if post in globals(): + func = globals()[post] + + # check if the requested object is a function + if type(func) is types.FunctionType: + self.post_process.append(func) + else: + raise Exception( + f"The function '{post}' is not a function") + else: + # If the function was not loaded, throw an exception + raise Exception( + f"The function '{post}' was not loaded or does not exist") + + else: + # load the default pre and post processing functions + self.pre_process = [uncapitalise] + self.post_process = [deserialise, capitalise] + + """ List all the names from a given category file + Args: + category: (str) the category to select names from + Returns: + data: (str[]) an array containing all of the names from the given category file + """ + + def get_names(self, category): + with open(self.datasets[category], "r") as datafile: + return [name for name in datafile.read().split("\n")] + + """ List all names in all categories + Returns: + data: (str[]) an array with all of the names in this country's datasets + """ + + def get_all(self): + return [name for k in self.datasets for name in self.get_names(k)] + + """ Pre-process a name for training + Args: + name: the name loaded from the dataset + Returns: + name: the name after being processed + """ + + def postprocess(self, name): + for f in self.post_process: + name = f(name) + return name + + """ Post-process a name after sampling + Args: + name: the name output from the recurrent neural network + Returns: + name: the name after being processed + """ + + def preprocess(self, name): + for f in self.pre_process: + name = f(name) + return name + + """ Train a neural network on the given dataset + Args: + category: (str) the category to sample training names from + """ + + def train(self, category): + # select the RNN model to be training on + rnn = self.rnn[category] + + # load names from that dataset and pre proccess them + print("preprocessing names...") + names = [self.preprocess(name) for name in self.get_names(category)] + print(f"processed {len(names)} names!") + + # calculate optimum number of iterations (using 80% of whole dataset) + iters = int(len(names) * 0.8) + + # start training + learn_names(rnn, names, self.alphabet, iterations=iters, + num_processes=num_processes) + + """ Sample a name from the neural network with a given starting letter + Args: + category: (str) the category to sample generated names from + Returns: + name: the output from the neural network + """ + + def sample(self, category, start_letter): + + # select the RNN model to be sampling from + rnn = self.rnn[category] + + # set the random factor of the RNN to randomise names that are generated + rnn.random_factor = 0.7 + + # call the rnn sample function to generate a single name + name = sample(rnn, self.alphabet, start_letter) + + # post process the name and return + return self.postprocess(name) + + """ Load the rnn from its file + Args: + category: (str) the category to load + parent_directory: (str) where to find the model + """ + + def load_rnn(self, category, parent_directory): + model_file = os.path.join(parent_directory, f"{category}.pt") + self.rnn[category] = torch.load(model_file) + + """ Save the rnn of a given category to its file + Args: + category: (str) the category to save + parent_directory: (str) the directory to save the model file to + """ + + def save_rnn(self, category, parent_directory): + rnn = self.rnn[category] + model_file = os.path.join(parent_directory, f"{category}.pt") + torch.save(rnn, model_file) + + +def get_countries(): + return { + country: Country(os.path.join(countries_path, country)) for country in os.listdir(countries_path) if os.path.isdir(os.path.join(countries_path, country)) + } + + +""" train all of the datasets from a specific country + Args: + country: (Country) +""" + + +def train_country(country, name): + datasets = country.datasets + for dataset in datasets: + print(f"Training {dataset} in {name}") + country.train(dataset) + + print(f"Finished training on {dataset}... saving...", end="") + path = os.path.join("data", "models", name) + + # check if the path already exists before trying to make directories + if not os.path.exists(path): + os.makedirs(path) + + country.save_rnn(dataset, path) + print("saved!") + + +def sample_country(country, country_name, number_of_samples=10000): + + datasets = country.datasets + for dataset in datasets: + + # ensure that the model exists before sampling + path = os.path.join("data", "models", country_name) + if os.path.exists(os.path.join(path, dataset + ".pt")): + + # load the country's rnn + country.load_rnn(dataset, path) + + # load the names from the country's dataset, and pre-process them + names = [country.preprocess(name) + for name in country.get_names(dataset)] + + # make a dictionary full of start letters and their frequency + start_letters = {} + + for name in names: + if len(name) > 0: + start_letter = name[0] + + # if the start letter isn't already in the dictionary, add it with value 1 + if start_letter in start_letters: + start_letters[start_letter] += 1 + else: + start_letters[start_letter] = 1 + + # turn each integer count into a float where: letter_weight=frequency/total_names + total = len(names) + + for letter in start_letters: + weight = float(start_letters[letter] / total) + start_letters[letter] = weight + + # sample names from the RNN + sampled_names = [] + + for i in range(number_of_samples): + try: + letter = weighted_choice(start_letters) + sample = country.sample(dataset, letter) + sampled_names.append(sample) + except: + pass + + # remove duplicate names + sampled_names = list(dict.fromkeys(sampled_names)) + + # create a sqlite connection + connection = sqlite3.connect(database) + + # always close the connection when finished + with connection: + cursor = connection.cursor() + for name in sampled_names: + sql = "INSERT INTO names(Name, Origin, Category) VALUES(?, ?, ?)" + + # insert the current name and options into the database + cursor.execute(sql, (name, country_name, dataset)) + + # commit changes and save the database + connection.commit() + + print( + f"Saved {len(sampled_names)} names for {country_name}/{dataset}") + + else: + print(f"the model: {country_name}/{dataset} was not found.") + + +countries_path = "data/datasets" +database = os.path.join("data", "names.db") +if __name__ == "__main__": + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + + # allow processes on this model to share memory + torch.multiprocessing.set_start_method('spawn') + + # List all the directories containing country datasets to populate the countries dictionary + countries = get_countries() + + country_count = len(countries) + # Display debug information + print(f"Loaded {country_count} countries!") + + # list all countries in neat collumns + collumns = 4 + width = 14 + i = 0 + for country in countries: + i += 1 + + # print the country and then its index + print(country, end="") + + # organise into rows and collumns + if i % collumns == 0: + print("") + else: + # separate collumns with spaces + print(" " * (width - len(country)), end="") + + # keep asking until the country selection is valid + good_selection = False + while not good_selection: + # prompt user to select a country to train, or train all + country_selection = input( + "select the name of a country to train on, or (all) to train on all countries: ") + + good_selection = True + selected_countries = [] + + # if the user selected all, then add all countries to list, if not, add the selected country + if country_selection.lower() == "all": + [selected_countries.append(country) for country in countries] + elif country_selection.lower() in countries: + selected_countries.append(country_selection) + else: + print("Country not found, try again") + good_selection = False + + choice = input("(t)rain on data, or (s)ample from weights?") + + if choice.lower()[0] == "t": + for country in selected_countries: + train_country(countries[country], country) + + elif choice.lower()[0] == "s": + create_table(database) + for country in selected_countries: + sample_country(countries[country], country) diff --git a/src/neuralnetwork/util.py b/src/neuralnetwork/util.py new file mode 100644 index 0000000..268819e --- /dev/null +++ b/src/neuralnetwork/util.py @@ -0,0 +1,185 @@ +import sqlite3 +import tensorflow as tf +from pincelate import Pincelate +from multiprocessing import Value +import random + +"""Atomic Number +A multiprocessing-safe Number that you can increment and set a value to. +""" +class AtomicNumber: + def __init__(self, initial=0): + # set the initial value of the number + self._v = Value("d", initial) + + # use python thread locks + self._lock = self._v.get_lock() + + def set(self, num): + with self._lock: + # set the value of the number and return it + self._v.value = num + return self._v.value + + def increment(self, num=1): + with self._lock: + # increase the value of the number and then return it + self._v.value += num + return self._v.value + + def get(self): + return self._v.value + + +""" Capitalise the first letter of a name + Args: + name: (str) the name to transform + Returns: + name: (str) the output name +""" + + +def capitalise(name): + return str(name).capitalize() + + +""" uncapitalise the first letter of a name + Args: + name: (str) the name to transform + Returns: + name: (str) the output name +""" + + +def uncapitalise(name): + return str(name).lower() + + +# import pincelate + +# tell tensorflow to only log ERRORS rather than all problems +tf.get_logger().setLevel('ERROR') + +pin = Pincelate() + +""" Transliterate names into their phonetic spelling + Args: + name: (str) the name to transliterate + Returns: + name: (str) the pronunciation of the name as an arpabet list +""" + + +def transliterate(name): + output = [] + + # iterate through each word and sound out separately + for word in name.split(" "): + try: + for phoneme in pin.soundout(word): + output.append(phoneme) + except Exception as e: + output.append(word) + output.append(" ") + + # remove the trailing " " + output.pop() + + return output + + +""" Transliterate phonetic spellings back into names + Args: + name: (str) the pronunciation of the name as an arpabet list + Returns: + name: (str) a guessed spelling of the given phoneme list +""" + + +def reverse_transliterate(name): + words = [] + + current_word = [] + # iterate through all phonemes, spliting groups between " " into words + for phoneme in name: + if phoneme == " ": + words.append(current_word) + + # reset current word + current_word = [] + else: + current_word.append(phoneme) + + # add whats left of the current word to the list of words + words.append(current_word) + + # spell each word separately + spellings = [pin.spell(word) for word in words] + return " ".join(spellings) + + +"""Load random line from a given filename +""" + + +def get_random_line(file_name): + total_bytes = os.stat(file_name).st_size + random_point = random.randint(0, total_bytes) + file = open(file_name) + file.seek(random_point) + file.readline() # skip this line to clear the partial line + return file.readline() + + +""" Concatenate elemnts of a list + Args: + name: (str[]) the letters of a name in an array + Returns: + name: (str) +""" + + +def deserialise(name): + return "".join(name) + + +""" return a random item from a dictionary of weighted items + Args: + weights: (dict) a dictionary containing the items as keys and float values as weights + Returns: + item: a random item selected from the dictionary +""" + + +def weighted_choice(weights): + # choose a randm number between 0 and 1 + choice = random.uniform(0.0, 1.0) + + # iterate through weights, subtracting the weight from the choice each time + for item, weight in weights.items(): + choice -= weight + + # if we are currently on the chosen item, return it + if choice < 0: + return item + + # in case the input dictionary is incorrectly setup, return the last item + return list(weights)[-1] + + +def create_table(database_path): + # connect to the database and get the cursor + connection = sqlite3.connect(database_path) + + # always close the connection at the end + with connection: + cursor = connection.cursor() + + cursor.execute("CREATE TABLE IF NOT EXISTS names (\ + Name TEXT,\ + Origin TEXT,\ + Category TEXT\ + )") + + # commit the changes, saving them + connection.commit() diff --git a/src/webserver/dist/index.html b/src/webserver/dist/index.html new file mode 100644 index 0000000..cd016b2 --- /dev/null +++ b/src/webserver/dist/index.html @@ -0,0 +1,122 @@ +<!DOCTYPE HTML> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Name Generator</title> + + <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"/> + + <script type="text/javascript" src="/site.js"></script> + <link rel="stylesheet" href="style.css"> + + +</head> +<body onload="updateMap()"> + <div class="main"> + <h1 class="title box-item">Name Generator</h1> + + <div id="namearea" class="box-item"> + <!-- Area for generated names to show--> + </div> + + <button class="box-item" id="generate" onclick="generateName()">Generate Name</button> + + <div class="options box-item"> + <select id="gender"> + <option value="male">Male</option> + <option value="female">Female</option> + </select> + + <select id="origin" onchange="if (this.selectedIndex) updateMap();"> + <option value="uk">UK</option> + <option value="usa">USA</option> + <option value="taiwan">Taiwan</option> + <option value="switzerland">Switzerland</option> + <option value="sweden">Sweden</option> + <option value="spain">Spain</option> + <option value="south_africa">South Africa</option> + <option value="slovenia">Slovenia</option> + <option value="singapore">Singapore</option> + <option value="serbia">Serbia</option> + <option value="russia">Russia</option> + <option value="puerto_rico">Puerto Rico</option> + <option value="portugal">Portugal</option> + <option value="poland">Poland</option> + <option value="philpine">Philippines</option> + <option value="peru">Peru</option> + <option value="panama">Panama</option> + <option value="norway">Norway</option> + <option value="nigeria">Nigeria</option> + <option value="netherland">Netherlands</option> + <option value="namibia">Namibia</option> + <option value="moldova">Moldova</option> + <option value="mexico">Mexico</option> + <option value="mauritius">Mauritius</option> + <option value="malta">Malta</option> + <option value="malaysia">Malaysia</option> + <option value="macao">Macao</option> + <option value="luxemburj">Luxembourg</option> + <option value="lithunia">Lithuania</option> + <option value="jamaica">Jamaica</option> + <option value="italy">Italy</option> + <option value="israel">Israel</option> + <option value="ireland">Ireland</option> + <option value="iran">Iran</option> + <option value="indonesia">Indonesia</option> + <option value="india">India</option> + <option value="iceland">Iceland</option> + <option value="hungary">Hungary</option> + <option value="honduras">Honduras</option> + <option value="haiti">Haiti</option> + <option value="finland">Finland</option> + <option value="fiji">Fiji</option> + <option value="ethopia">Ethiopia</option> + <option value="estonia">Estonia</option> + <option value="ecuador">Ecuador</option> + <option value="dibouti">Djibouti</option> + <option value="denmark">Denmark</option> + <option value="czech">Czech</option> + <option value="cyprus">Cyprus</option> + <option value="croatia">Croatia</option> + <option value="costa">Costa Rica</option> + <option value="colombia">Colombia</option> + <option value="chile">Chile</option> + <option value="canada">Canada</option> + <option value="cameroon">Cameroon</option> + <option value="cambodia">Cambodia</option> + <option value="burundi">Burundi</option> + <option value="bulgaria">Bulgaria</option> + <option value="brunei">Brunei</option> + <option value="brazil">Brazil</option> + <option value="botswana">Botswana</option> + <option value="bangladesh">Bangladesh</option> + <option value="azerbaijan">Azerbaijan</option> + <option value="austria">Austria</option> + <option value="argentina">Argentina</option> + <option value="angolia">Angola</option> + <option value="albania">Albania</option> + <option value="afghanistan">Afghanistan</option> + </select> + </div> + + <canvas id="worldmap" width="2947" height="1601"></canvas> + + + <div> + <button id="advanced" onclick="toggleAdvanced()">Advanced Options</button> + </div> + + <div id="advancedoptions" style="display: none"> + <p></p> + <label>number of names: </label><input id="number" type="number" value="1" min="1" max="99" maxlength="2" onkeyup="forceCount()"> + <p></p> + + <label>generate surnames: </label><input id="surnames" type="checkbox" checked="true"> + <span class="indicator" onclick="checkBox(document.getElementById('surnames'))"></span> + </input> + </div> + </div> + + +</body> +</html> diff --git a/src/webserver/dist/map/afghanistan.png b/src/webserver/dist/map/afghanistan.png Binary files differnew file mode 100644 index 0000000..49abc92 --- /dev/null +++ b/src/webserver/dist/map/afghanistan.png diff --git a/src/webserver/dist/map/albania.png b/src/webserver/dist/map/albania.png Binary files differnew file mode 100644 index 0000000..c045c57 --- /dev/null +++ b/src/webserver/dist/map/albania.png diff --git a/src/webserver/dist/map/angolia.png b/src/webserver/dist/map/angolia.png Binary files differnew file mode 100644 index 0000000..2e415e5 --- /dev/null +++ b/src/webserver/dist/map/angolia.png diff --git a/src/webserver/dist/map/argentina.png b/src/webserver/dist/map/argentina.png Binary files differnew file mode 100644 index 0000000..458376c --- /dev/null +++ b/src/webserver/dist/map/argentina.png diff --git a/src/webserver/dist/map/austria.png b/src/webserver/dist/map/austria.png Binary files differnew file mode 100644 index 0000000..f3ed00e --- /dev/null +++ b/src/webserver/dist/map/austria.png diff --git a/src/webserver/dist/map/azerbaijan.png b/src/webserver/dist/map/azerbaijan.png Binary files differnew file mode 100644 index 0000000..430b9d6 --- /dev/null +++ b/src/webserver/dist/map/azerbaijan.png diff --git a/src/webserver/dist/map/background.png b/src/webserver/dist/map/background.png Binary files differnew file mode 100644 index 0000000..77802f6 --- /dev/null +++ b/src/webserver/dist/map/background.png diff --git a/src/webserver/dist/map/bangladesh.png b/src/webserver/dist/map/bangladesh.png Binary files differnew file mode 100644 index 0000000..8fdf65a --- /dev/null +++ b/src/webserver/dist/map/bangladesh.png diff --git a/src/webserver/dist/map/botswana.png b/src/webserver/dist/map/botswana.png Binary files differnew file mode 100644 index 0000000..ec58775 --- /dev/null +++ b/src/webserver/dist/map/botswana.png diff --git a/src/webserver/dist/map/brazil.png b/src/webserver/dist/map/brazil.png Binary files differnew file mode 100644 index 0000000..8ba32c5 --- /dev/null +++ b/src/webserver/dist/map/brazil.png diff --git a/src/webserver/dist/map/brunei.png b/src/webserver/dist/map/brunei.png Binary files differnew file mode 100644 index 0000000..c518380 --- /dev/null +++ b/src/webserver/dist/map/brunei.png diff --git a/src/webserver/dist/map/bulgaria.png b/src/webserver/dist/map/bulgaria.png Binary files differnew file mode 100644 index 0000000..c8edece --- /dev/null +++ b/src/webserver/dist/map/bulgaria.png diff --git a/src/webserver/dist/map/burundi.png b/src/webserver/dist/map/burundi.png Binary files differnew file mode 100644 index 0000000..3f8d894 --- /dev/null +++ b/src/webserver/dist/map/burundi.png diff --git a/src/webserver/dist/map/cambodia.png b/src/webserver/dist/map/cambodia.png Binary files differnew file mode 100644 index 0000000..c92c6f3 --- /dev/null +++ b/src/webserver/dist/map/cambodia.png diff --git a/src/webserver/dist/map/cameroon.png b/src/webserver/dist/map/cameroon.png Binary files differnew file mode 100644 index 0000000..b5b57ea --- /dev/null +++ b/src/webserver/dist/map/cameroon.png diff --git a/src/webserver/dist/map/canada.png b/src/webserver/dist/map/canada.png Binary files differnew file mode 100644 index 0000000..7358637 --- /dev/null +++ b/src/webserver/dist/map/canada.png diff --git a/src/webserver/dist/map/chile.png b/src/webserver/dist/map/chile.png Binary files differnew file mode 100644 index 0000000..e0a3c50 --- /dev/null +++ b/src/webserver/dist/map/chile.png diff --git a/src/webserver/dist/map/colombia.png b/src/webserver/dist/map/colombia.png Binary files differnew file mode 100644 index 0000000..3859cc0 --- /dev/null +++ b/src/webserver/dist/map/colombia.png diff --git a/src/webserver/dist/map/costa.png b/src/webserver/dist/map/costa.png Binary files differnew file mode 100644 index 0000000..035badd --- /dev/null +++ b/src/webserver/dist/map/costa.png diff --git a/src/webserver/dist/map/croatia.png b/src/webserver/dist/map/croatia.png Binary files differnew file mode 100644 index 0000000..1ce5650 --- /dev/null +++ b/src/webserver/dist/map/croatia.png diff --git a/src/webserver/dist/map/cyprus.png b/src/webserver/dist/map/cyprus.png Binary files differnew file mode 100644 index 0000000..ea90e2a --- /dev/null +++ b/src/webserver/dist/map/cyprus.png diff --git a/src/webserver/dist/map/czech.png b/src/webserver/dist/map/czech.png Binary files differnew file mode 100644 index 0000000..9f89545 --- /dev/null +++ b/src/webserver/dist/map/czech.png diff --git a/src/webserver/dist/map/denmark.png b/src/webserver/dist/map/denmark.png Binary files differnew file mode 100644 index 0000000..bef926b --- /dev/null +++ b/src/webserver/dist/map/denmark.png diff --git a/src/webserver/dist/map/dibouti.png b/src/webserver/dist/map/dibouti.png Binary files differnew file mode 100644 index 0000000..43015e8 --- /dev/null +++ b/src/webserver/dist/map/dibouti.png diff --git a/src/webserver/dist/map/ecuador.png b/src/webserver/dist/map/ecuador.png Binary files differnew file mode 100644 index 0000000..bf2e9d4 --- /dev/null +++ b/src/webserver/dist/map/ecuador.png diff --git a/src/webserver/dist/map/estonia.png b/src/webserver/dist/map/estonia.png Binary files differnew file mode 100644 index 0000000..fa6ac33 --- /dev/null +++ b/src/webserver/dist/map/estonia.png diff --git a/src/webserver/dist/map/ethopia.png b/src/webserver/dist/map/ethopia.png Binary files differnew file mode 100644 index 0000000..207b3e7 --- /dev/null +++ b/src/webserver/dist/map/ethopia.png diff --git a/src/webserver/dist/map/fiji.png b/src/webserver/dist/map/fiji.png Binary files differnew file mode 100644 index 0000000..b574fc9 --- /dev/null +++ b/src/webserver/dist/map/fiji.png diff --git a/src/webserver/dist/map/finland.png b/src/webserver/dist/map/finland.png Binary files differnew file mode 100644 index 0000000..1a2754e --- /dev/null +++ b/src/webserver/dist/map/finland.png diff --git a/src/webserver/dist/map/haiti.png b/src/webserver/dist/map/haiti.png Binary files differnew file mode 100644 index 0000000..c0773a6 --- /dev/null +++ b/src/webserver/dist/map/haiti.png diff --git a/src/webserver/dist/map/honduras.png b/src/webserver/dist/map/honduras.png Binary files differnew file mode 100644 index 0000000..fa7442d --- /dev/null +++ b/src/webserver/dist/map/honduras.png diff --git a/src/webserver/dist/map/hungary.png b/src/webserver/dist/map/hungary.png Binary files differnew file mode 100644 index 0000000..97d9e91 --- /dev/null +++ b/src/webserver/dist/map/hungary.png diff --git a/src/webserver/dist/map/iceland.png b/src/webserver/dist/map/iceland.png Binary files differnew file mode 100644 index 0000000..d1f0e7d --- /dev/null +++ b/src/webserver/dist/map/iceland.png diff --git a/src/webserver/dist/map/india.png b/src/webserver/dist/map/india.png Binary files differnew file mode 100644 index 0000000..e0fc17b --- /dev/null +++ b/src/webserver/dist/map/india.png diff --git a/src/webserver/dist/map/indonesia.png b/src/webserver/dist/map/indonesia.png Binary files differnew file mode 100644 index 0000000..c31bf40 --- /dev/null +++ b/src/webserver/dist/map/indonesia.png diff --git a/src/webserver/dist/map/iran.png b/src/webserver/dist/map/iran.png Binary files differnew file mode 100644 index 0000000..2ee5b2b --- /dev/null +++ b/src/webserver/dist/map/iran.png diff --git a/src/webserver/dist/map/ireland.png b/src/webserver/dist/map/ireland.png Binary files differnew file mode 100644 index 0000000..92fd6dc --- /dev/null +++ b/src/webserver/dist/map/ireland.png diff --git a/src/webserver/dist/map/israel.png b/src/webserver/dist/map/israel.png Binary files differnew file mode 100644 index 0000000..3c350f2 --- /dev/null +++ b/src/webserver/dist/map/israel.png diff --git a/src/webserver/dist/map/italy.png b/src/webserver/dist/map/italy.png Binary files differnew file mode 100644 index 0000000..fb18140 --- /dev/null +++ b/src/webserver/dist/map/italy.png diff --git a/src/webserver/dist/map/jamaica.png b/src/webserver/dist/map/jamaica.png Binary files differnew file mode 100644 index 0000000..0cc2224 --- /dev/null +++ b/src/webserver/dist/map/jamaica.png diff --git a/src/webserver/dist/map/lithunia.png b/src/webserver/dist/map/lithunia.png Binary files differnew file mode 100644 index 0000000..633fc4b --- /dev/null +++ b/src/webserver/dist/map/lithunia.png diff --git a/src/webserver/dist/map/luxemburj.png b/src/webserver/dist/map/luxemburj.png Binary files differnew file mode 100644 index 0000000..c296bd0 --- /dev/null +++ b/src/webserver/dist/map/luxemburj.png diff --git a/src/webserver/dist/map/macao.png b/src/webserver/dist/map/macao.png Binary files differnew file mode 100644 index 0000000..8c3017b --- /dev/null +++ b/src/webserver/dist/map/macao.png diff --git a/src/webserver/dist/map/malaysia.png b/src/webserver/dist/map/malaysia.png Binary files differnew file mode 100644 index 0000000..7c14b5a --- /dev/null +++ b/src/webserver/dist/map/malaysia.png diff --git a/src/webserver/dist/map/malta.png b/src/webserver/dist/map/malta.png Binary files differnew file mode 100644 index 0000000..bdbfc49 --- /dev/null +++ b/src/webserver/dist/map/malta.png diff --git a/src/webserver/dist/map/mauritius.png b/src/webserver/dist/map/mauritius.png Binary files differnew file mode 100644 index 0000000..6e39be8 --- /dev/null +++ b/src/webserver/dist/map/mauritius.png diff --git a/src/webserver/dist/map/mexico.png b/src/webserver/dist/map/mexico.png Binary files differnew file mode 100644 index 0000000..ac7d570 --- /dev/null +++ b/src/webserver/dist/map/mexico.png diff --git a/src/webserver/dist/map/moldova.png b/src/webserver/dist/map/moldova.png Binary files differnew file mode 100644 index 0000000..aea9bb2 --- /dev/null +++ b/src/webserver/dist/map/moldova.png diff --git a/src/webserver/dist/map/namibia.png b/src/webserver/dist/map/namibia.png Binary files differnew file mode 100644 index 0000000..013eb0c --- /dev/null +++ b/src/webserver/dist/map/namibia.png diff --git a/src/webserver/dist/map/netherland.png b/src/webserver/dist/map/netherland.png Binary files differnew file mode 100644 index 0000000..ea929f8 --- /dev/null +++ b/src/webserver/dist/map/netherland.png diff --git a/src/webserver/dist/map/nigeria.png b/src/webserver/dist/map/nigeria.png Binary files differnew file mode 100644 index 0000000..fbb8c81 --- /dev/null +++ b/src/webserver/dist/map/nigeria.png diff --git a/src/webserver/dist/map/norway.png b/src/webserver/dist/map/norway.png Binary files differnew file mode 100644 index 0000000..8246c98 --- /dev/null +++ b/src/webserver/dist/map/norway.png diff --git a/src/webserver/dist/map/panama.png b/src/webserver/dist/map/panama.png Binary files differnew file mode 100644 index 0000000..2a080cb --- /dev/null +++ b/src/webserver/dist/map/panama.png diff --git a/src/webserver/dist/map/peru.png b/src/webserver/dist/map/peru.png Binary files differnew file mode 100644 index 0000000..c0c759b --- /dev/null +++ b/src/webserver/dist/map/peru.png diff --git a/src/webserver/dist/map/philpine.png b/src/webserver/dist/map/philpine.png Binary files differnew file mode 100644 index 0000000..4301c70 --- /dev/null +++ b/src/webserver/dist/map/philpine.png diff --git a/src/webserver/dist/map/poland.png b/src/webserver/dist/map/poland.png Binary files differnew file mode 100644 index 0000000..f16d57f --- /dev/null +++ b/src/webserver/dist/map/poland.png diff --git a/src/webserver/dist/map/portugal.png b/src/webserver/dist/map/portugal.png Binary files differnew file mode 100644 index 0000000..bdec23d --- /dev/null +++ b/src/webserver/dist/map/portugal.png diff --git a/src/webserver/dist/map/puerto_rico.png b/src/webserver/dist/map/puerto_rico.png Binary files differnew file mode 100644 index 0000000..e7c0b10 --- /dev/null +++ b/src/webserver/dist/map/puerto_rico.png diff --git a/src/webserver/dist/map/russia.png b/src/webserver/dist/map/russia.png Binary files differnew file mode 100644 index 0000000..e77b48f --- /dev/null +++ b/src/webserver/dist/map/russia.png diff --git a/src/webserver/dist/map/serbia.png b/src/webserver/dist/map/serbia.png Binary files differnew file mode 100644 index 0000000..c3debe2 --- /dev/null +++ b/src/webserver/dist/map/serbia.png diff --git a/src/webserver/dist/map/singapore.png b/src/webserver/dist/map/singapore.png Binary files differnew file mode 100644 index 0000000..59e3aec --- /dev/null +++ b/src/webserver/dist/map/singapore.png diff --git a/src/webserver/dist/map/slovenia.png b/src/webserver/dist/map/slovenia.png Binary files differnew file mode 100644 index 0000000..1dd5ebf --- /dev/null +++ b/src/webserver/dist/map/slovenia.png diff --git a/src/webserver/dist/map/south_africa.png b/src/webserver/dist/map/south_africa.png Binary files differnew file mode 100644 index 0000000..ecdccb7 --- /dev/null +++ b/src/webserver/dist/map/south_africa.png diff --git a/src/webserver/dist/map/spain.png b/src/webserver/dist/map/spain.png Binary files differnew file mode 100644 index 0000000..b6947e3 --- /dev/null +++ b/src/webserver/dist/map/spain.png diff --git a/src/webserver/dist/map/sweden.png b/src/webserver/dist/map/sweden.png Binary files differnew file mode 100644 index 0000000..6b7ba10 --- /dev/null +++ b/src/webserver/dist/map/sweden.png diff --git a/src/webserver/dist/map/switzerland.png b/src/webserver/dist/map/switzerland.png Binary files differnew file mode 100644 index 0000000..6a8180a --- /dev/null +++ b/src/webserver/dist/map/switzerland.png diff --git a/src/webserver/dist/map/taiwan.png b/src/webserver/dist/map/taiwan.png Binary files differnew file mode 100644 index 0000000..ca08390 --- /dev/null +++ b/src/webserver/dist/map/taiwan.png diff --git a/src/webserver/dist/map/uk.png b/src/webserver/dist/map/uk.png Binary files differnew file mode 100644 index 0000000..51f6e4d --- /dev/null +++ b/src/webserver/dist/map/uk.png diff --git a/src/webserver/dist/map/usa.png b/src/webserver/dist/map/usa.png Binary files differnew file mode 100644 index 0000000..06cabde --- /dev/null +++ b/src/webserver/dist/map/usa.png diff --git a/src/webserver/dist/site.js b/src/webserver/dist/site.js new file mode 100644 index 0000000..2e9bac3 --- /dev/null +++ b/src/webserver/dist/site.js @@ -0,0 +1,129 @@ + + +// the function to be called when the generate name button is pressed +function generateName() { + + // get the values of the various buttons and selectors and store them as variables + var gender = document.getElementById("gender").value; + var origin = document.getElementById("origin").value; + + var count = parseInt(document.getElementById("number").value); + var surnames = document.getElementById("surnames").checked; + + // create a request object + var request = { + "origin": origin, + "gender": gender, + "count": count, + "surname": surnames + }; + + // turn the request json into a string + request = JSON.stringify(request) + + console.log(request) + + // Make the http request using ajax + const http = new XMLHttpRequest(); + const url = "/api/name"; + http.open("POST", url); + http.send(request); + + // create a listener for when the request is returned + http.onreadystatechange = (e) => { + showNames(JSON.parse(http.responseText)) + } +} + +// Change the page's html to show the generated names +function showNames(names) { + + // get the name area element + var nameArea = document.getElementById("namearea"); + + // delete all existing name entries + while (nameArea.lastChild) { + nameArea.removeChild(nameArea.lastChild); + } + + // iterate through all of the given names + names.names.forEach((name) => { + + // create the name element + var nameElement = document.createElement("p"); + nameElement.textContent = name; + nameElement.classList.add("name"); + + // add the name element to the name area + nameArea.appendChild(nameElement); + }); +} + +function updateMap() { + // Load the current country of origin + var origin = document.getElementById("origin").value; + + console.log(origin) + + // get the canvas context for the worldmap + var canvas = document.getElementById("worldmap"); + var context = canvas.getContext("2d"); + + // clear the canvas + context.clearRect(0, 0, canvas.width, canvas.height); + + // create the background image + var background = new Image(); + background.src = "/map/background.png" + + // wait for the image to load before trying to draw it + background.onload = function() { + context.drawImage(background, 0, 0) + + // only draw the country after the background has been drawn + var country = new Image(); + country.src = "/map/" + origin + ".png" + + // wait for the image to load before trying to draw it + country.onload = function() { + context.drawImage(country, 0, 0) + }; + + }; + +} + +// force the count to be between 1 and 99 +function forceCount() { + var count = parseInt(document.getElementById("number").value); + if (count > 99) { + document.getElementById("number").value = 99 + } else if (count < 1) { + document.getElementById("number").value = 1 + } +} + +// toggle the visibility of advanced options +function toggleAdvanced() { + // get the advanced options div + var element = document.getElementById("advancedoptions"); + + // if display: none, make it visible and vice versa + if (element.style.display == "none") { + element.style.display = "" + } else { + element.style.display = "none" + } + +} + +// toggle the checkbox from checked to unchecked and vice versa +function checkBox(checkbox) { + if (checkbox.getAttribute("checked")) { + // uncheck the box + checkbox.removeAttribute("checked"); + } else { + // set the box to checked + checkbox.setAttribute("checked", true); + } +} diff --git a/src/webserver/dist/style.css b/src/webserver/dist/style.css new file mode 100644 index 0000000..1ba596d --- /dev/null +++ b/src/webserver/dist/style.css @@ -0,0 +1,138 @@ +#worldmap { + width: 50%; +} + +body { + font-family: sans-serif; + background-color: #191919; + color: #f0c674; + width:auto; +} + +.main { + padding: 0; + margin-left: 10%; + margin-right: 10%; + width: 80%; + font-size: 2rem; +} + +#worldmap { + width: 50%; +} + +@media (orientation : portrait) { + .main { + padding: 0; + margin: 0; + width: 100%; + font-size: 1.5rem; + } + + #worldmap { + width: 100%; + } +} + + +.main { + display: inline-block; + text-align: center; + +} + +.box-item { + margin-top: 1rem; + margin-bottom: 1rem; +} + + +button,select,input[type=number] { + font-size: inherit; + background-color: #191919; + color: #f0c674; + border-radius: 0.5em; + text-decoration: none; + padding: 0.5rem; + border: 0.05rem solid #373b41; + box-shadow: 0 0.2em #373b41; +} + +#number { + width: 3rem; +} +img { + width: 2rem; +} + +button:active { + background-color: #373b41; + box-shadow: 0 0.1em #373b41; + transform: translateY(0.1em); +} + + +.box { + margin-top: 10%; + padding: 1%; + text-align: center; + display: inline-block; + box-sizing: border-box; + margin-left:15%; + width: 70%; + height: 50%; + + background: transparent; + border: 0; + outline: 0; + border-bottom: 0.25rem solid #0f7d7b; + color: #e8922a; + font-size: 100%; + outline: none !important; + +} +input:focus, textarea { + outline: none !important; +} +button:focus, textarea { + outline: none !important; +} + + +input[type=checkbox]{ + position:absolute; + opacity: 0; + z-index: -9999; +} + +input[type=checkbox] + .indicator { + width: 1.5rem; + height: 1.5rem; + margin-left: 0.5rem; + position: absolute; + + + font-size: inherit; + background-color: #191919; + color: #191919; + border-radius: 0.5em; + text-decoration: none; + padding: 0.5rem; + border: 0.05rem solid #373b41; + box-shadow: 0 0.2em #373b41; + + content: ""; +} + +input[type=checkbox]:checked + .indicator { + background-color: #373b41; + box-shadow: 0 0.1em #373b41; + transform: translateY(0.1em); +} + +input[type=checkbox]+ .indicator::after { + content: ""; +} +input[type=checkbox]:checked + .indicator::after { + content: "X"; +} diff --git a/src/webserver/dist/subdir/image.png b/src/webserver/dist/subdir/image.png Binary files differnew file mode 100644 index 0000000..80fb972 --- /dev/null +++ b/src/webserver/dist/subdir/image.png diff --git a/src/webserver/dist/subdir/index.html b/src/webserver/dist/subdir/index.html new file mode 100644 index 0000000..b7e784a --- /dev/null +++ b/src/webserver/dist/subdir/index.html @@ -0,0 +1 @@ +index of the sub dir diff --git a/src/webserver/dist/subdir/test.txt b/src/webserver/dist/subdir/test.txt new file mode 100644 index 0000000..6ee329a --- /dev/null +++ b/src/webserver/dist/subdir/test.txt @@ -0,0 +1 @@ +this is text.txt diff --git a/src/webserver/pom.xml b/src/webserver/pom.xml new file mode 100644 index 0000000..c4a716d --- /dev/null +++ b/src/webserver/pom.xml @@ -0,0 +1,47 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>io.github.davidovski.names</groupId> + <artifactId>NameGenerator</artifactId> + <version>0.0.1-SNAPSHOT</version> + <packaging>jar</packaging> + <dependencies> + <dependency> + <groupId>org.xerial</groupId> + <artifactId>sqlite-jdbc</artifactId> + <version>3.32.3</version> + </dependency> + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + <version>20210307</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>shade</goal> + </goals> + <configuration> + <shadedArtifactAttached>true</shadedArtifactAttached> + <transformers> + <transformer implementation= + "org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> + <mainClass>io.github.davidovski.names.WebServer</mainClass> + </transformer> + </transformers> + </configuration> + </execution> + </executions> + </plugin> + + </plugins> + </build> +</project> diff --git a/src/webserver/src/main/java/io/github/davidovski/names/APIRequestHandler.java b/src/webserver/src/main/java/io/github/davidovski/names/APIRequestHandler.java new file mode 100644 index 0000000..5ef2cfe --- /dev/null +++ b/src/webserver/src/main/java/io/github/davidovski/names/APIRequestHandler.java @@ -0,0 +1,112 @@ +package io.github.davidovski.names; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONTokener; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; + +@SuppressWarnings("restriction") +public class APIRequestHandler implements HttpHandler { + + private NameDatabaseManager nameDatabaseManager; + + public APIRequestHandler() { + nameDatabaseManager = new NameDatabaseManager(new File("names.db")); + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + // get the requested path + String path = exchange.getRequestURI().getPath(); + + System.out.println(path); + + if (path.startsWith("/api/name")) { + + // parse the body as a json object + JSONTokener jsonParser = new JSONTokener(exchange.getRequestBody()); + JSONObject json = (JSONObject) jsonParser.nextValue(); + + System.out.println(json.toString(2)); + + if (json == null) { + // Malformed JSON request, 400 + sendJSON(exchange, (new JSONObject()).put("message", "Malformed JSON body"), 400); + return; + } + + // generate name(s) and send it + generateName(exchange, json); + } else { + sendJSON(exchange, (new JSONObject()).put("message", "Not Found"), 404); + } + } + + public void generateName(HttpExchange exchange, JSONObject options) throws JSONException, IOException { + String origin = options.optString("origin", "none").toLowerCase(); + + int count = options.optInt("count", 1); + + // ensure that the count is between 1-100 + if (count < 1 || count > 100) { + sendJSON(exchange, (new JSONObject()).put("message", "Name count is out of range: Ensure that the request is between 1 and 100 names"), 400); + return; + } + + String gender = options.optString("gender", "female"); + + // ensure that the gender is either male or female + if (!gender.equals("male") && !gender.equals("female")) { + sendJSON(exchange, (new JSONObject()).put("message", "Requested gender is invalid"), 400); + return; + } + + // Store the names in an array + List<String> names = nameDatabaseManager.getRandomNames(origin, gender, count); + + if (options.optBoolean("surname")) { + List<String> surnames = nameDatabaseManager.getRandomNames(origin, "surname", count); + + // Add surnames to the end of each firstname in the names list + for (int i = 0; i < count; i++) { + String fullname = names.get(i) + " " + surnames.get(i); + names.set(i, fullname); + } + } + + // Create the response json object + JSONObject response = new JSONObject(); + response.put("message", "Generated " + count + " names"); + response.put("names", new JSONArray(names)); + + // send the json back to the client + sendJSON(exchange, response, 200); + } + + public void sendJSON(HttpExchange exchange, JSONObject json, int responseCode) throws IOException { + // convert the json to a string + String response = json.toString(2); + + // calculate the response content size + int contentSize = response.toString().getBytes().length; + + // set the response headers + exchange.getResponseHeaders().add("Content-Type", "text/json"); + exchange.sendResponseHeaders(responseCode, contentSize); + + // write the response to the output stream + OutputStream outputStream = exchange.getResponseBody(); + + outputStream.write(response.toString().getBytes()); + outputStream.close(); + } + +} diff --git a/src/webserver/src/main/java/io/github/davidovski/names/NameDatabaseManager.java b/src/webserver/src/main/java/io/github/davidovski/names/NameDatabaseManager.java new file mode 100644 index 0000000..8822d9c --- /dev/null +++ b/src/webserver/src/main/java/io/github/davidovski/names/NameDatabaseManager.java @@ -0,0 +1,75 @@ +package io.github.davidovski.names; + +import java.io.File; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +public class NameDatabaseManager { + private File databaseFile; + private Connection connection; + + private static final String TABLE = "names"; + + public NameDatabaseManager(File databaseFile) { + this.databaseFile = databaseFile; + + connect(); + } + + /** + * Creates a connection to the database. If one could not be created, the connection will remain as null + */ + private void connect() { + connection = null; + try { + connection = DriverManager.getConnection("jdbc:sqlite:" + databaseFile.getPath()); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public List<String> getRandomNames(String origin, String category, int quantitiy) { + // create the set to return, even if empty + List<String> names = new ArrayList<String>(); + + if (connection != null) { + // Create an sql statement + String sql = "SELECT Name FROM " + TABLE + " WHERE Origin=? AND Category=? ORDER BY RANDOM() LIMIT ?;"; + PreparedStatement statement; + try { + statement = connection.prepareStatement(sql); + + // insert relevant values into the statement + statement.setString(1, origin); + statement.setString(2, category); + statement.setInt(3, quantitiy); + + // execute the query and get the result + ResultSet result = statement.executeQuery(); + + // Add all of the results to the names set + while (result.next()) { + String name = result.getString("Name"); + names.add(name); + } + } catch (SQLException e) { + e.printStackTrace(); + } + + } + return names; + } + + public static void main(String[] args) { + NameDatabaseManager dbManager = new NameDatabaseManager(new File("names.db")); + List<String> names = dbManager.getRandomNames("spain", "female", 10); + for (String name : names) { + System.out.println(name); + } + } +} diff --git a/src/webserver/src/main/java/io/github/davidovski/names/StaticRequestHandler.java b/src/webserver/src/main/java/io/github/davidovski/names/StaticRequestHandler.java new file mode 100644 index 0000000..d10d0b1 --- /dev/null +++ b/src/webserver/src/main/java/io/github/davidovski/names/StaticRequestHandler.java @@ -0,0 +1,85 @@ +package io.github.davidovski.names; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; + +@SuppressWarnings("restriction") +public class StaticRequestHandler implements HttpHandler { + private File root; + + public StaticRequestHandler(File root) { + this.root = root; + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + // get the requested path + String path = exchange.getRequestURI().getPath(); + + File requested = new File(root, path); + + // automatically send the index of a directory + if (requested.isDirectory()) { + requested = new File(requested, "index.html"); + } + + // ensure that the file is in the intended document root + if (!isInRoot(requested, root)) { + sendText(exchange, "Access Denied", 403); + } else if (requested.exists()) { + sendFile(exchange, requested); + } else { + // send 404 if the file isnt found + sendText(exchange, "File Not Found", 404); + } + } + + private void sendFile(HttpExchange exchange, File file) throws IOException { + // read the file as into an array of bytes + byte[] bytes = Files.readAllBytes(file.toPath()); + + // send the file headers + exchange.sendResponseHeaders(200, bytes.length); + + // send the file body + OutputStream os = exchange.getResponseBody(); + os.write(bytes); + os.close(); + } + + private void sendText(HttpExchange exchange, String response, int responseCode) throws IOException { + // calculate the response content size + int contentSize = response.toString().getBytes().length; + + // set the response headers + exchange.getResponseHeaders().add("Content-Type", "text/json"); + exchange.sendResponseHeaders(responseCode, contentSize); + + // write the response to the output stream + OutputStream outputStream = exchange.getResponseBody(); + + outputStream.write(response.toString().getBytes()); + outputStream.close(); + } + + public static boolean isInRoot(File request, File root) { + File parentFile = request; + + // start from the requested file and traverse upwards until reaching the root directory + while (parentFile != null) { + if (root.equals(parentFile)) { + return true; + } + parentFile = parentFile.getParentFile(); + } + + // If there isn't a parent file, return false + return false; + } + +} diff --git a/src/webserver/src/main/java/io/github/davidovski/names/WebServer.java b/src/webserver/src/main/java/io/github/davidovski/names/WebServer.java new file mode 100644 index 0000000..60b311f --- /dev/null +++ b/src/webserver/src/main/java/io/github/davidovski/names/WebServer.java @@ -0,0 +1,51 @@ +package io.github.davidovski.names; + +import java.io.File; +import java.io.IOException; +import java.net.InetSocketAddress; + +import com.sun.net.httpserver.HttpServer; + +@SuppressWarnings("restriction") +public class WebServer { + private int port; + private HttpServer server; + + public WebServer(int port) throws IOException { + this.port = port; + + // create an HTTP server instance + InetSocketAddress socketAddress = new InetSocketAddress(port); + server = HttpServer.create(socketAddress, 0); + + // create a context for the static request handler + server.createContext("/", new StaticRequestHandler(new File("dist"))); + // create a context for the api request handler + server.createContext("/api", new APIRequestHandler()); + + } + + public void start() { + server.start(); + + // tell the user that the webserver has been started, and the port used + System.out.println("Webserver started on port " + port); + } + + + public static void main(String[] args) throws IOException { + + // set a default port number + int port = 8080; + + // parse the arguments for a port number + if (args.length > 0) + port = Integer.parseInt(args[0]); + + // Create the webserver instance + WebServer webServer = new WebServer(port); + + // start the webserver + webServer.start(); + } +} |