Parsing and bridging between the CSV struct and proto done

This commit is contained in:
cdricms
2024-04-28 17:43:39 +02:00
parent 041c9378c7
commit 25e4296fdb
11 changed files with 1600 additions and 157 deletions

113
Records.proto Normal file
View File

@@ -0,0 +1,113 @@
syntax = "proto3";
option go_package = "proto/";
enum Gender {
MALE = 0;
FEMALE = 1;
}
enum Quarter {
Q1 = 0;
Q2 = 1;
Q3 = 2;
Q4 = 3;
}
enum Half {
FIRST_HALF = 0;
SECOND_HALF = 1;
}
enum Month {
JANUARY = 0;
FEBRUARY = 1;
MARCH = 2;
APRIL = 3;
MAY = 4;
JUNE = 5;
JULY = 6;
AUGUST = 7;
SEPTEMBER = 8;
OCTOBER = 9;
NOVEMBER = 10;
DECEMBER = 11;
}
enum MonthShort {
JAN = 0;
FEB = 1;
MAR = 2;
APR = 3;
MAY_SHORT = 4;
JUN = 5;
JUL = 6;
AUG = 7;
SEP = 8;
OCT = 9;
NOV = 10;
DEC = 11;
}
enum WeekDay {
SUNDAY = 0;
MONDAY = 1;
TUESDAY = 2;
WEDNESDAY = 3;
THURSDAY = 4;
FRIDAY = 5;
SATURDAY = 6;
}
enum WeekDayShort {
SUN = 0;
MON = 1;
TUE = 2;
WED = 3;
THU = 4;
FRI = 5;
SAT = 6;
}
message Employee {
uint32 emp_id = 1;
string name_prefix = 2;
string first_name = 3;
string middle_initial = 4;
string last_name = 5;
Gender gender = 6;
string email = 7;
string fathers_name = 8;
string mothers_name = 9;
string mothers_maiden_name = 10;
string birthdate = 11;
string birth_time = 12;
uint32 weight_kg = 13;
string joining_date = 14;
Quarter joining_quarter = 15;
Half joining_half = 16;
uint32 joining_year = 17;
uint32 joining_month = 18;
Month joining_month_name = 19;
MonthShort joining_month_name_short = 20;
uint32 joining_month_day = 21;
WeekDay joining_week_day = 22;
WeekDayShort joining_week_day_short = 23;
float years_of_service = 24;
uint32 salary = 25;
string latest_hike_percentage = 26;
string ssn = 27;
string phone_number = 28;
string place_name = 29;
string county = 30;
string city = 31;
string state = 32;
uint32 zip = 33;
string region = 34;
string username = 35;
string password = 36;
}
message EmployeeList {
repeated Employee employees = 1;
}

BIN
employee_data.bin Normal file

Binary file not shown.

1
employee_data.json Normal file

File diff suppressed because one or more lines are too long

5
go.mod
View File

@@ -1,3 +1,8 @@
module git.cems.dev/cdricms/bdooc module git.cems.dev/cdricms/bdooc
go 1.22.2 go 1.22.2
require (
github.com/golang/protobuf v1.5.4 // indirect
google.golang.org/protobuf v1.33.0 // indirect
)

4
go.sum Normal file
View File

@@ -0,0 +1,4 @@
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=

43
main.go
View File

@@ -1,27 +1,42 @@
package main package main
import ( import (
"encoding/csv" // "encoding/csv"
"fmt" "fmt"
"os" // "os"
"git.cems.dev/cdricms/bdooc/parsing"
"git.cems.dev/cdricms/bdooc/parsing"
"git.cems.dev/cdricms/bdooc/proto"
// "git.cems.dev/cdricms/bdooc/parsing"
) )
func main() { func main() {
f, err := os.Open("50000 Records.csv") // f, err := os.Open("50000 Records.csv")
if err != nil { // if err != nil {
fmt.Println(err) // fmt.Println(err)
} // }
defer f.Close() // defer f.Close()
reader := csv.NewReader(f) // reader := csv.NewReader(f)
employees, err := parsing.UnmarshalEmployees(reader) // employees, err := parsing.UnmarshalEmployees(reader)
if err != nil { // if err != nil {
fmt.Println(err) // fmt.Println(err)
} // }
fmt.Println(employees[:10]) // data := parsing.MapToProto(employees)
// data.SaveToFile("employee_data.bin")
// fmt.Println(employees[:10])
data, err := proto.LoadFromFile("employee_data.bin")
if err != nil {
fmt.Println(err)
}
employees := parsing.MapFromProtoList(data)
fmt.Println(employees[:2])
} }

