penguin/golifehk

@golifehk bot in Telegram

datasources/cjlookup/maps.go

raw ยท 3517 bytes

package cjlookup

import (
	"bufio"
	"encoding/csv"
	utils "github.com/tgckpg/golifehk/utils"
	"io"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

var TXT_CANGJIE_KEYS string = filepath.Join(utils.STATIC_DIR, "cangjie.keys.txt")
var YAML_CANGJIE5_DICT string = filepath.Join(utils.STATIC_DIR, "cangjie5.dict.yaml")
var YAML_JYUTPING_CHARS string = filepath.Join(utils.STATIC_DIR, "jyut6ping3.chars.dict.yaml")

func ReadCangJieKeys() (*strings.Replacer, error) {
	f, err := os.Open(TXT_CANGJIE_KEYS)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	r := csv.NewReader(f)
	r.Comma = '\t'
	r.FieldsPerRecord = -1

	cjKeymap := []string{}

	for {
		record, err := r.Read()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatal(err)
		}

		cjKeymap = append(cjKeymap, record[0])
		cjKeymap = append(cjKeymap, record[1])
	}

	return strings.NewReplacer(cjKeymap...), nil
}

func ReadCangJieTable(charMap map[string]*CChar, repl *strings.Replacer) error {

	f, err := os.Open(YAML_CANGJIE5_DICT)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	br := bufio.NewReader(f)

	// Skip until YAML document end
	for {
		line, err := br.ReadString('\n')
		if err != nil {
			return err
		}
		if strings.TrimSpace(line) == "..." {
			break
		}
	}

	r := csv.NewReader(br)
	r.Comma = '\t'
	r.FieldsPerRecord = -1

	for {
		record, err := r.Read()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatal(err)
		}

		face := record[0]
		if c, ok := charMap[face]; ok {
			c.Face = face
			c.CangJie = repl.Replace(record[1])
		} else {
			c := CChar{}
			c.Face = face
			c.Key = &c.Face
			c.CangJie = repl.Replace(record[1])
			charMap[face] = &c
		}
	}

	return nil
}

func ReadJyutPingTable(charMap map[string]*CChar) (map[string]*CJyutPing, error) {
	f, err := os.Open(YAML_JYUTPING_CHARS)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	br := bufio.NewReader(f)

	// Skip until YAML document end
	for {
		line, err := br.ReadString('\n')
		if err != nil {
			return nil, err
		}
		if strings.TrimSpace(line) == "..." {
			break
		}
	}

	r := csv.NewReader(br)
	r.Comma = '\t'
	r.FieldsPerRecord = -1

	JyutPingMap := map[string]*CJyutPing{}
	for {
		record, err := r.Read()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatal(err)
		}

		face := record[0]
		jyutping := record[1]

		var tjz *[]*CChar
		cjp, ok := JyutPingMap[jyutping]
		if ok {
			tjz = cjp.TungJamZi
		} else {
			cjp = &CJyutPing{}
			cjp.Roman = jyutping
			cjp.SearchKey = strings.ToUpper(jyutping)
			cjp.Key = &cjp.SearchKey
			tjz = &[]*CChar{}
			cjp.TungJamZi = tjz
			JyutPingMap[jyutping] = cjp
		}

		var c *CChar
		c, ok = charMap[face]
		if !ok {
			c = &CChar{}
			c.Face = face
			c.Key = &c.Face
			charMap[face] = c
		}

		*tjz = append(*tjz, c)

		var dj *DukJam

		if len(record) == 2 {
			c.JyutPing = cjp
			dj = &DukJam{}
			dj.Weight = 100
			dj.JyutPing = cjp
		} else if len(record) == 3 {
			s := record[2]
			var w int
			if strings.HasSuffix(s, "%") {
				w, err = strconv.Atoi(s[:len(s)-1])
				if err != nil {
					return nil, err
				}
			}
			dj = &DukJam{}
			dj.Weight = w
			dj.JyutPing = cjp
		}

		if dj != nil {
			if c.DukJam == nil {
				c.DukJam = &[]*DukJam{}
			}
			*c.DukJam = append(*c.DukJam, dj)
		}
	}

	for _, c := range charMap {
		if c.JyutPing == nil && c.DukJam != nil {
			_max := -1
			for _, dj := range *c.DukJam {
				if _max < dj.Weight {
					_max = dj.Weight
					c.JyutPing = dj.JyutPing
				}
			}
		}
	}

	return JyutPingMap, nil
}