diff --git a/.gitea/workflows/workflow.yaml b/.gitea/workflows/workflow.yaml index f635eb6..ec41e06 100644 --- a/.gitea/workflows/workflow.yaml +++ b/.gitea/workflows/workflow.yaml @@ -8,7 +8,7 @@ on: jobs: build: - runs-on: ubuntu-latest # You can change this to macos-latest or windows-latest if needed + runs-on: ubuntu-24.04 # You can change this to macos-latest or windows-latest if needed steps: - uses: actions/checkout@v3 @@ -39,4 +39,3 @@ jobs: echo "Go code has style issues. Please run 'golint./...' to see them." exit 1 fi - diff --git a/.gitignore b/.gitignore index 7b79aa2..a5b7afc 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /clean_file +numbers.json diff --git a/main.go b/main.go index 1875a2e..659852b 100644 --- a/main.go +++ b/main.go @@ -2,8 +2,9 @@ package main import "fmt" import "os" +import "git.kundeng.us/phoenix/clean_file/parser" -const VERSION = "0.4.101" +const VERSION = "0.3.101" func main() { fmt.Println("clean_file") @@ -17,6 +18,13 @@ func main() { filepath := args[1] fmt.Println("File path:", filepath) - // TODO: Create parser package and Parser struct to do the remaining - // work + prsr := parser.NumberParser{FilePath: filepath} + + rawValues := prsr.FileDump() + parsedValues := prsr.UpdateValues(rawValues) + newUpdated := prsr.RemoveDups(parsedValues) + + prsr.PrintValues(newUpdated, true) + + prsr.SaveFile(newUpdated) } diff --git a/parser/parser.go b/parser/parser.go new file mode 100644 index 0000000..79edf74 --- /dev/null +++ b/parser/parser.go @@ -0,0 +1,173 @@ +package parser + +import "fmt" +import "os" +import "unicode" +import ( + "bufio" + "log" +) +import "encoding/json" +import "strings" + +const Letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + +type SomeObject struct { + Value string `json:"value"` +} + +type NumberParser struct { + FilePath string +} + +func (prsr NumberParser) FileDump() []SomeObject { + fmt.Println("Dumping files") + objs := []SomeObject{} + + for _, line := range prsr.readLines(prsr.FilePath) { + if strings.ContainsAny(line, Letters) { + continue + } + + myObj := SomeObject{Value: line} + if myObj.Value != "" { + objs = append(objs, myObj) + } + } + + return objs +} + +func (prsr NumberParser) UpdateValues(vals []SomeObject) []SomeObject { + updated := []SomeObject{} + + for _, val := range vals { + parsed := val.Value + if len(parsed) < 2 { + fmt.Println("Invalid number:", parsed) + continue + } + + pars := prsr.removeSomeData(parsed) + parsed = pars + + fmt.Println(parsed) + + updatedParsed := prsr.addPrefix(parsed) + updated = append(updated, SomeObject{Value: updatedParsed}) + } + + return updated +} + +func (prsr NumberParser) RemoveDups(vals []SomeObject) []SomeObject { + updated := []SomeObject{} + uniqueItems := make(map[string]string) + + for _, val := range vals { + uniqueItems[val.Value] = val.Value + } + + for _, item := range uniqueItems { + updated = append(updated, SomeObject{Value: item}) + } + + return updated +} + +func (prsr NumberParser) PrintValues(vals []SomeObject, printTotal bool) { + fmt.Println("Printing values") + + for _, val := range vals { + fmt.Println("Value:", val.Value) + } + + if printTotal { + fmt.Println("Total Numbers:", len(vals)) + } +} + +func (prsr NumberParser) SaveFile(vals []SomeObject) { + filename := "numbers.json" + allNumbers := []string{} + + for _, val := range vals { + allNumbers = append(allNumbers, val.Value) + } + + // Create json and save it to the filesystem + jsonData, err := json.MarshalIndent(allNumbers, "", " ") + if err != nil { + fmt.Println("Error marshaling JSON:", err) + return + } + + err = os.WriteFile(filename, jsonData, 0644) + if err != nil { + fmt.Println("Error writing file:", err) + return + } +} + +func (prsr NumberParser) readLines(filename string) []string { + // Open the file + file, err := os.Open(filename) + if err != nil { + log.Fatal(err) + } + defer file.Close() + + // Create a scanner to read the file line by line + scanner := bufio.NewScanner(file) + lines := []string{} + + // Read line by line + for scanner.Scan() { + line := scanner.Text() + lines = append(lines, line) + } + + // Check for any errors during scanning + if err := scanner.Err(); err != nil { + log.Fatal(err) + } + + return lines +} + +func (prsr NumberParser) removeSomeData(unparsed string) string { + parsed := "" + + for _, ch := range unparsed { + if ch == ' ' { + continue + } else { + if unicode.IsDigit(ch) { + parsed += string(ch) + } + } + } + + fmt.Println("Parsed:", parsed) + + return parsed +} + +func (prsr NumberParser) addPrefix(raw string) string { + parsed := raw + + firstChar := raw[0] + secondChar := raw[1] + + if firstChar == '1' { + parsed = "+" + parsed + } else if firstChar != '+' { + if secondChar != '1' { + parsed = "+1" + parsed + } else { + parsed = "+1" + parsed + } + } + + return parsed +} diff --git a/parser/parser_test.go b/parser/parser_test.go new file mode 100644 index 0000000..bdc1eae --- /dev/null +++ b/parser/parser_test.go @@ -0,0 +1,129 @@ +package parser + +import "testing" +import "fmt" + +const Test_File_Path = "../tests/numbers.txt" + +// Add three tests +// File dump +func Test_FileDump(t *testing.T) { + parser := NumberParser{FilePath: Test_File_Path} + rawValues := parser.FileDump() + + testValues := []SomeObject{ + {Value: "(217) 555-0194"}, + {Value: "(602) 555-0177"}, + {Value: "(713) 555-0167"}, + {Value: "(608) 555-0190"}, + {Value: "(305) 555-0112"}, + {Value: "(415) 555-0135"}, + {Value: "(608) 555-0190"}, + {Value: "(602) 555-0177"}, + {Value: "(317) 555-0123"}, + {Value: "(360) 555-0158"}, + } + + if len(rawValues) < 1 { + t.Error("Dump should not be empty") + } + + if !dataEqual(rawValues, testValues) { + t.Error("File dump was not correctly dump") + } +} + +// Parse values +func Test_Parsed(t *testing.T) { + parser := NumberParser{FilePath: Test_File_Path} + rawValues := parser.FileDump() + + if len(rawValues) < 1 { + t.Error("Dump should not be empty") + } + + parsed := parser.UpdateValues(rawValues) + testValues := []SomeObject{ + {Value: "+12175550194"}, + {Value: "+16025550177"}, + {Value: "+17135550167"}, + {Value: "+16085550190"}, + {Value: "+13055550112"}, + {Value: "+14155550135"}, + {Value: "+16085550190"}, + {Value: "+16025550177"}, + {Value: "+13175550123"}, + {Value: "+13605550158"}, + } + + aSize := len(parsed) + bSize := len(testValues) + if aSize != bSize { + t.Error("Data has varrying sizes A", aSize, " B", bSize) + } + if !dataEqual(parsed, testValues) { + t.Error("Data has not be updated") + } +} + +// Remove duplicates +func Test_RemoveDups(t *testing.T) { + parser := NumberParser{FilePath: Test_File_Path} + rawValues := parser.FileDump() + + if len(rawValues) < 1 { + t.Error("Dump should not be empty") + } + + parsed := parser.UpdateValues(rawValues) + finalAmount := parser.RemoveDups(parsed) + testValues := []SomeObject{ + {Value: "+12175550194"}, + {Value: "+16025550177"}, + {Value: "+17135550167"}, + {Value: "+16085550190"}, + {Value: "+13055550112"}, + {Value: "+14155550135"}, + {Value: "+13175550123"}, + {Value: "+13605550158"}, + } + + aSize := len(finalAmount) + bSize := len(testValues) + if aSize != bSize { + t.Error("Data has varrying sizes A", aSize, " B", bSize) + } + if !dataEqual(finalAmount, testValues) { + fmt.Println("Printing final amount") + for _, val := range finalAmount { + fmt.Println("Value:", val.Value) + } + fmt.Println("Printing test values") + for _, val := range testValues { + fmt.Println("Value:", val.Value) + } + + t.Error("Data has not be updated") + } +} + +func dataEqual(a, b []SomeObject) bool { + if len(a) != len(b) { + return false + } + + for i := range a { + foundIt := false + for j := range b { + if a[i] == b[j] { + foundIt = true + } + } + + if !foundIt { + return false + } + } + + return true +} diff --git a/tests/numbers.txt b/tests/numbers.txt new file mode 100644 index 0000000..ea2d2ad --- /dev/null +++ b/tests/numbers.txt @@ -0,0 +1,10 @@ +(217) 555-0194 +(602) 555-0177 +(713) 555-0167 +(608) 555-0190 +(305) 555-0112 +(415) 555-0135 +(608) 555-0190 +(602) 555-0177 +(317) 555-0123 +(360) 555-0158