View File

@@ -1,54 +1,13 @@
package parsing package parsing
import ( import (
"errors" "encoding/csv"
"encoding/csv" "errors"
"reflect" "reflect"
"strconv" "strconv"
"git.cems.dev/cdricms/bdooc/proto"
) )
type Employee struct {
EmpID uint `csv:"Emp ID"`
NamePrefix string `csv:"Name Prefix"`
FirstName string `csv:"First Name"`
MiddleInitial string `csv:"Middle Initial"`
LastName string `csv:"Last Name"`
Gender Gender `csv:"Gender"`
Email string `csv:"E Mail"`
FathersName string `csv:"Father's Name"`
MothersName string `csv:"Mothers's Name"`
MothersMaidenName string `csv:"Mother's Maiden Name"`
Birthdate string `csv:"Date of Birth"`
BirthTime string `csv:"Time of Birth"`
WeightKg uint16 `csv:"Weight in Kgs."`
JoiningDate string `csv:"Date of Joining"`
JoiningQuarter Quarter `csv:"Quarter of Joining"`
JoiningHalf Half `csv:"Half of Joining"`
JoiningYear uint16 `csv:"Year of Joining"`
JoiningMonth uint8 `csv:"Month of Joining"`
JoiningMonthName Month `csv:"Month Name of Joining"`
JoiningMonthNameShort MonthShort `csv:"Short Month"`
JoiningMonthDay uint8 `csv:"Day of Joining"`
JoiningWeekDay WeekDay `csv:"DOW of Joining"`
JoiningWeekDayShort WeekDayShort `csv:"Short DOW"`
YearsOfService float32 `csv:"Age in Company (Years)"`
Salary uint32 `csv:"Salary"`
LatestHikePercentage string `csv:"Last % Hike"`
SSN string `csv:"SSN"`
PhoneNumber string `csv:"Phone No."`
PlaceName string `csv:"Place Name"`
County string `csv:"County"`
City string `csv:"City"`
State string `csv:"State"`
Zip uint32 `csv:"Zip"`
Region string `csv:"Region"`
Username string `csv:"User Name"`
Password string `csv:"Password"`
// Empty slot
// Empty slot
// Empty slot
}
func UnmarshalEmployees(reader *csv.Reader) ([]Employee, error) { func UnmarshalEmployees(reader *csv.Reader) ([]Employee, error) {
reader.Comma = ',' reader.Comma = ','
headers, err := reader.Read() headers, err := reader.Read()
@@ -56,19 +15,18 @@ func UnmarshalEmployees(reader *csv.Reader) ([]Employee, error) {
return nil, errors.New("Couldn't read the headers.") return nil, errors.New("Couldn't read the headers.")
} }
e := Employee{} e := Employee{}
refet := reflect.TypeOf(e) refet := reflect.TypeOf(e)
tagMap := make(map[string]int) tagMap := make(map[string]int)
headersLength := len(headers) headersLength := len(headers)
numFields := refet.NumField() numFields := refet.NumField()
for i := 0; i < numFields && i < headersLength; i++ { for i := 0; i < numFields && i < headersLength; i++ {
field := refet.Field(i) field := refet.Field(i)
if field.Tag.Get("csv") == headers[i] { if field.Tag.Get("csv") == headers[i] {
tagMap[field.Name] = i tagMap[field.Name] = i
} }
} }
var employees []Employee var employees []Employee
for { for {
record, err := reader.Read() record, err := reader.Read()
@@ -85,10 +43,6 @@ func UnmarshalEmployees(reader *csv.Reader) ([]Employee, error) {
switch field.Type().Name() { switch field.Type().Name() {
case "string": case "string":
field.SetString(record[index]) field.SetString(record[index])
case "uint":
if intValue, err := strconv.ParseUint(record[index], 10, 64); err == nil {
field.SetUint(intValue)
}
case "uint8": case "uint8":
if intValue, err := strconv.ParseUint(record[index], 10, 8); err == nil { if intValue, err := strconv.ParseUint(record[index], 10, 8); err == nil {
field.SetUint(intValue) field.SetUint(intValue)
@@ -127,3 +81,110 @@ func UnmarshalEmployees(reader *csv.Reader) ([]Employee, error) {
return employees, nil return employees, nil
} }
func (e Employee) MapToProto() *proto.Employee {
employee := &proto.Employee{}
employee.EmpId = e.EmpID
employee.NamePrefix = e.NamePrefix
employee.FirstName = e.FirstName
employee.MiddleInitial = e.MiddleInitial
employee.LastName = e.LastName
employee.Gender = proto.Gender(e.Gender)
employee.Email = e.Email
employee.FathersName = e.FathersName
employee.MothersName = e.MothersName
employee.MothersMaidenName = e.MothersMaidenName
employee.Birthdate = e.Birthdate
employee.BirthTime = e.BirthTime
employee.WeightKg = uint32(e.WeightKg)
employee.JoiningDate = e.JoiningDate
employee.JoiningQuarter = proto.Quarter(e.JoiningQuarter.Uint8())
employee.JoiningHalf = proto.Half(e.JoiningHalf.Uint8())
employee.JoiningYear = uint32(e.JoiningYear)
employee.JoiningMonth = uint32(e.JoiningMonth)
employee.JoiningMonthName = proto.Month(e.JoiningMonthName.Uint8())
employee.JoiningMonthNameShort = proto.MonthShort(e.JoiningMonthNameShort.Uint8())
employee.JoiningMonthDay = uint32(e.JoiningMonthDay)
employee.JoiningWeekDay = proto.WeekDay(e.JoiningWeekDay.Uint8())
employee.JoiningWeekDayShort = proto.WeekDayShort(e.JoiningWeekDayShort.Uint8())
employee.YearsOfService = float32(e.YearsOfService)
employee.Salary = uint32(e.Salary)
employee.LatestHikePercentage = e.LatestHikePercentage
employee.Ssn = e.SSN
employee.PhoneNumber = e.PhoneNumber
employee.PlaceName = e.PlaceName
employee.County = e.County
employee.City = e.City
employee.State = e.State
employee.Zip = uint32(e.Zip)
employee.Region = e.Region
employee.Username = e.Username
employee.Password = e.Password
return employee
}
func MapToProto(es []Employee) *proto.EmployeeList {
employeeList := &proto.EmployeeList{}
for _, employee := range es {
employeeList.Employees = append(employeeList.Employees, employee.MapToProto())
}
return employeeList
}
func MapFromProto(e *proto.Employee) Employee {
employee := Employee{}
employee.EmpID = e.EmpId
employee.NamePrefix = e.NamePrefix
employee.FirstName = e.FirstName
employee.MiddleInitial = e.MiddleInitial
employee.LastName = e.LastName
employee.Gender = Gender(e.Gender)
employee.Email = e.Email
employee.FathersName = e.FathersName
employee.MothersName = e.MothersName
employee.MothersMaidenName = e.MothersMaidenName
employee.Birthdate = e.Birthdate
employee.BirthTime = e.BirthTime
employee.WeightKg = uint16(e.WeightKg)
employee.JoiningDate = e.JoiningDate
employee.JoiningQuarter = Quarter(e.JoiningQuarter.String())
employee.JoiningHalf = Half(e.JoiningHalf.String())
employee.JoiningYear = uint16(e.JoiningYear)
employee.JoiningMonth = uint8(e.JoiningMonth)
employee.JoiningMonthName = Month(e.JoiningMonthName.String())
employee.JoiningMonthNameShort = MonthShort(e.JoiningMonthNameShort.String())
employee.JoiningMonthDay = uint8(e.JoiningMonthDay)
employee.JoiningWeekDay = WeekDay(e.JoiningWeekDay.String())
employee.JoiningWeekDayShort = WeekDayShort(e.JoiningWeekDayShort.String())
employee.YearsOfService = float32(e.YearsOfService)
employee.Salary = uint32(e.Salary)
employee.LatestHikePercentage = e.LatestHikePercentage
employee.SSN = e.Ssn
employee.PhoneNumber = e.PhoneNumber
employee.PlaceName = e.PlaceName
employee.County = e.County
employee.City = e.City
employee.State = e.State
employee.Zip = uint32(e.Zip)
employee.Region = e.Region
employee.Username = e.Username
employee.Password = e.Password
return employee
}
func MapFromProtoList(el *proto.EmployeeList) []Employee {
employees := []Employee{}
for _, pemployee := range el.GetEmployees() {
employees = append(employees, MapFromProto(pemployee))
}
return employees
}

View File

@@ -1,82 +0,0 @@
package parsing
type Gender rune
const (
Male Gender = 'M'
Female Gender = 'F'
)
type Quarter string
const (
QuarterOne Quarter = "Q1"
QuarterTwo Quarter = "Q2"
QuarterThree Quarter = "Q3"
QuarterFour Quarter = "Q4"
)
type Half string
const (
HalfOne Half = "H1"
HalfTwo Half = "H2"
)
type Month string
const (
January Month = "January"
February Month = "February"
March Month = "March"
April Month = "April"
May Month = "May"
June Month = "June"
July Month = "July"
August Month = "August"
September Month = "September"
October Month = "October"
November Month = "November"
December Month = "December"
)
type MonthShort string
const (
Jan MonthShort = "Jan"
Feb MonthShort = "Feb"
Mar MonthShort = "Mar"
Apr MonthShort = "Apr"
MayShort MonthShort = "May"
Jun MonthShort = "Jun"
Jul MonthShort = "Jul"
Aug MonthShort = "Aug"
Sep MonthShort = "Sep"
Oct MonthShort = "Oct"
Nov MonthShort = "Nov"
Dec MonthShort = "Dec"
)
type WeekDay string
const (
Monday WeekDay = "Monday"
Tuesday WeekDay = "Tuesday"
Wednesday WeekDay = "Wednesday"
Thursday WeekDay = "Thursday"
Friday WeekDay = "Friday"
Saturday WeekDay = "Saturday"
Sunday WeekDay = "Sunday"
)
type WeekDayShort string
const (
Mon WeekDayShort = "Mon"
Tue WeekDayShort = "Tue"
Wed WeekDayShort = "Wed"
Thu WeekDayShort = "Thu"
Fri WeekDayShort = "Fri"
Sat WeekDayShort = "Sat"
Sun WeekDayShort = "Sun"
)

250
parsing/types.go Normal file
View File

@@ -0,0 +1,250 @@
package parsing
type Gender rune
const (
Male Gender = 'M'
Female Gender = 'F'
)
type Quarter string
const (
QuarterOne Quarter = "Q1"
QuarterTwo Quarter = "Q2"
QuarterThree Quarter = "Q3"
QuarterFour Quarter = "Q4"
)
func (x Quarter) Uint8() uint8 {
switch x {
case QuarterOne:
return 1
case QuarterTwo:
return 2
case QuarterThree:
return 3
case QuarterFour:
return 4
}
return 0
}
type Half string
const (
HalfOne Half = "H1"
HalfTwo Half = "H2"
)
func (x Half) Uint8() uint8 {
switch x {
case HalfOne:
return 1
case HalfTwo:
return 2
}
return 0
}
type Month string
const (
January Month = "January"
February Month = "February"
March Month = "March"
April Month = "April"
May Month = "May"
June Month = "June"
July Month = "July"
August Month = "August"
September Month = "September"
October Month = "October"
November Month = "November"
December Month = "December"
)
func (x Month) Uint8() uint8 {
switch x {
case January:
return 1
case February:
return 2
case March:
return 3
case April:
return 4
case May:
return 5
case June:
return 6
case July:
return 7
case August:
return 8
case September:
return 9
case October:
return 10
case November:
return 11
case December:
return 12
default:
return 0
}
}
type MonthShort string
const (
Jan MonthShort = "Jan"
Feb MonthShort = "Feb"
Mar MonthShort = "Mar"
Apr MonthShort = "Apr"
MayShort MonthShort = "May"
Jun MonthShort = "Jun"
Jul MonthShort = "Jul"
Aug MonthShort = "Aug"
Sep MonthShort = "Sep"
Oct MonthShort = "Oct"
Nov MonthShort = "Nov"
Dec MonthShort = "Dec"
)
func (x MonthShort) Uint8() uint8 {
switch x {
case Jan:
return 1
case Feb:
return 2
case Mar:
return 3
case Apr:
return 4
case MayShort:
return 5
case Jun:
return 6
case Jul:
return 7
case Aug:
return 8
case Sep:
return 9
case Oct:
return 10
case Nov:
return 11
case Dec:
return 12
}
return 0
}
type WeekDay string
const (
Monday WeekDay = "Monday"
Tuesday WeekDay = "Tuesday"
Wednesday WeekDay = "Wednesday"
Thursday WeekDay = "Thursday"
Friday WeekDay = "Friday"
Saturday WeekDay = "Saturday"
Sunday WeekDay = "Sunday"
)
func (x WeekDay) Uint8() uint8 {
switch x {
case Monday:
return 1
case Tuesday:
return 2
case Wednesday:
return 3
case Thursday:
return 4
case Friday:
return 5
case Saturday:
return 6
case Sunday:
return 7
}
return 0
}
type WeekDayShort string
const (
Mon WeekDayShort = "Mon"
Tue WeekDayShort = "Tue"
Wed WeekDayShort = "Wed"
Thu WeekDayShort = "Thu"
Fri WeekDayShort = "Fri"
Sat WeekDayShort = "Sat"
Sun WeekDayShort = "Sun"
)
func (x WeekDayShort) Uint8() uint8 {
switch x {
case Mon:
return 1
case Tue:
return 2
case Wed:
return 3
case Thu:
return 4
case Fri:
return 5
case Sat:
return 6
case Sun:
return 7
}
return 0
}
type Employee struct {
EmpID uint32 `csv:"Emp ID"`
NamePrefix string `csv:"Name Prefix"`
FirstName string `csv:"First Name"`
MiddleInitial string `csv:"Middle Initial"`
LastName string `csv:"Last Name"`
Gender Gender `csv:"Gender"`
Email string `csv:"E Mail"`
FathersName string `csv:"Father's Name"`
MothersName string `csv:"Mothers's Name"`
MothersMaidenName string `csv:"Mother's Maiden Name"`
Birthdate string `csv:"Date of Birth"`
BirthTime string `csv:"Time of Birth"`
WeightKg uint16 `csv:"Weight in Kgs."`
JoiningDate string `csv:"Date of Joining"`
JoiningQuarter Quarter `csv:"Quarter of Joining"`
JoiningHalf Half `csv:"Half of Joining"`
JoiningYear uint16 `csv:"Year of Joining"`
JoiningMonth uint8 `csv:"Month of Joining"`
JoiningMonthName Month `csv:"Month Name of Joining"`
JoiningMonthNameShort MonthShort `csv:"Short Month"`
JoiningMonthDay uint8 `csv:"Day of Joining"`
JoiningWeekDay WeekDay `csv:"DOW of Joining"`
JoiningWeekDayShort WeekDayShort `csv:"Short DOW"`
YearsOfService float32 `csv:"Age in Company (Years)"`
Salary uint32 `csv:"Salary"`
LatestHikePercentage string `csv:"Last % Hike"`
SSN string `csv:"SSN"`
PhoneNumber string `csv:"Phone No."`
PlaceName string `csv:"Place Name"`
County string `csv:"County"`
City string `csv:"City"`
State string `csv:"State"`
Zip uint32 `csv:"Zip"`
Region string `csv:"Region"`
Username string `csv:"User Name"`
Password string `csv:"Password"`
// Empty slot
// Empty slot
// Empty slot
}

1034
proto/Records.pb.go Normal file

File diff suppressed because it is too large Load Diff

42
proto/io.go Normal file
View File

@@ -0,0 +1,42 @@
package proto
import (
"os"
"google.golang.org/protobuf/proto"
// "git.cems.dev/cdricms/bdooc/parsing"
)
func (el *EmployeeList) SaveToFile(filename string) error {
data, err := proto.Marshal(el)
if err != nil {
return err
}
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
_, err = file.Write(data)
if err != nil {
return err
}
return nil
}
func LoadFromFile(filename string) (*EmployeeList, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
data, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
el := &EmployeeList{}
err = proto.Unmarshal(data, el)
if err != nil {
return nil, err
}
return el, nil
}