From 9840dd694e2c20f2c83a89e020a6904a951dd38d Mon Sep 17 00:00:00 2001 From: Paul Ferrell Date: Mon, 17 Oct 2016 12:36:40 -0600 Subject: [PATCH 1/3] Made devel server compatible with python 3.4. --- devel-server.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/devel-server.py b/devel-server.py index 410e109..f4ae8d4 100755 --- a/devel-server.py +++ b/devel-server.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 import glob +import http import http.server import mistune import os @@ -8,7 +9,13 @@ import pathlib import puzzles import socketserver -HTTPStatus = http.server.HTTPStatus +if hasattr(http, 'HTTPStatus'): + HTTPStatus = http.HTTPStatus +else: + class HTTPStatus: + NOT_FOUND = 404 + OK = 200 + def page(title, body): return """ From 5072b238385b69e86da471cdf1ff15528f865acd Mon Sep 17 00:00:00 2001 From: Paul Ferrell Date: Mon, 17 Oct 2016 13:24:54 -0600 Subject: [PATCH 2/3] Reworked some basics of how the Puzzle class works. Shouldn't look to different from the outside. --- .gitignore | 3 ++- devel-server.py | 3 +-- puzzles.py | 48 +++++++++++++++++++++++++++--------------------- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index c3c1634..a22d658 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,9 @@ *# *.pyc *.o +.idea ./bin/ build/ cache/ target/ -puzzles \ No newline at end of file +puzzles diff --git a/devel-server.py b/devel-server.py index f4ae8d4..732a87b 100755 --- a/devel-server.py +++ b/devel-server.py @@ -1,7 +1,6 @@ #!/usr/bin/python3 import glob -import http import http.server import mistune import os @@ -9,7 +8,7 @@ import pathlib import puzzles import socketserver -if hasattr(http, 'HTTPStatus'): +if hasattr(http.server, 'HTTPStatus'): HTTPStatus = http.HTTPStatus else: class HTTPStatus: diff --git a/puzzles.py b/puzzles.py index e2c79f5..e844a00 100644 --- a/puzzles.py +++ b/puzzles.py @@ -1,12 +1,13 @@ #!/usr/bin/python3 -import hmac -import base64 import argparse +import base64 import glob +import hmac import json -import os import mistune +import multidict +import os import random messageChars = b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' @@ -17,12 +18,19 @@ def djb2hash(buf): h = ((h * 33) + c) & 0xffffffff return h -class Puzzle: - def __init__(self, stream): +class Puzzle(multidict.MultiDict): + + def __init__(self, seed): + super().__init__() + self.message = bytes(random.choice(messageChars) for i in range(20)) - self.fields = {} - self.answers = [] - self.hashes = [] + self.body = '' + + self.rand = random.Random(seed) + + @classmethod + def from_stream(cls, stream): + pzl = cls(None) body = [] header = True @@ -35,34 +43,32 @@ class Puzzle: key, val = line.split(':', 1) key = key.lower() val = val.strip() - self._add_field(key, val) + pzl.add(key, val) else: body.append(line) - self.body = ''.join(body) + pzl.body = ''.join(body) + return pzl - def _add_field(self, key, val): + def add(self, key, value): + super().add(key, value) if key == 'answer': - h = djb2hash(val.encode('utf8')) - self.answers.append(val) - self.hashes.append(h) - else: - self.fields[key] = val + super().add(hash, djb2hash(value.encode('utf8'))) def htmlify(self): return mistune.markdown(self.body) def publish(self): obj = { - 'author': self.fields['author'], - 'hashes': self.hashes, + 'author': self['author'], + 'hashes': self.getall('hash'), 'body': self.htmlify(), } return obj def secrets(self): obj = { - 'answers': self.answers, - 'summary': self.fields['summary'], + 'answers': self.getall('answer'), + 'summary': self['summary'], } return obj @@ -78,7 +84,7 @@ if __name__ == '__main__': filename = os.path.basename(puzzlePath) points, ext = os.path.splitext(filename) points = int(points) - puzzle = Puzzle(open(puzzlePath)) + puzzle = Puzzle.from_stream(open(puzzlePath)) puzzles[points] = puzzle for points in sorted(puzzles): From f22d7d95fbe3629757cfc0c73058f8050b8ca651 Mon Sep 17 00:00:00 2001 From: Paul Ferrell Date: Mon, 17 Oct 2016 19:58:51 -0600 Subject: [PATCH 3/3] Files now come with a file handle to the original file. --- answer_words.txt | 4096 ++++++++++++++++++++++++++++++++++++++++++++++ devel-server.py | 9 +- puzzles.py | 196 ++- 3 files changed, 4278 insertions(+), 23 deletions(-) create mode 100644 answer_words.txt diff --git a/answer_words.txt b/answer_words.txt new file mode 100644 index 0000000..55d9e06 --- /dev/null +++ b/answer_words.txt @@ -0,0 +1,4096 @@ +abalones +abashed +abattoir +abbreviating +abduct +abetters +abettors +abhorrent +ablution +ablutions +aboriginal +aborted +aboveboard +abrades +absence +absorbents +abstention +abstraction +abuser +academically +acceptably +accepting +accompanists +accumulative +accuracy +accurate +accusers +acetate +acidifying +acidity +acolytes +acoustic +acquires +actualized +acuity +adagios +addicting +adherent +adjacently +adjectivally +adjoined +adjuration +adjustable +administrates +admiringly +admonish +admonishments +adores +adorns +adulterers +advance +advancing +advert +advisory +aerosol +aerospace +affability +affable +afflict +affordable +affront +afterbirths +agates +agglomerates +aggravations +aggressiveness +agnostic +agrarian +aiding +ailments +airfoils +airily +airless +aisles +albatrosses +alcoholism +alderwoman +alerting +aliasing +aligns +allayed +allays +alleyway +allocated +allocates +allocation +allotments +allowances +allures +alluring +allusion +aloofness +alternately +always +amalgam +amalgamations +amanuenses +ambassadorship +ambiguity +ambulance +amenity +amiably +amoeba +amoebae +amorality +amounting +amphitheater +amplified +anaconda +anatomy +ancestors +android +anesthesia +anesthetic +angina +angular +animal +animate +animating +animations +anions +annealing +announcements +annoyingly +annoys +annuals +answering +antagonize +antecedent +anthropomorphic +anticlimaxes +antique +antiwar +apathetically +aphelion +aphrodisiacs +apostrophe +apostrophes +appeases +appellation +appendage +appendages +appetizingly +applaud +applauded +applesauce +appliances +applicators +appointing +appraises +apprise +approbations +arboretums +archaeologists +archeologist +archest +archivists +arcing +ardors +arguing +argyles +armadas +arraigned +arraignment +arrangers +arrowhead +arsenals +artichokes +artificially +artistically +ascensions +ashamed +assault +assaulter +assaults +assertiveness +assign +assignations +assignments +assizes +assumes +assuming +astounds +astral +astrological +atrocity +attacked +attained +attempted +attendances +attentiveness +attitudinizing +auctioneers +auctioning +audiences +audits +augurs +aureole +auspiciously +authorizes +authors +automaton +aviaries +aviator +avionics +avoidable +avoirdupois +avowed +awaiting +awaken +awarded +aweigh +awfuller +babble +babysit +bacchanal +backpackers +backpacking +backpedaling +backstage +badness +bagpipe +balanced +baleen +balloon +ballyhooing +baluster +bamboozles +banishment +bankruptcies +banned +bantam +banters +banyans +baptismal +baptisteries +baptized +barbered +bargains +barnstormed +baroness +barraged +barrelled +barrelling +barricaded +barroom +baseless +baselines +bassists +bathing +batsman +beaching +beacons +beaker +beamed +beaning +beatified +beatitude +beautifier +becoming +bedazzled +bedfellow +bedrocks +bedtime +beetles +befouled +beginnings +begrudge +begrudges +beguiled +beholds +beleaguers +belligerently +bellow +bellwether +bellyached +belong +belting +bemoans +benefit +benign +bequeathed +bequeathing +besieged +besieging +besmirches +bestir +bethinking +betokening +bewilders +bewitched +bicameral +bigamist +biggest +binders +binged +birdied +bitchiest +biting +bittersweets +bivouac +bivouacking +blackball +blacked +blackmailed +blackness +bladder +blamed +blaming +blancmange +blaring +blasphemer +blasphemes +bleakest +blessings +blinked +blistered +blocks +blondest +blooding +bloodshot +blotchier +blower +boarders +boasts +boaters +bobbed +bobbing +bobolink +bobsledding +boggle +boldface +bologna +bolting +bondage +bondsman +bonging +bonitoes +boogie +bookkeeping +bookstore +boomeranged +boondoggled +boosters +boosting +bootee +booths +bootlegged +botanical +botanist +bottomed +bouillabaisse +boulevards +bountiful +bouquet +bracelet +bracts +braining +brandies +brandishes +brashest +brawled +brazenly +breach +breaded +breadfruits +breadths +breadwinner +breakage +breastbones +breaststroke +breezier +breviaries +bricklayers +bridal +bridals +brides +bright +brilliant +brilliantly +briquettes +brisket +bristles +bristly +brittleness +brittlest +broadcasting +broadened +broadest +broadness +broadswords +brochure +brochures +broncos +brontosauruses +brownout +browser +bruises +brunettes +brushed +bucketfuls +buckler +bucktooth +buffalo +buffing +buildings +buildup +bulldozes +bullet +bulletined +bulrushes +buncombe +bunion +buoyed +burglarize +burnoose +burros +burrows +busheling +bushwhacking +busybodies +busying +butcher +butchers +buzzards +cablegram +cables +cadaverous +cadger +calcium +calculated +calligrapher +callused +calmed +calved +camber +camellia +cameramen +camisole +camouflaged +camper +cancan +cancans +cancelled +cancers +candles +cannabis +canneries +cantankerously +canteens +cantered +canters +canticles +capering +capons +capriciously +capsize +capsizing +capstan +captain +captivating +caramel +carcass +cardiogram +caressing +caribou +caricaturing +carnivals +caroler +carousels +carpeting +carport +cartwheel +carves +caseload +caseworker +caseworkers +cassava +cassino +castigated +castigators +castings +catalysts +catcalls +catechized +caterers +catheter +cattails +cattle +catwalks +caudal +caught +cavaliers +caveman +caving +cavorting +ceases +ceasing +celebrant +celebrated +celebrates +celerity +celesta +celestial +cellulars +cellulite +censure +censuring +centenarian +centenaries +centers +centralized +cerebellum +ceremonial +ceremony +cesarian +chaining +chairmanship +championing +channelled +channelling +chantey +chapel +chaplaincy +chapped +charitable +charity +charming +charted +chartered +chases +chastened +chastised +chatters +chattier +chauffeured +cheapskate +checkered +cheekbones +cheerleaders +cheerless +cheesecloth +cheesiest +cheroot +chessboard +chewing +chickpea +chiding +chiefer +chiefest +childhoods +chilliness +chillings +chilly +chisel +chisels +chlorinated +choking +choleric +choruses +chronically +chronology +chrysalises +churchyards +churls +cicadas +cinctures +cinematographer +ciphering +circulation +circulations +circulatory +circumcising +circumflexes +circumscribes +circumventing +citizenship +civics +civilians +civilized +civvies +clamminess +clandestinely +clapboarding +clapboards +clapper +clarinetists +clarity +classify +clauses +cleanings +clematises +clergies +clergymen +clerked +cleverness +climactic +climaxes +clippers +clippings +clitorises +cloakroom +closest +cloudy +clutter +coalesce +coarse +coasted +coasting +coasts +cobble +cobblers +cobbling +cockiest +cocooning +codding +coeducational +coeval +coffeecake +coffin +cognac +cohabiting +coined +colder +coldest +collapsible +collectible +collectibles +collectivize +collects +colleges +collie +collocates +colluded +colonizer +coloraturas +column +combed +combustible +comedies +comforted +comity +commandeered +commandeers +commencement +commiserations +commissioner +commutative +compartmentalizes +compassed +compassing +compel +competition +competitively +compiles +completeness +complexes +complicated +component +composer +composite +composition +compound +compounding +comprehensible +compresses +compromising +comptrollers +computes +conceal +concentrating +concentrically +conceptualizations +conciliates +conciser +conclusively +concussions +condemning +condenser +condescends +condoled +condor +conduce +conducing +conducive +conduction +confabs +confederations +confessions +confidante +confinement +confiscate +conflicted +confronting +congestion +conglomeration +congratulate +congratulations +congress +congresses +congressmen +conjecture +conjoint +conjugated +conjurors +conked +conking +connecter +conquers +consciously +consecrates +consequences +considerately +consigning +consignment +consist +consisted +consolidates +conspicuously +conspired +constituted +constrictions +consummated +consumptive +containing +contaminates +contemplative +contest +contiguous +continuation +contort +controversies +contusions +conurbation +convenes +convenient +convergence +converter +convivial +convolutions +convoys +convulses +cooked +coolly +coopers +coordinator +coppery +coquetted +coquetting +corals +cording +cornea +cornrows +cornstalks +coronet +corralled +correspondent +cosigns +cosmetologists +cosmically +cosmologist +costars +cotter +cotton +cottonmouth +cottons +coughs +councillor +counterpoints +counterrevolutionaries +counting +courtliness +courtly +coverlets +cowardliness +cowhide +cowing +crackup +craftily +crashes +credential +credibility +creditable +creels +creeper +cribbing +crimsoning +crinkles +crinoline +crisscrossed +crisscrosses +crofts +crooners +crosschecked +crowns +cruddiest +crudely +cruelly +cruets +crumpet +crunches +crunchiest +cryogenics +crystal +crystalized +crystallize +cuckoos +cultivated +cultural +culvert +cupping +curiously +curliest +currant +curriculums +curtailed +curtailments +cushions +cussing +cyberpunk +cyclamen +cymbals +cytoplasm +dabble +daemons +daffiest +dahlias +daintiest +damaging +dampest +damply +danker +dankest +dapples +darken +darling +dashes +datelined +daubers +daydreamed +daydreaming +deactivating +deadbolt +deaden +dearness +deathtraps +debater +debaters +debauches +debilitate +debits +debonair +debtor +debtors +decadently +decadents +decays +deceitfully +deceitfulness +deceiving +decelerate +decimate +decked +decoding +decolonize +decomposed +deconstruction +decontaminated +decontaminating +decoration +decreasing +deducing +deductible +deducting +deescalating +defaced +defected +defendants +deferments +deflect +defogger +degraded +dehumidifier +dehydrates +dejecting +delegates +deletes +delinquently +deluges +delusions +delusive +delves +delving +demagog +demagogue +demarcate +demarcated +demeans +demesne +demijohn +demise +demoed +demonstrators +demoralize +demoralized +demurring +demurs +dendrite +denied +denizen +denizens +denominates +denominator +denser +dentist +dentists +deodorizes +dependability +dependant +depict +depleted +depleting +deported +deposing +deprecating +depriving +deputies +derail +deregulates +derive +dermatology +dervish +descants +descriptively +desecrating +desert +desire +desolately +despatches +desperate +destination +desultory +detain +detergent +determiners +dethrones +detoxification +devaluation +development +developments +develops +deviate +devised +devours +devout +devoutest +dhotis +diagnosed +dialogues +diddling +diereses +digestive +digitized +digressed +digressing +dilation +dilatory +dillydallies +dillydally +dimensional +diminished +dimwit +diplomacy +diplomata +dippers +dipsticks +directions +directorship +directory +dirigibles +disabusing +disadvantaging +disallowing +disappointingly +disapprovingly +disarms +disassembles +disbarred +disburse +discern +disclosing +discoing +disconnect +disconnections +discontentedly +discontinuations +discontinues +discording +discotheque +discount +discourages +discoursed +discus +discussions +disembowels +disgruntled +dishcloths +disheartens +dishevelled +dishonoring +disillusioning +disinclined +disliking +disorganize +disparaged +dispassionately +dispenses +displayable +disposes +disproven +disruptive +dissected +disservice +dissociated +distastefully +distastes +distillations +distilleries +distillers +distinguishing +distracted +distributions +distributive +diverging +dividend +diviners +divisibility +divisors +divorcing +dizzies +docile +docility +dockets +doctrine +dogfights +dogies +dolefully +domesticity +domicile +domineered +dominion +donate +dormitory +dorsal +dossiers +doubtless +douches +doughtiest +downhill +downplays +downscale +downsize +dozing +drachmas +draftiest +dragonfly +dramatizing +drawbridges +drawstrings +dreaded +dreadful +dreadlocks +dreamlike +dreamy +dreary +drenches +dressage +dressiest +drifted +drivelled +driven +drizzles +drowse +drowsily +drowsiness +drummed +drumming +drumstick +duelling +dumbfound +dunner +duodena +duplicity +during +duskiest +dustbin +dustman +dwarfism +dwelled +dwindled +dynamite +dynamos +earned +earnestness +earthwork +easily +easterlies +eavesdroppers +economized +editorship +effete +efficacious +effusions +eggplants +elaborate +elapse +elating +elbowed +electoral +elicited +elides +elites +ellipse +elongations +emaciating +emancipates +embalmers +embalms +embarking +embitters +emboldening +embossed +embrace +embryos +eminently +emoted +emotions +emphases +emphatic +emphatically +empire +empires +employment +emulsifies +emulsify +enamor +encapsulate +encapsulation +encase +encoded +encoder +encompass +encouragements +encrusted +endeavor +endures +energies +enfeebled +enfolding +enforcers +engages +engender +engenders +engraver +engulfing +enlargement +ennobles +enquiring +enquiry +ensconcing +enshrines +ensnares +entail +entails +entangling +entertainment +enthralls +enthusiastically +enticed +enticements +entire +entombed +entraps +entrusted +enumeration +enunciates +enunciation +envelops +envisions +epaulettes +ephemeral +epidemiology +epilogues +epoxied +equality +equalizing +equestrian +equilateral +equivocates +erasing +erection +eroticism +errors +eruptions +escapees +escorting +espouses +essaying +essayist +essentials +established +establishes +estates +ethically +ethics +ethnologists +eulogizes +euthanasia +evaporating +evened +evener +everlasting +evocation +evolves +exactest +exceed +excepting +excepts +excerpt +excessively +excitement +exclaims +exclusives +excoriate +excretions +exculpate +excuses +executable +executors +exhausted +exhilarated +exhumations +exigent +exiles +existent +existentially +existing +exoduses +exonerating +expanding +expects +expediences +expedites +expending +experiments +expiry +explanatory +exploring +expressed +expressing +expressiveness +expressly +expunge +extemporized +extension +extinguished +extrapolates +extrapolation +extricates +extroversion +extrovert +exults +eyeful +eyelets +facsimiled +factory +factual +faecal +fagged +fainted +fairness +faithfuls +faithlessness +fallibility +fallowed +falsest +falterings +famines +famished +fanatical +fancying +fantasy +farmhands +farmland +farsighted +farting +fastenings +fathoms +feasibility +feasting +featherweights +felicity +feline +fermentation +ferrets +fertilization +fertilizer +fervidly +festoons +fetiches +fetter +feuding +feverish +fibber +fiendish +fiercely +fifteens +figurehead +figures +filching +fillies +filliped +filtering +finalizing +finders +finessed +finesses +fingerprint +finishing +finking +firestorm +firmer +fishbowl +fishier +fishiest +fishnets +fishtailing +fisticuffs +fitted +flagellate +flakiness +flamencos +flames +flanneling +flapjacks +flashier +flatfoot +flatness +fleecing +flicks +flimsiness +flings +flintlocks +flippantly +florid +flotillas +flounces +flourish +fluffing +fluoroscope +fluxing +flyleaves +flyovers +foetuses +fogbound +fogging +foghorns +follow +fondles +fondue +footballers +footbridges +footstep +forborne +forebears +foreboding +forehand +foreshortened +foreskin +forestalls +foresting +foreswore +foretasting +foreword +forklifts +forsworn +fortifies +fortissimo +fortitude +fortuitously +forward +fossil +fossilizes +foundations +foxtrotting +fracas +fractiously +fractures +frailest +frailty +frantic +frappes +fraternally +fraternization +fraudulently +freebooters +freewheeled +freewill +freighters +frenetically +frequenting +freshman +freshmen +friendship +friers +fringes +frisking +frittering +frizzed +frolicked +frontispiece +froths +fruitiest +frustrates +fulminations +functioning +fundamentally +funerals +furling +furloughing +furnish +furnished +furors +furriest +furrows +furtherance +fustier +gabardine +gadded +gaffed +gaggle +gainsays +galena +gallantly +gallery +gallivanted +gallivanting +gallstones +gamesmanship +gamest +gangrenes +garbanzo +gardening +garishly +garners +garnish +garnished +gashes +gather +gauchos +gaudiest +gearshifts +gearwheels +geishas +gelling +geneses +genetic +genetically +geneticist +genteel +gentian +gentlefolk +genuineness +geodesics +geostationary +gesticulated +gesture +gestures +gherkin +ghostwriting +gibberish +gibbon +gibing +giblet +giddily +gigabyte +giggles +gigolo +girdled +glamored +glamour +glassier +glazing +gleaned +glimmering +glimpse +glistened +globetrotters +globule +glories +glossary +glower +gluttonous +glycerine +gnashed +goalies +gobbler +godsends +goldbricking +golfed +gondoliers +gonged +gonorrhea +goslings +gossamer +gouges +goulash +governance +gowning +gracefully +grandee +grannies +grapnel +grateful +gratified +gratis +graying +greases +gregarious +grenadiers +greyhounds +grilled +grislier +gristlier +grossest +grottos +grouses +gruelings +grunted +guardrail +guessed +guesstimate +guidance +guided +guileful +gulled +gulling +gummed +gunboat +gunpowder +gushiest +gutters +guzzling +gymnastic +gynecology +haberdashery +habituates +hackneying +hackneys +haemophilia +haggled +hairbreadth +hairless +hairpiece +halberd +halftimes +hallelujahs +hallmarking +hamlets +hammed +hammered +hammers +handbags +handballs +handcraft +handcuffing +handedness +handicapper +handily +handing +handkerchiefs +handlebars +handling +handpicking +handshake +handstand +hangars +hanged +hangings +hankerings +harassing +hardcover +hardiest +harelip +harems +harmfully +harmonizes +harrowed +harvest +hashed +hastened +hatchbacks +haversacks +hawing +hayseed +headers +headland +headsets +headwinds +healthfully +hearkened +hearses +heartened +heartens +hearth +heaters +heaven +heavens +heckler +hedgerows +hedonistic +heehawed +heiress +heliotropes +helium +hellebore +hellion +helpmates +heppest +herbicide +hereditary +heretical +heroins +heroism +hibernating +hierarchical +hierarchy +highballs +highbrows +highjack +highjackers +hindquarter +hindrance +hippie +hirsute +historians +hitched +hitchhike +hitchhiker +hitchhikers +hitting +hoagie +hoarded +hobbling +hobgoblin +hobnailing +hockey +holdout +holdouts +holdover +hollowing +holography +homeland +homeopathy +homesickness +homogeneity +homogeneously +homogenization +homosexuals +honest +honeymooners +honorariums +hoodwink +hoofing +hoorayed +horticulturist +hosannas +hoteliers +householder +housemaid +housewares +hubcap +huffily +humanizer +humerus +humiliate +hungriest +hurrying +hurtle +hussies +hutches +hutzpa +hydraulic +hydrogenates +hydrology +hydroplane +hydroplanes +hyenas +hygienic +hyperventilated +hyphenations +hyphened +hypochondriac +hypochondriacs +hypoglycemia +hypothesize +hysterectomy +hysterical +hysterically +idealist +identically +identifying +idolatry +igniting +ignorant +illumined +illusive +illustrated +illustrator +imagining +imbalance +imbedded +imbibes +imitates +immediacy +immigration +immortally +impaired +impairment +impaneling +impanels +impediment +imperatively +imperiling +imperils +imperishable +impertinence +impinged +impingement +implacability +implant +imposingly +impound +imprimaturs +imprisonments +improperly +imputed +inaccessibility +inaccurately +inaction +inadequacy +inamorata +inaugural +inbred +inbreeds +incarcerations +incinerators +incisiveness +incite +incomes +inconstancy +incredulously +incriminate +incrusted +incurably +indecipherable +indentations +indestructible +indicatives +indicator +indictment +indigestion +indignant +indiscreetly +indisposition +indorsed +inducing +inductions +industrial +industrialism +inebriated +ineffectiveness +ineptitude +inessential +inessentials +inexorably +inextricable +infamous +inferior +infertility +inflames +inflatable +inflate +infomercial +informed +infringe +ingraining +ingratiatingly +inhabit +inhalation +inhalations +inheritors +initiates +injection +inkblots +inmates +inoperative +inputting +inquest +insecurities +insensitivity +insentient +instability +instances +instills +institutionalize +institutionalized +instrumentalist +insularity +insureds +intake +integrates +integrating +intelligence +intend +intensifiers +intercepted +interface +interfered +interjects +interleaved +interluding +internal +internalize +internationalism +interpret +interrogation +intersection +interviewees +interweaving +intriguingly +introduce +introverted +intrudes +inundate +inveighs +inveigle +inventive +invents +investment +invests +invitational +invoice +invoke +ionizing +ipecacs +irking +irrefutable +irregardless +irregular +irrelevancy +irresolute +irrespective +irretrievably +islands +isolated +isolating +italicizing +itemized +iterator +itinerary +jabbered +jackrabbits +jading +jamboree +jangle +jauntily +jaunting +jawbones +jazzier +jazziest +jeopardizes +jerkiest +jitney +jokers +jonquil +joshing +jounced +jounces +journalism +jovial +joyfully +joyriders +judgmental +juggler +juicers +juicing +junkie +junkier +justest +justify +juxtaposing +kamikaze +kangaroos +katydid +kayaking +keening +kenneling +kerosine +kettledrum +khakis +kibitzers +kickbacks +kicked +kickers +kickstand +kickstands +kielbasas +killdeers +killers +kilobyte +kindliness +kinematics +kisses +kitchen +kleptomania +kneads +knitters +knitwear +knobbier +knotted +knuckle +kookaburras +kopecks +laboratories +ladles +lallygagging +lamentably +lamming +lancers +landladies +landowner +languages +languishes +lapsed +laryngitis +lassies +lateraling +latterly +laudable +launderer +laundering +lavishest +lawless +lazies +league +learned +leased +leases +leaven +lectern +lecturing +leeches +leerier +leeriest +legatos +leggins +legislator +legislatures +leonine +lethally +letters +levitates +lexicographer +liability +liable +libeling +liberalization +liberally +libertine +librettos +licensed +licentiate +lieutenancy +lifespan +lightning +likeliest +likenesses +limelight +limousines +limpets +linage +linearly +linefeed +lingeringly +liniments +linnets +lionized +lisped +literals +livens +livestock +loader +loading +lobbed +lobbying +localizes +locket +locking +locust +lodges +logarithm +logbook +loggers +logistics +lollygags +longed +longingly +looked +looming +loonies +lordly +loudspeaker +loveable +loveliness +lowers +loyalty +lubricator +lucidness +lugubriously +lumberjacks +luminously +lunched +luncheon +lunges +luring +lusted +luxuriantly +luxury +lyceum +macing +macintoshes +macroscopic +mademoiselle +madras +madrigals +maggots +magnanimous +magnesia +magnetize +magnified +magnolia +magnolias +maharaja +maharajas +maharanee +maiming +majestic +making +maladjusted +malfunctions +mallows +manhandled +maniacal +manicured +manning +mantlepieces +marcher +margin +marginally +marigold +marihuana +marinade +marketed +marketer +marmalade +marquess +marquis +martini +martinis +marveling +marvels +masculines +mashed +masochism +masochists +massiveness +material +materialism +matures +maturities +matzot +maximal +mayors +mealier +mealtime +mealtimes +meandered +meanly +measurably +meatballs +mediaeval +mediation +meeting +mellower +meltdowns +member +members +membrane +menaces +menagerie +menopause +menorahs +meretricious +merganser +merged +merges +mermaids +merrymakers +metallurgical +metatarsals +meteorologist +methadon +method +mewing +miasma +microwaving +midmost +midterm +midyears +miffing +mightiest +migraines +migration +milepost +militia +milkman +milkshake +mimosas +mincing +mingled +minibike +minicomputers +minimalists +mining +minstrel +minstrels +misadventures +misanthropes +misapply +misconceive +misconstrue +miscounted +miscued +misdealt +misdiagnosis +misdoings +misfires +misfitted +misguiding +mishap +misidentified +misinterpretation +mislays +misogynist +misogynists +misprints +misrepresent +misrepresentations +missal +mistaken +mistiness +mistreating +misuses +mixture +mizzen +moccasin +mockingly +modernism +modernity +modernize +modulates +moisturizes +molder +moldier +molecular +molluscs +mollycoddles +mommas +monetary +moneymakers +mongoose +monicker +moniker +monkeyed +monkeys +monoliths +monolog +monopolizes +monosyllabic +monosyllables +monotony +moochers +mooned +moonshine +moonshines +moralizes +moratoriums +mordants +mortgagees +morticing +mortifying +moseys +mosques +mothballed +mothering +motherland +motivate +motivates +motivating +motocross +motorcar +motorists +motorized +motormouth +mountaineer +mountainside +mountebanks +mounted +mourned +mournful +mousses +mouthing +moving +muckiest +mucking +mudslingers +muezzin +muffin +muftis +muggers +muggiest +mulligatawny +multiplexors +multiplication +multiprocessing +multitude +multivariate +mumblers +munching +muralist +murders +murkiest +mushiness +mushing +musicology +muskmelon +mustered +mutability +muteness +muting +muzzled +myrtles +napalmed +narcissuses +narrating +nasalizing +national +nattily +naturalize +naturalizes +naturally +natures +navigate +necessaries +necessity +neckerchiefs +necklace +needles +nefarious +negligently +negligs +neighboring +nephew +nerves +neurotic +neuter +newscasters +newspapers +newsreel +nicknames +nicknaming +niftier +nightclubbing +nightingale +nightmare +nightshirt +nimblest +ninety +nobility +nobleness +nobler +noiselessly +noising +nominations +nonagenarians +nonempty +nonevents +nonexistence +nonobjective +nonpayment +nonrenewable +nonwhites +normalize +normalizing +northeast +northeastern +northeastward +notwithstanding +nuggets +nullify +numerating +numeric +nursed +nutmeats +nutted +objection +obscene +obscurest +observable +observing +obsessive +obstacle +obstruct +obtrudes +occlude +occluded +occluding +occupational +occurrences +oceanographic +oddity +odious +odometers +offenders +offends +offensiveness +offices +officials +officiate +offing +offsetting +offshoots +oilfields +oleanders +omelette +omnibus +omnivores +onlooker +operetta +oppresses +orbital +ordaining +orderliness +orientating +ornaments +ornate +ornerier +ornithologists +orphaning +orthodontics +orthogonal +oscillating +oscillators +osteoporosis +ounces +ousted +outbidding +outdistance +outfitter +outgoes +outlays +outnumbered +outnumbers +outplacement +outputted +outrageous +outriders +outselling +outshining +outsiders +outstretched +outvotes +outwitted +overacts +overate +overawes +overbearing +overcharged +overcome +overcompensation +overdose +overdoses +overexposed +overexposes +overexposing +overexposure +overextending +overheating +overpays +overpower +overpowered +overseer +oversees +overshoe +oversimplifications +overstay +overtaxes +overture +overweening +overwhelmingly +overworking +ownership +pachyderm +pacifier +packet +padding +padres +pageant +paintbrush +paintwork +pajamas +paleness +palest +palindromes +palladium +pallbearers +pallets +palmiest +palsying +pancake +pancreatic +pandemics +pandering +panelled +panoplies +panoply +pantheons +panthers +pantomimed +pantsuits +papergirls +parable +parachuting +paradoxically +paragraphing +parakeets +parallelisms +paralytic +parameter +parameters +paramilitary +paranoid +paranormal +paraphrasing +paraplegia +parboiling +pardoning +parented +parked +parkway +parlays +parquetry +parries +parrying +partake +particularity +particularization +particularizes +particularizing +partisanship +partnered +partook +passageway +passageways +passel +password +pasteurization +patents +paternal +patinae +patriarchy +patricides +patriot +patriotically +patronize +patronizingly +paunches +peaceably +peccaries +peccary +pectorals +peculiarly +pedagogical +peddler +peddlers +pedlars +peerless +pellets +pendulous +peninsula +penlites +pennies +pensioner +pensioning +pentagon +penthouse +penury +peppercorn +peppermint +pepperonis +peppier +perceivable +peregrinations +perennially +perfecter +perfectionists +perforation +performer +perfunctory +perilous +periodical +periodicals +peripatetic +peritoneum +perking +peroxided +perpetuate +perplexities +perseveres +personage +personify +persons +persuasively +perter +pervaded +petiole +pettifogged +petunia +petunias +phalanx +phalluses +pharmacopeia +philanderer +philter +phoebe +phonetics +phonic +photocopied +photographic +photography +phraseology +physicked +piazze +piccalilli +pickaxes +picketing +pickled +piddling +piffle +piggish +piggishness +piggyback +pilferer +pilling +pillory +pinnacle +pinochle +pinprick +pintos +pipped +piquing +pirouetted +pisses +pistachio +pistil +pistils +pistons +pitched +piteous +pitiable +pitiless +pitons +pivotal +pixels +pizzerias +placeholder +placentas +placer +placidly +plagiarism +plagiarizing +plague +plainclothesman +plainest +plaintiff +plaits +playgoer +playhouse +playpen +pleads +pleasing +pleasure +plenipotentiaries +plenitudes +plexus +pliancy +plinths +plodding +plowman +plowshare +pluming +plunderers +plunking +plural +plutocracies +plutocratic +plutocrats +plutonium +plying +pockmarked +poetically +poised +pokeys +police +poliomyelitis +politeness +pollinate +polliwog +pollute +pollywogs +polyhedra +polythene +pommel +poniards +pooched +poodle +portables +portage +portaged +portent +portly +portmanteaus +portray +portrays +positioned +positioning +possession +possessions +possessively +postdoc +postmarking +postmodern +postpaid +postscript +posture +postures +potboilers +potholders +potpies +potshots +pouches +poultices +powered +powerhouse +powwow +powwowing +practicability +practicably +practical +pranced +pranksters +preachier +precluded +precludes +preconceived +preconceives +predicates +predication +preexists +preferable +prefixed +prejudices +preliminary +preludes +prematurely +premeditating +premiere +premising +preordaining +prepackage +prepositions +prepossessed +prepossessing +preppie +prequels +presage +presaged +presages +prescience +presences +presentations +presents +presidents +pressing +presume +presupposes +preterit +preterits +prettified +prettifies +prevalence +prevaricated +prevaricating +preventing +prided +primly +primmer +printer +prisms +privater +privatization +privatized +privileges +prizefighting +proclivities +proclivity +procrastination +procreates +proctoring +procured +procuring +prodding +producing +professorships +profiling +profiteered +profiteering +profusely +profusions +programing +programmer +programmers +progression +prohibitory +projectile +proliferating +prolongations +promiscuous +promptest +prompts +pronouncements +proofs +propagandists +propagandized +propellent +propeller +propelling +propensity +properly +prophesied +prophylactics +propounds +prorates +proscriptions +proselytes +proselytizing +prosperous +protectiveness +protruding +protuberances +providence +provisional +provocatively +psyched +psychobabble +psychologists +psychopaths +psychotics +ptomaine +publicity +puddled +puffins +pullout +pulpits +pulsars +pulsate +pumice +pumpkin +pupils +pureed +purism +puritanical +purplest +pyromaniacs +quadraphonic +quadruplicating +quahogs +qualification +queenlier +queerer +questionable +questioned +questions +quicker +quicklime +quiescence +quietus +quilted +quintessences +quintuple +quirking +quitter +rabbited +raccoon +racial +racism +racketeered +radiotelephone +radium +raffles +raggedest +raggediest +ragtags +raining +rainmakers +raised +ramrodded +rancid +rancorous +ransom +ranting +rapport +rasher +raspberry +rations +rattlesnake +rattletraps +rattlings +razors +reachable +reaches +reactions +readied +reaffirms +reappoints +reason +reasons +reassemble +reassembles +reassured +rebind +rebuke +rebukes +recapitulating +recede +receipt +receives +recently +recess +recessions +recheck +rechecks +recipe +reciprocating +recoil +recoils +recompensed +recompenses +reconcile +reconciles +reconsidering +reconvening +recorder +recording +recount +recovering +recriminated +recriminating +recruiters +recruitment +recursion +redcoat +reddened +redeemed +redoes +redouble +redoubles +redounds +redrawn +redraws +reduction +redwood +reeducation +reefing +reelect +reenforced +reenlist +reexamine +refines +refocussed +refrigerates +refrigerating +refuelled +refurbish +refuse +refutation +regales +regency +regenerates +regimenting +regularized +rehabbed +rehashed +rehashes +rehired +reimburses +reimposed +reiterating +relabelling +relapsed +release +relentlessness +reliance +relocation +reluctant +remade +remand +remarks +remedied +remedies +remiss +remodel +remodels +remotely +remounting +removal +remunerating +renders +rendition +renegade +renegaded +renews +rental +rented +reoccupying +repairable +repeal +repeatedly +repellants +repellents +rephrasing +replacing +replaying +replete +replying +reposes +reprehends +represent +representation +repressed +reprieve +reprieving +reprise +reprises +reproofing +reptiles +repulsing +repulsiveness +requested +requirement +reread +resale +reschedule +reschedules +rescission +resentfully +resents +reserves +reside +residents +residue +resigns +resinous +resolves +resonates +restatement +restaurateur +restaurateurs +resulted +resumed +resurrecting +resuscitate +retards +retirements +retrain +retread +retried +retrievable +retrieving +retrogression +retrorocket +retrospectives +returns +revels +revere +reverencing +reversals +reversing +reviling +revise +revisiting +revivify +revocable +revolt +revolutionize +reworded +rewording +rework +rheumatic +ricocheting +riders +ridiculous +rifling +rightful +rigidly +rigors +riposted +ripping +ripsaw +ritzier +rivaling +rivalling +rivers +roadblocked +roadkill +rocking +roguery +rolled +romanticizes +rooter +rootless +rosier +rostra +rotates +rotational +rotundas +rotundity +roughhouse +roughing +roughnecked +roughs +roughshod +rounder +rouses +roustabouts +routed +rowdier +rowdies +rowdiest +royalty +rubber +rubbished +rubbishing +rubbishy +rubicund +rubier +rudimentary +ruggeder +ruggedest +rumbas +rumors +rundowns +rushes +russet +rustics +rustier +rustiest +rusting +rustle +rustproofs +saboteur +sachems +sacked +sacrilege +sadistically +saffrons +sailors +salads +salaries +salesmanship +salesmen +salines +salmonella +saloons +saltcellar +saltines +saluting +salvage +sanctimonious +sanctions +sandblaster +sandstone +sanserif +sarcastically +sartorial +sassafras +satinwood +satirizing +satisfies +sauted +savoriest +sawing +scalloped +scalpel +scalpers +scandalously +scanners +scapegoated +scapulae +scarecrow +scariest +scarify +scatted +scatterbrain +scavengers +schemes +scheming +scherzos +schoolbook +schoolboy +schoolmate +schoolroom +schoolrooms +scolloping +scorch +scorcher +scoreless +scoutmaster +scowls +scrabbled +scraggly +scrappiest +screwdrivers +screwy +scrimps +scrimshaw +scrimshawing +scrimshaws +scrolled +scrounging +scrupulously +scrutinized +seabeds +seaboard +seaman +seaming +seamless +seamstress +searching +seascapes +seasonally +seaweed +seaworthy +seclude +secluded +secularization +seductively +seedier +seediness +seeped +seesawed +segment +segmenting +seizure +semaphored +semiautomatic +semifinalists +semifinals +seminar +senses +sensibly +sensitize +sensually +sepals +separation +seraphic +serial +serialize +seriousness +serpent +served +service +serviceman +servos +sessions +settle +sevenths +seventieths +severely +sexagenarian +sexiest +shackle +shadowbox +shadowboxed +shakes +shakeups +shallowest +shallows +shambling +shammies +shards +sharking +shaven +shears +sheathe +shebangs +sheered +sheerest +shellac +sheltering +shelved +sheriffs +shillelagh +shilling +shimmy +shingled +shinier +shinning +shirking +shirks +shirttails +shittier +shittiest +shivers +shleps +shocks +shoddier +shoddily +shoehorned +shoehorning +shoeing +shoelace +shoeshine +shooters +shooting +shoplifter +shopped +shored +shoring +shortsightedness +should +shovelfuls +shovelled +showboated +shrewish +shucked +shuffles +shutterbug +shuttlecock +shyster +sickly +sideshows +siestas +signal +signifying +signposts +silencer +silences +silent +silliness +silverfishes +silvery +simplification +sinful +singletons +sinking +sirocco +sitars +sixteenth +sizable +skewering +skimpy +skirts +skylines +slaloming +slammed +slashed +slaughtering +slavish +sleazy +sledge +sledgehammer +sledges +sleepyhead +sleeted +sleeve +slenderest +slenderizes +slicer +slimmed +slinkiest +slipcover +sluing +slumbering +slumping +slurring +smacking +smallest +smelly +smidgen +smites +smoggiest +smokiest +smuttier +snickers +snider +sniped +snipes +snivelled +snored +snorers +snowballed +snowdrift +snowdrop +snowflake +snowmobile +snuffed +soaping +soapstone +sobered +sociability +socialite +sociologist +sociology +softeners +sojourn +soldierly +solely +solemn +solicitor +solicitous +solider +soliloquies +solitaire +somewhere +sophisticates +sophisticating +sorceress +sordidly +sorrow +soulfully +sourer +southbound +southwestern +spacesuits +spadeful +spades +spandex +spanking +speaking +specialization +spectator +spectroscopic +speculated +speculating +spellbinder +spelled +spellings +spendthrift +spermicides +spiking +spills +spillways +spinach +spindlier +spinier +spiniest +spinster +splashdowns +spleen +splice +splines +spoiled +spoilt +spokespeople +spokesperson +sponges +spooked +spoonfuls +sportscast +sportsmanship +spotter +sprawls +sprayed +sprightly +spring +sprinting +sprucer +sprucest +spryer +spryness +spurring +spurted +spurts +sputters +squash +squashy +squeezers +squint +stabilizer +stabled +stables +stagings +staircase +staircases +stalkings +stallions +stamping +stanch +stands +staphylococcus +stapler +starchiest +stared +starlings +stated +statehood +stateroom +statesmanlike +statue +statute +stauncher +staunchly +stayed +steeples +stemming +stencil +steppingstones +stepsisters +sterilized +sterner +stewarded +stewardess +stickpins +stiffen +stiffeners +stilettoes +stilettos +stilled +stimulated +stinkers +stockier +stodgiest +stomach +stomping +stoneware +stoniest +stooping +stoppage +storehouses +storey +straddled +straightforward +straightforwardly +straitened +strange +strangers +strangleholds +strapping +stratagems +strategic +strategist +streakiest +streetlights +strenuous +strews +stridden +strikeout +stringiest +stripe +strongboxes +structure +strudel +struggled +studies +sturdiest +stutterer +stylist +subbasement +subclass +subcompact +subdivided +subjugate +subjunctives +subleasing +submarines +submissive +subornation +subplot +subpoena +subscribed +substations +subsumed +subterranean +subtitled +subtle +subtractions +suburbanites +suburbans +suburbs +successions +succinct +suffering +suffixed +suffocate +suffocation +suffragettes +suicides +suitcases +suites +sulphured +sultrier +summations +sunglasses +sunroof +suntan +superabundances +superber +supercharged +supercharger +superhighways +superpowers +superscripts +supervision +supplant +suppositories +suppository +surfaced +surfacing +surges +surgical +surmised +surmises +surmounting +surplice +surprises +surrendered +surrogate +surround +survived +suspends +suspense +suspension +suspensions +swains +swapped +swarming +swarthiest +swashes +swatted +sweatshop +swellings +swelter +swelters +swerve +swiftest +swinger +switchbacks +switchboards +swords +sycophant +syllabify +syllabus +symbioses +symbolically +symmetrical +symptoms +synagogs +synched +syndromes +synopses +synthesizer +synthetic +syphilis +syphoning +tabloids +tackles +tackling +tadpoles +tailspin +tallness +tameable +tangential +tangos +tanned +tapioca +tariffs +tarnish +tarots +tarpons +tastelessly +tatters +tattles +tattletales +tattoo +taxonomic +taxying +teabag +technicality +technological +technology +teleconference +telegraphy +telemetries +telepathically +telepathy +telephony +telephoto +telethon +televise +televised +telexes +temperas +tempestuous +template +templates +temporary +temporized +temporizes +tempted +tenable +tenacious +tenancies +tenancy +tenoning +tenser +tensing +tentacles +tenuous +terminally +termly +terrorizes +testier +testiness +tetrahedrons +textbook +thankless +theatrical +theologies +theorems +theoretic +therapists +thereabouts +therein +therewith +thesis +thickened +thimbleful +thinker +thinning +thirtieth +thistle +thoraces +thorny +thoughtful +thoughtfully +thraldom +thread +threes +throes +throne +thronging +throttles +thunder +thwarted +tiddlywinks +tidying +tieing +tightened +tightropes +timbering +timekeeper +timetable +timetabled +timing +tinkle +tinselled +tinsmiths +tipper +tippler +tireless +tiring +titillating +titled +toadstool +toasts +toddler +toddling +toffees +toileted +tollgate +tomahawked +tomatoes +tombstone +topics +topographies +topped +topsides +torpedoes +totter +tougher +toughly +towheaded +townsmen +towpaths +toxemia +tracheas +tracing +tractors +trademarking +tradesmen +trammed +trampling +trampoline +trampolines +tranquilizer +tranquillizing +transaction +transcript +transferable +transfers +transformed +translation +translators +transpired +transponder +trapezoids +trappable +treacheries +treatise +treaty +trekking +trembles +tremulous +trenches +trepidation +triage +tribalism +tribunals +trickery +trickling +trimming +trinity +trisect +triter +trivial +trochee +troubadours +troublemaker +trounced +troupes +trouser +troweled +truancy +truffle +trusting +tuberculous +tuberous +tubular +tufted +tufting +tumbrils +tunnies +turnabout +turnpikes +turquoises +turtledoves +turtlenecks +tussle +tussocks +tutorial +twaddles +tweaking +tweediest +twelfth +twenties +twerps +twigging +twisted +twittered +twitting +typecasts +tyrannical +tyrannosauruses +tzarina +ubiquity +ugliness +umbilici +umbilicus +umpiring +umpteen +unanimous +unaware +unbeliever +unbend +unbolts +unbounded +unbreakable +unbuckle +unburden +unbutton +uncensored +uncharacteristic +uncleaner +unclothe +unclothed +unconvincingly +uncooperative +uncork +uncouth +uncover +uncritical +undefined +underachieved +underachieving +underacts +undercurrents +underdogs +underexposes +underfeed +underlines +underlining +underpay +undersecretary +underside +understandable +undulated +uneasily +uneconomic +unenthusiastic +unexpected +unexpectedly +unfetter +unfilled +unfurled +unfurling +ungainlier +unguents +unhealthier +unhelpful +unhinge +unified +uniforming +uninitialized +uninstaller +unjustly +unlatched +unlatching +unleashes +unleashing +unmake +unmasked +unmentionables +unmodified +unobserved +unopposed +unpaid +unpleasantness +unpredictability +unprepared +unprompted +unprotected +unprovoked +unquenchable +unreadier +unreasonableness +unrecognizable +unreliability +unremarkable +unrewarding +unruliness +unscrambling +unseeing +unshaven +unsightliness +unskilled +unsnapping +unsnaps +unsubscribing +unsuccessful +untaught +untiringly +unused +unveil +upfront +upholstered +uprising +uproariously +uranium +urbaner +urbanized +urbanizing +uselessness +usurpation +usurpers +uterine +utters +uvulars +vacuity +vacuums +vagrant +vainglorious +valiantly +validates +valleys +vantages +vaporizing +variations +vatting +vaulter +vaulters +vaunts +vegetarianism +vendor +veneer +venial +ventured +veracity +verbalize +verbalized +verbalizing +verily +vermin +vexatious +victimizing +videodisc +viewed +viewings +vigilante +vilified +villainous +villein +vintages +violate +virtually +visaed +visage +viscountess +visioning +visual +vitiating +viticulture +vocalization +vocations +vocative +vociferates +voiding +voracious +vouchsafing +waiver +waiving +walked +wallboard +wallflowers +walrus +wampum +warbled +warehousing +warmly +warned +warping +warrants +warrens +warthogs +washable +washbowl +washcloths +wasters +wasting +watchfulness +waterfall +wattled +waveform +waxwings +weakens +weaned +webbed +wedding +weeder +weediest +weeper +weepiest +weighed +weirdness +welders +wellsprings +westerners +wetted +wheelbarrows +whetted +whiled +whiling +whimsical +whiniest +whining +whinnying +whipping +whirligig +whirlwinds +whispers +whistling +whitecaps +whitening +whoever +wholesalers +whorls +wickers +wickets +widths +wifelier +wiggles +wildfowl +wiling +willfully +windjammer +windowsills +windscreen +winged +wingless +wingtip +winterier +wiseacres +wisecrack +wisecracking +wishes +wispier +wispiest +withering +withers +withstanding +wizards +wobbled +woefuller +wolfhound +wondrous +wonted +woodier +woodpile +woofer +woofing +woolen +woolies +workings +workmanlike +wormier +worryings +worshipers +worshipping +worthy +wounded +wreathes +wrenched +wrested +wrestler +wrinkling +writer +wrongheadedly +yachted +yammer +yammered +yawing +yearlings +yelled +yessing +yipping +yodelers +yummiest +zealously +zephyr +zeroing +zestfully +zigzags +zircons +zodiac +zoological diff --git a/devel-server.py b/devel-server.py index 732a87b..e280ffb 100755 --- a/devel-server.py +++ b/devel-server.py @@ -8,9 +8,9 @@ import pathlib import puzzles import socketserver -if hasattr(http.server, 'HTTPStatus'): - HTTPStatus = http.HTTPStatus -else: +try: + from http.server import HTTPStatus +except ImportError: class HTTPStatus: NOT_FOUND = 404 OK = 200 @@ -30,6 +30,7 @@ def page(title, body): """.format(title, body) + def mdpage(body): try: title, _ = body.split('\n', 1) @@ -43,6 +44,7 @@ def mdpage(body): class ThreadingServer(socketserver.ThreadingMixIn, http.server.HTTPServer): pass + class MothHandler(http.server.CGIHTTPRequestHandler): def do_GET(self): if self.path == "/": @@ -142,6 +144,7 @@ you are a fool. self.end_headers() self.wfile.write(content.encode('utf-8')) + def run(address=('', 8080)): httpd = ThreadingServer(address, MothHandler) print("=== Listening on http://{}:{}/".format(address[0] or "localhost", address[1])) diff --git a/puzzles.py b/puzzles.py index e844a00..5b057d6 100644 --- a/puzzles.py +++ b/puzzles.py @@ -1,37 +1,105 @@ #!/usr/bin/python3 import argparse -import base64 +from collections import defaultdict, namedtuple import glob -import hmac -import json +import hashlib +from importlib.machinery import SourceFileLoader import mistune -import multidict import os import random +import tempfile messageChars = b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' + def djb2hash(buf): h = 5381 for c in buf: h = ((h * 33) + c) & 0xffffffff return h -class Puzzle(multidict.MultiDict): +# We use a named tuple rather than a full class, because any random name generation has +# to be done with Puzzle's random number generator, and it's cleaner to not pass that around. +PuzzleFile = namedtuple('PuzzleFile', ['path', 'handle', 'name', 'visible']) - def __init__(self, seed): +class Puzzle: + + KNOWN_KEYS = [ + 'file', + 'resource', + 'temp_file', + 'answer', + 'points', + 'author', + 'summary' + ] + REQUIRED_KEYS = [ + 'author', + 'answer', + 'points' + ] + SINGULAR_KEYS = [ + 'points' + ] + + # Get a big list of clean words for our answer file. + ANSWER_WORDS = [w.strip() for w in open(os.path.join(os.path.dirname(__file__), + 'answer_words.txt'))] + + def __init__(self, path, category_seed): super().__init__() + self._dict = defaultdict(lambda: []) + if os.path.isdir(path): + self._puzzle_dir = path + else: + self._puzzle_dir = None self.message = bytes(random.choice(messageChars) for i in range(20)) self.body = '' - self.rand = random.Random(seed) + if not os.path.exists(path): + raise ValueError("No puzzle at path: {]".format(path)) + elif os.path.isfile(path): + try: + # Expected format is path/.moth + self['points'] = int(os.path.split(path)[-1].split('.')[0]) + except (IndexError, ValueError): + raise ValueError("Invalid puzzle config. " + "Expected something like .moth") - @classmethod - def from_stream(cls, stream): - pzl = cls(None) + stream = open(path) + self._read_config(stream) + elif os.path.isdir(path): + try: + # Expected format is path/.moth + self['points'] = int(os.path.split(path)[-1]) + except (IndexError, ValueError): + raise ValueError("Invalid puzzle config. Expected an integer point value for a " + "directory name.") + files = os.listdir(path) + + if 'config.moth' in files: + self._read_config(open(os.path.join(path, 'config.moth'))) + + if 'make.py' in files: + # Good Lord this is dangerous as fuck. + loader = SourceFileLoader('puzzle_mod', os.path.join(path, 'make.py')) + puzzle_mod = loader.load_module() + if hasattr(puzzle_mod, 'make'): + puzzle_mod.make(self) + else: + raise ValueError("Unacceptable file type for puzzle at {}".format(path)) + + self._seed = hashlib.sha1(category_seed + bytes(self['points'])).digest() + self.rand = random.Random(self._seed) + + # Set our 'files' as a dict, since we want register them uniquely by name. + self['files'] = dict() + + def _read_config(self, stream): + """Read a configuration file (ISO 2822)""" body = [] header = True for line in stream: @@ -43,31 +111,119 @@ class Puzzle(multidict.MultiDict): key, val = line.split(':', 1) key = key.lower() val = val.strip() - pzl.add(key, val) + self[key] = val else: body.append(line) - pzl.body = ''.join(body) - return pzl + self.body = ''.join(body) + + def random_hash(self): + """Create a random hash from our number generator suitable for use as a filename.""" + return hashlib.sha1(str(self.rand.random()).encode('ascii')).digest() + + def _puzzle_file(self, path, name, visible=True): + """Make a puzzle file instance for the given file. + :param path: The path to the file + :param name: The name of the file. If set to None, the published file will have + a random hash as a name and have visible set to False. + :return: + """ + + # Make sure it actually exists. + if not os.path.exists(path): + raise ValueError("Included file {} does not exist.") + + file = open(path, 'rb') + + return PuzzleFile(path=path, handle=file, name=name, visible=visible) + + def make_file(self, name=None, mode='rw+b'): + """Get a file object for adding dynamically generated data to the puzzle. + :param name: The name of the file for links within the puzzle. If this is None, + the file will be hidden with a random hash as the name. + :return: A file object for writing + """ + + file = tempfile.TemporaryFile(mode=mode, delete=False) + + self._dict['files'].append(self._puzzle_file(file.name, name)) + + return file + + def __setitem__(self, key, value): + + if key in ('file', 'resource', 'hidden') and self._puzzle_dir is None: + raise KeyError("Cannot set a puzzle file for single file puzzles.") - def add(self, key, value): - super().add(key, value) if key == 'answer': - super().add(hash, djb2hash(value.encode('utf8'))) + # Handle adding answers to the puzzle + self._dict['hashes'].append(djb2hash(value.encode('utf8'))) + self._dict['answers'].append(value) + elif key == 'file': + # Handle adding files to the puzzle + path = os.path.join(self._puzzle_dir, 'files', value) + self._dict['files'][value] = self._puzzle_file(path, value) + elif key == 'resource': + # Handle adding category files to the puzzle + path = os.path.join(self._puzzle_dir, '../res', value) + self._dict['files'].append(self._puzzle_file(path, value)) + elif key == 'hidden': + # Handle adding secret, 'hidden' files to the puzzle. + path = os.path.join(self._puzzle_dir, 'files', value) + name = self.random_hash() + self._dict['files'].append(self._puzzle_file(path, name, visible=False)) + elif key in self.SINGULAR_KEYS: + # These keys can only have one value + self._dict[key] = value + elif key in self.KNOWN_KEYS: + self._dict[key].append(value) + else: + raise KeyError("Invalid Attribute: {}".format(key)) + + def __getitem__(self, item): + return self._dict[item] + + def make_answer(self, word_count, sep=b' '): + """Generate and return a new answer. It's automatically added to the puzzle answer list. + :param int word_count: The number of words to include in the answer. + :param str|bytes sep: The word separator. + :returns: The answer bytes + """ + + if type(sep) == str: + sep = sep.encode('ascii') + + answer = sep.join(self.rand.sample(self.ANSWER_WORDS, word_count)) + self['answer'] = answer + + return answer + def htmlify(self): return mistune.markdown(self.body) - def publish(self): + def publish(self, dest): + """Deploy the puzzle to the given directory, and return the info needed for describing + the puzzle and accepting answers in MOTH.""" + + if not os.path.exists(dest): + raise ValueError("Puzzle destination directory does not exist.") + + # Delete the original directory + + # Save puzzle html file + + # Copy over all the files. + obj = { 'author': self['author'], - 'hashes': self.getall('hash'), + 'hashes': self['hashes'], 'body': self.htmlify(), } return obj def secrets(self): obj = { - 'answers': self.getall('answer'), + 'answers': self['answers'], 'summary': self['summary'], } return obj @@ -84,7 +240,7 @@ if __name__ == '__main__': filename = os.path.basename(puzzlePath) points, ext = os.path.splitext(filename) points = int(points) - puzzle = Puzzle.from_stream(open(puzzlePath)) + puzzle = Puzzle(puzzlePath, "test") puzzles[points] = puzzle for points in sorted(puzzles):