func pinyinifyLookupHandler(writer http.ResponseWriter, request *http.Request) { text := getLastPathComponent(request) charSet := cedict.DetermineCharSet(text) splitText, err := chinese.SplitChineseTextIntoWords(text, charSet) if err != nil { fmt.Fprint(writer, `{"error": "`+err.Error()+`}`) return } output := "" for _, word := range splitText { records, _ := cedict.FindRecords(word, charSet) if len(records) > 0 { output += records[0].Pinyin } else { output += word } output += " " } j, err := json.Marshal(map[string]interface{}{ "error": "nil", "result": output, }) if err != nil { fmt.Fprint(writer, `{"error": "`+err.Error()+`}`) return } fmt.Fprint(writer, string(j)) }
func findMoeEntriesForWords(words []string, charSet chinese.CharSet) ([]moedict.Entry, error) { moeEntries := make([]moedict.Entry, 0) // TODO explain diff. between trad and simp if charSet == chinese.Trad { for _, word := range words { entry, err := moedict.FindEntry(word) if err != nil { return nil, err } if entry != nil { moeEntries = append(moeEntries, *entry) } } } // if the sentences is in simplified characters, find cedict records first // (there may be multiple records per word) and find moedict records using // the traditional word of the cedict records. if charSet == chinese.Simp { for _, word := range words { records, err := cedict.FindRecords(word, chinese.Simp) if err != nil { return nil, err } individualRecords := make([]cedict.Record, 0) for _, r := range records { recordInSlice := false for _, ir := range individualRecords { if r.Trad == ir.Trad { recordInSlice = true } } if !recordInSlice { individualRecords = append(individualRecords, r) } } for _, record := range individualRecords { entry, err := moedict.FindEntry(record.Trad) if err != nil { return nil, err } if entry != nil { moeEntries = append(moeEntries, *entry) } } } } return moeEntries, nil }
// This function is responsible for paths of the form // /vocab/lookup/<word> and returns a json dictionary // containing the csv to be added to the output text area // or an "error" field of something other than "nil" if an // error occured during execution. func vocabLookupHandler(writer http.ResponseWriter, request *http.Request) { word := getLastPathComponent(request) colors := getColors(request) fmt.Println("vocabLookupHandler: " + word) // search the db for records (simp first, if unsuccessful, try trad) // and send errors back to client if any occur records, err := cedict.FindRecords(word, chinese.Simp) if err != nil { fmt.Fprint(writer, `{"error": "`+err.Error()+`", "word": "`+word+`"}`) return } if len(records) == 0 { records, err = cedict.FindRecords(word, chinese.Trad) if err != nil { fmt.Fprint(writer, `{"error": "`+err.Error()+`", "word": "`+word+`"}`) return } } if len(records) == 0 { fmt.Fprint(writer, `{"error": "No matches found", "word": "`+word+`"}`) return } // this string has the same number of characters as the word. // in places where the simplified and the traditional characters // are the same, it has a space, otherwise it has the simplified character simpChars := "" tradChars := "" for is, cs := range records[0].Simp { for it, ct := range records[0].Trad { if is == it { if cs == ct { simpChars += string('\u3000') tradChars += string('\u3000') } else { simpChars += string(cs) tradChars += string(ct) } } } } // construct csv row var output string output += records[0].Trad output += "\t" output += records[0].Simp output += "\t" // This dot is necessary because Anki trims whitespace when importing. // For more details, see the card layout of the shengci deck output += "." + tradChars output += "\t" output += "." + simpChars output += "\t" for _, record := range records { output += pinyin.Num2DiaCol(record.Pinyin, colors, " ") // Add another real space character at the end // to make the line break between pinyin and definition on small screens output += " " output += record.English output += "<br />" } // use json.Marshal with an anonymous variable to escape the \t and " characters // in the response j, err := json.Marshal(map[string]interface{}{ "error": "nil", "csv": output, }) if err != nil { fmt.Fprint(writer, `{"error": "`+err.Error()+`", "word": "`+word+`"}`) return } fmt.Fprint(writer, string(j)) }
func mcdsLookupHandler(writer http.ResponseWriter, request *http.Request) { text := getLastPathComponent(request) text = strings.Replace(text, "@SLASH@", "/", -1) text = strings.Replace(text, "\n", "<br />", -1) text = strings.Replace(text, "\t", " ", -1) notes := request.FormValue("notes") notes = strings.Replace(notes, "@SLASH@", "/", -1) notes = strings.Replace(notes, "\n", "<br />", -1) notes = strings.Replace(notes, "\t", " ", -1) charsRaw := request.FormValue("chars") charsArrayRaw := strings.Split(charsRaw, " ") // Construct new slice without empty strings chars := make([]string, 0) for _, char := range charsArrayRaw { if char != "" { chars = append(chars, char) } } colors := getColors(request) charSet := cedict.DetermineCharSet(text) splitText, err := chinese.SplitChineseTextIntoWords(text, charSet) if err != nil { fmt.Fprint(writer, `{"error": "`+err.Error()+`}`) return } var output string // Go through all chars to be clozed. Every iteration adds one line to the output var (i.e. one card) for _, char := range chars { var front, back string wordsToBeLookedUp := make([]string, 0) // This loop goes through all words in the text. This could be optimised by only going // through the text once and constructing all cards simultaneously for _, wordInText := range splitText { indexOfChar := strings.Index(wordInText, char) if indexOfChar == -1 { front += wordInText back += wordInText } else { front += strings.Replace(wordInText, char, clozeBegin+clozeChar+clozeEnd, -1) back += strings.Replace(wordInText, char, clozeBegin+char+clozeEnd, -1) wordsToBeLookedUp = append(wordsToBeLookedUp, wordInText) } } // Fine unique words to be looked up in moedict wordsToBeLookedUnique := make([]string, 0) for _, word := range wordsToBeLookedUp { alreadyInWordsToBeLookedUpUnique := false for _, wordUnique := range wordsToBeLookedUnique { if word == wordUnique { alreadyInWordsToBeLookedUpUnique = true } } if !alreadyInWordsToBeLookedUpUnique { wordsToBeLookedUnique = append(wordsToBeLookedUnique, word) } } cedictRecords := make([]cedict.Record, 0) for _, wordToBeLookedUpInCedict := range wordsToBeLookedUnique { records, _ := cedict.FindRecords(wordToBeLookedUpInCedict, charSet) for _, record := range records { cedictRecords = append(cedictRecords, record) } } moeEntries, err := findMoeEntriesForWords(wordsToBeLookedUnique, charSet) if err != nil { fmt.Fprint(writer, `{"error": "`+err.Error()+`}`) return } output += front output += "\t" output += back output += "\t" output += notes output += "\t" for _, moeEntry := range moeEntries { output += moeEntry.ToHTML(colors) output += "<br>" } output += "\t" for _, cr := range cedictRecords { output += cr.ToHTML(colors) output += "<br>" } output += "\n" } // TODO turn this into a function // use json.Marshal with an anonymous variable to escape the \t and " characters // in the response j, err := json.Marshal(map[string]interface{}{ "error": "nil", "result": output, }) if err != nil { fmt.Fprint(writer, `{"error": "`+err.Error()+`}`) return } fmt.Fprint(writer, string(j)) }
func sentencesLookupHandler(writer http.ResponseWriter, request *http.Request) { sentence := getLastPathComponent(request) colors := getColors(request) fmt.Println("sentencesLookupHandler: " + string([]rune(sentence)[0:10]) + "。。。") // get words in sentence wordsRaw := findWordsInSentencesRegexp.FindAllStringSubmatch(sentence, -1) words := make([]string, len(wordsRaw)) for i, w := range wordsRaw { words[i] = w[1] } charSet := cedict.DetermineCharSet(sentence) moeEntries, err := findMoeEntriesForWords(words, charSet) if err != nil { fmt.Fprint(writer, `{"error": "`+err.Error()+`", "sentence": "`+sentence+`"}`) return } cedictRecords := make([]cedict.Record, 0) for _, word := range words { records, err := cedict.FindRecords(word, charSet) if err != nil { fmt.Fprint(writer, `{"error": "`+err.Error()+`", "sentence": "`+sentence+`"}`) return } for _, record := range records { cedictRecords = append(cedictRecords, record) } } // construct csv row var output string var outputSentence string outputSentence = strings.Replace(sentence, "[", "", -1) outputSentence = strings.Replace(outputSentence, "]", "", -1) output += outputSentence output += "\t" for _, moeEntry := range moeEntries { output += moeEntry.ToHTML(colors) output += "<br>" } output += "\t" for _, cedictRecord := range cedictRecords { output += cedictRecord.ToHTML(colors) output += "<br>" } // This adds an additional field for the audio file output += "\t" // This is necessary for Anki to recognise all fields output += " " // TODO turn this into a function // use json.Marshal with an anonymous variable to escape the \t and " characters // in the response j, err := json.Marshal(map[string]interface{}{ "error": "nil", "csv": output, }) if err != nil { fmt.Fprint(writer, `{"error": "`+err.Error()+`", "sentence": "`+sentence+`"}`) return } fmt.Fprint(writer, string(j)) }