From 553b89cfe0136be3bb004503c12dd5efb2c9f5b7 Mon Sep 17 00:00:00 2001 From: Zorchenhimer Date: Sat, 20 Feb 2021 21:18:26 -0500 Subject: [PATCH] Implement consumeNewWord() Implement the consumeNewWord() method that will handle new words defined in format strings enclosed in double curly braces. The format is as follows: {{word_type:word:options,list}} The notable difference between this and the other definitions is that only verbs and nouns are allowed to be defined this way. Additionally only regular verbs and nouns are allowed (the "irregular" option is ignored). A new sentence has been added that utilizes this new function. Lastly, some of the option parsing code for verbs and nouns has been separated into their own functions so it can be reused between both consumeWord() and consumeNewWord(). --- english.go | 186 ++++++++++++++++++++++++++++++++++++++---------- word_lists.json | 3 +- 2 files changed, 150 insertions(+), 39 deletions(-) diff --git a/english.go b/english.go index 5abfecf..0f73945 100644 --- a/english.go +++ b/english.go @@ -21,6 +21,8 @@ type InitialData struct { type english struct { db database.DB + + currentPronoun string } func NewEnglish(db database.DB) (HackerQuotes, error) { @@ -35,12 +37,15 @@ func NewEnglish(db database.DB) (HackerQuotes, error) { {{word_type:new word:properties}} {pronoun} can't {verb:i,present} {noun_phrase}, it {verb:it,future} {noun_phrase}! - {verb:you,present} {noun_phrase:definite}, then you can {verb:you,present} {noun_phrase:definite}! + {verb:you,present} {noun_phrase:indefinite}, then you can {verb:you,present} {noun_phrase:definite}! {noun_phrase} {verb}. With {noun_phrase:indifinite,noadj,compound}! + + {pronoun} {{verb:need:from_pronoun,present}} to {verb:i,present} {noun_phrase:definite}! */ func (g *english) Hack() (string, error) { //var fmtString string = `{verb:you,present} {noun_phrase:definite} then you can {verb:you,present} {noun_phrase:definite}!` + //var str string = `{pronoun} {{verb:need:from_pronoun,present}} to {verb:i,present} {noun_phrase:definite}!` str, err := g.randomSentence() if err != nil { return "", err @@ -54,6 +59,7 @@ func (g *english) HackThis(fmtString string) (string, error) { var err error var nidx int output := &strings.Builder{} + g.currentPronoun = "" for idx < len(fmtString) { if fmtString[idx] == '{' { @@ -95,8 +101,145 @@ func (g *english) consumeRaw(fmtString string, idx int, output *strings.Builder) return idx+end, nil } +func (g *english) parseVerbOptions(optlist []string) (models.ConjugationType, models.ConjugationTime, bool) { + var ct models.ConjugationType = models.ConjugationType(rand.Intn(5) + 1) + if sliceContains(optlist, "i") { + ct = models.CT_I + } else if sliceContains(optlist, "you") { + ct = models.CT_You + } else if sliceContains(optlist, "it") { + ct = models.CT_It + } else if sliceContains(optlist, "we") { + ct = models.CT_We + } else if sliceContains(optlist, "they") { + ct = models.CT_They + } + + var cm models.ConjugationTime = models.ConjugationTime(rand.Intn(3) + 1) + if sliceContains(optlist, "present") { + cm = models.CM_Present + } else if sliceContains(optlist, "past") { + cm = models.CM_Past + } else if sliceContains(optlist, "future") { + cm = models.CM_Future + } + + var invert bool = rand.Int() % 2 == 0 + if sliceContains(optlist, "invert") { + invert = true + } + + //var regular bool = true + //if sliceContains(optlist, "irregular") { + // regular = false + //} + + if sliceContains(optlist, "from_pronoun") { + switch g.currentPronoun { + case "he", "she", "it": + ct = models.CT_It + case "i": + ct = models.CT_I + case "you": + ct = models.CT_You + case "we": + ct = models.CT_We + case "they": + ct = models.CT_They + } + } + + return ct, cm, invert +} + +func (g *english) parseNounOptions(optlist []string) (bool, bool) { + var plural bool = rand.Int() % 2 == 0 + if sliceContains(optlist, "plural") { + plural = true + } else if sliceContains(optlist, "singular") { + plural = false + } + + var compound bool = rand.Int() % 2 == 0 + if sliceContains(optlist, "compound") { + plural = true + } else if sliceContains(optlist, "simple") { + plural = false + } + + return plural, compound +} + func (g *english) consumeNewWord(fmtString string, idx int, output *strings.Builder) (int, error) { - return 0, fmt.Errorf("not implemented") + idx += 2 + var wordtype string + var word string + var options string + + end := strings.Index(fmtString[idx:], "}") + if end == -1 { + return 0, fmt.Errorf("[consumeNewWord] Unclosed definition starting at %d", idx) + } + end += idx + + // Find the start of the new word + def := strings.Index(fmtString[idx:], ":") + if def == -1 { + return 0, fmt.Errorf("[consumeNewWord] Word definition missing word") + } + def += idx + wordtype = fmtString[idx:def] + + // Find the start of the options + opts := strings.Index(fmtString[def+1:], ":") + + if opts > -1 { + opts += def+2 + options = fmtString[opts:end] + word = fmtString[def+1:opts-1] + } else { + word = fmtString[def+1:end] + } + + //fmt.Printf("idx:%d def:%d opts:%d end:%d type:%q word:%q opts:%q\n", + // idx, def, opts, end, + // wordtype, + // word, + // options) + + optlist := strings.Split(options, ",") + var formatted string + switch wordtype { + case "verb": + ct, cm, invert := g.parseVerbOptions(optlist) + + v := models.Verb{ + Regular: true, + Word: word, + } + + formatted = v.Conjugate(ct, cm, invert) + + case "noun": + plural, _ := g.parseNounOptions(optlist) + + if plural { + n := models.Noun{ + Regular: true, + Word: word, + } + formatted = n.Plural() + } else { + formatted = word + } + + default: + // Pronouns and adjectives aren't implemented because they have no modifications to apply. + return 0, fmt.Errorf("Word type %q not implemented creating in-sentence", wordtype) + } + + output.WriteString(formatted) + return end+2, nil } func (g *english) consumeWord(fmtString string, idx int, output *strings.Builder) (int, error) { @@ -138,34 +281,10 @@ func (g *english) consumeWord(fmtString string, idx int, output *strings.Builder if err != nil { return 0, err } + g.currentPronoun = word case "verb": - var ct models.ConjugationType = models.CT_I - if sliceContains(opts, "i") { - ct = models.CT_I - } else if sliceContains(opts, "you") { - ct = models.CT_You - } else if sliceContains(opts, "it") { - ct = models.CT_It - } else if sliceContains(opts, "we") { - ct = models.CT_We - } else if sliceContains(opts, "they") { - ct = models.CT_They - } - - var cm models.ConjugationTime = models.CM_Present - if sliceContains(opts, "present") { - cm = models.CM_Present - } else if sliceContains(opts, "past") { - cm = models.CM_Past - } else if sliceContains(opts, "future") { - cm = models.CM_Future - } - - var invert bool = false - if sliceContains(opts, "invert") { - invert = true - } + ct, cm, invert := g.parseVerbOptions(opts) word, err = g.randomVerb(ct, cm, invert) if err != nil { @@ -173,16 +292,7 @@ func (g *english) consumeWord(fmtString string, idx int, output *strings.Builder } case "noun": - var plural bool - var compound bool - - if sliceContains(opts, "plural") { - plural = true - } - - if sliceContains(opts, "compound") { - compound = true - } + plural, compound := g.parseNounOptions(opts) word, err = g.randomNoun(plural, compound) if err != nil { diff --git a/word_lists.json b/word_lists.json index 12b8dc9..066eeca 100644 --- a/word_lists.json +++ b/word_lists.json @@ -418,6 +418,7 @@ "sentences": [ "{pronoun} can't {verb:i,present} {noun_phrase}, it {verb:it,future} {noun_phrase}!", "{verb:you,present} {noun_phrase:definite}, then you can {verb:you,present} {noun_phrase:definite}!", - "{noun_phrase:it,past} {verb}. With {noun_phrase:indifinite,noadj,compound}!" + "{noun_phrase:it,past} {verb}. With {noun_phrase:indifinite,noadj,compound}!", + "{pronoun} {{verb:need:from_pronoun,present}} to {verb:i,present} {noun_phrase:definite}!" ] }