diff --git a/toukibo/houjin_stock.go b/toukibo/houjin_stock.go new file mode 100644 index 0000000..5269705 --- /dev/null +++ b/toukibo/houjin_stock.go @@ -0,0 +1,33 @@ +package toukibo + +import ( + "strconv" + "strings" +) + +type HoujinPreferredStock struct { + Type string `yaml:"Type"` + Amount int `yaml:"Amount"` +} + +type HoujinStock struct { + Total int + Preferred []HoujinPreferredStock +} + +func (s HoujinStock) Sum() int { + sum := 0 + for _, p := range s.Preferred { + sum += p.Amount + } + return sum +} + +func (s HoujinStock) String() string { + var b strings.Builder + for _, p := range s.Preferred { + b.WriteString(" - Type: " + p.Type + "\n") + b.WriteString(" Amount: " + strconv.Itoa(p.Amount) + "\n") + } + return b.String() +} diff --git a/toukibo/stock_converter.go b/toukibo/stock_converter.go index 288220c..6b29660 100644 --- a/toukibo/stock_converter.go +++ b/toukibo/stock_converter.go @@ -1,20 +1,19 @@ package toukibo import ( + "fmt" + "regexp" "strings" ) -func StockToNumber(stock string) int { - // 発行済株式の総数5万株 → 50000 - stock = strings.Replace(stock, "発行済株式の総数", "", -1) - if strings.HasPrefix(stock, "普通株式") { // sample1082用のハック - stock = strings.Replace(stock, "普通株式", "", -1) - } - stock = ZenkakuToHankaku(stock) - +func GetStockNumber(s string) (int, string) { sums := 0 cur := 0 - for _, v := range stock { + foundKabu := false + for idx, v := range s { + if foundKabu { + return sums, s[idx:] + } if v >= '0' && v <= '9' { cur = cur*10 + int(v-'0') continue @@ -32,10 +31,73 @@ func StockToNumber(stock string) int { cur = 0 case '株': sums += cur - return sums + cur = 0 // 意味はない + foundKabu = true // 発行済株式の総数4万8249株各種の株式の数普通株式   3万249株A種優先株式 1万株B種優先株式 8000株 // のようなパターンでは最初の株でReturnさせる + continue } } - return sums + return sums, "" +} + +func GetHoujinStock(stock string) HoujinStock { + stock = ZenkakuToHankaku(stock) + stock = trimAllSpace(stock) + res := HoujinStock{} + + for { + if stock == "" { + break + } + + if strings.HasPrefix(stock, "発行済株式の総数") { + stock = strings.Replace(stock, "発行済株式の総数", "", -1) + if strings.HasPrefix(stock, "普通株式") { + continue // sample1082用のハック + } + + sums, s := GetStockNumber(stock) + stock = s + res.Total = sums + continue + } + + if strings.HasPrefix(stock, "各種の株式の数") { + stock = strings.Replace(stock, "各種の株式の数", "", -1) + continue + } + + if strings.HasPrefix(stock, "普通株式") { + stock = strings.Replace(stock, "普通株式", "", -1) + normal, s := GetStockNumber(stock) + stock = s + res.Preferred = append(res.Preferred, HoujinPreferredStock{Type: "普通株式", Amount: normal}) + continue + } + + // *優先株式 で始まる場合 + pattern := fmt.Sprintf("([%s]+優先株式)", ZenkakuNoNumberStringPattern) + regex := regexp.MustCompile(pattern) + matches := regex.FindStringSubmatch(stock) + if len(matches) > 0 { + stock = strings.Replace(stock, matches[1], "", -1) + num, s := GetStockNumber(stock) + stock = s + res.Preferred = append(res.Preferred, HoujinPreferredStock{Type: matches[1], Amount: num}) + continue + } + + break + } + if res.Total == 0 { + res.Total = res.Sum() + } + + return res +} + +func StockToNumber(stock string) int { + res := GetHoujinStock(stock) + return res.Total } diff --git a/toukibo/stock_converter_test.go b/toukibo/stock_converter_test.go index 40271ef..de3f8a3 100644 --- a/toukibo/stock_converter_test.go +++ b/toukibo/stock_converter_test.go @@ -6,6 +6,35 @@ import ( "github.com/tychy/toukibo-parser/toukibo" ) +func TestGetStockNumber(t *testing.T) { + testCases := []struct { + input string + expected int + remain string + }{ + { + input: "5万株", + expected: 50000, + remain: "", + }, + { + input: "1万9013株各種の株式の数普通株式", + expected: 19013, + remain: "各種の株式の数普通株式", + }, + } + + for _, tc := range testCases { + got, remain := toukibo.GetStockNumber(tc.input) + if got != tc.expected { + t.Errorf("GetStockNumber(%s) = %d; want %d", tc.input, got, tc.expected) + } + if remain != tc.remain { + t.Errorf("GetStockNumber(%s) = %s; want %s", tc.input, remain, tc.remain) + } + } +} + func TestStockToNumber(t *testing.T) { testCases := []struct { input string @@ -15,10 +44,14 @@ func TestStockToNumber(t *testing.T) { input: "発行済株式の総数5万株", expected: 50000, }, + { + input: "発行済株式の総数1万9013株各種の株式の数普通株式   1万525株A種優先株式  3434株A1種優先株式 1100株A2種優先株式 2103株A3種優先株式 1851株", + expected: 19013, + }, { // sample1082 input: "発行済株式の総数普通株式     5138株A種優先株式   1250株B種優先株式   3250株", - expected: 5138, + expected: 9638, }, } diff --git a/toukibo/zenkaku.go b/toukibo/zenkaku.go index b710803..1c259aa 100644 --- a/toukibo/zenkaku.go +++ b/toukibo/zenkaku.go @@ -5,18 +5,19 @@ import ( ) const ( - ZenkakuZero = '0' - ZenkakuNine = '9' - ZenkakuA = 'A' - ZenkakuZ = 'Z' - ZenkakuSmallA = 'a' - ZenkakuSmallZ = 'z' - ZenkakuSpace = ' ' - ZenkakuColon = ':' - ZenkakuSlash = '/' - ZenkakuHyphen = '-' - ZenkakuNumberPattern = `0-9` - ZenkakuStringPattern = `\p{Han}\p{Hiragana}\p{Katakana}A-Za-z0-9A-Za-z0-9&’,‐.・ー\s 。-、:/` + ZenkakuZero = '0' + ZenkakuNine = '9' + ZenkakuA = 'A' + ZenkakuZ = 'Z' + ZenkakuSmallA = 'a' + ZenkakuSmallZ = 'z' + ZenkakuSpace = ' ' + ZenkakuColon = ':' + ZenkakuSlash = '/' + ZenkakuHyphen = '-' + ZenkakuNumberPattern = `0-9` + ZenkakuNoNumberStringPattern = `\p{Han}\p{Hiragana}\p{Katakana}A-Za-zA-Za-z&’,‐.・ー\s 。-、:/` + ZenkakuStringPattern = ZenkakuNoNumberStringPattern + ZenkakuNumberPattern + `0-9` ) func ZenkakuToHankaku(s string) string {