Files
challenge/proto/queries.go
2024-04-28 21:05:13 +02:00

246 lines
7.7 KiB
Go

package proto
import (
"fmt"
"math"
"reflect"
)
func GetMax[T float64 | float32 | int | uint | int8 | uint8 | int16 | uint16 | int32 | uint32 | int64 | uint64](a, b T) T {
if a > b {
return a
}
return b
}
func GetMin[T float64 | float32 | int | uint | int8 | uint8 | int16 | uint16 | int32 | uint32 | int64 | uint64](a, b T) T {
if a < b {
return a
}
return b
}
type EmployeeField string
const (
FieldEmpID EmployeeField = "EmpId"
FieldNamePrefix = "NamePrefix"
FieldFirstName = "FirstName"
FieldMiddleInitial = "MiddleInitial"
FieldLastName = "LastName"
FieldGender = "Gender"
FieldEmail = "Email"
FieldFathersName = "FathersName"
FieldMothersName = "MothersName"
FieldMothersMaidenName = "MothersMaidenName"
FieldBirthdate = "Birthdate"
FieldBirthTime = "BirthTime"
FieldWeightKg = "WeightKg"
FieldJoiningDate = "JoiningDate"
FieldJoiningQuarter = "JoiningQuarter"
FieldJoiningHalf = "JoiningHalf"
FieldJoiningYear = "JoiningYear"
FieldJoiningMonth = "JoiningMonth"
FieldJoiningMonthName = "JoiningMonthName"
FieldJoiningMonthNameShort = "JoiningMonthNameShort"
FieldJoiningMonthDay = "JoiningMonthDay"
FieldJoiningWeekDay = "JoiningWeekDay"
FieldJoiningWeekDayShort = "JoiningWeekDayShort"
FieldYearsOfService = "YearsOfService"
FieldSalary = "Salary"
FieldLatestHikePercentage = "LatestHikePercentage"
FieldSsn = "Ssn"
FieldPhoneNumber = "PhoneNumber"
FieldPlaceName = "PlaceName"
FieldCounty = "County"
FieldCity = "City"
FieldState = "State"
FieldZip = "Zip"
FieldRegion = "Region"
FieldUsername = "Username"
FieldPassword = "Password"
)
func (e *Employee) Copy() Employee {
return Employee{
EmpId: e.GetEmpId(),
NamePrefix: e.GetNamePrefix(),
FirstName: e.GetFirstName(),
MiddleInitial: e.GetMiddleInitial(),
LastName: e.GetLastName(),
Gender: e.GetGender(),
Email: e.GetEmail(),
FathersName: e.GetFathersName(),
MothersName: e.GetMothersName(),
MothersMaidenName: e.GetMothersMaidenName(),
Birthdate: e.GetBirthdate(),
BirthTime: e.GetBirthTime(),
WeightKg: e.GetWeightKg(),
JoiningDate: e.GetJoiningDate(),
JoiningQuarter: e.GetJoiningQuarter(),
JoiningHalf: e.GetJoiningHalf(),
JoiningYear: e.GetJoiningYear(),
JoiningMonth: e.GetJoiningMonth(),
JoiningMonthName: e.GetJoiningMonthName(),
JoiningMonthNameShort: e.GetJoiningMonthNameShort(),
JoiningMonthDay: e.GetJoiningMonthDay(),
JoiningWeekDay: e.GetJoiningWeekDay(),
JoiningWeekDayShort: e.GetJoiningWeekDayShort(),
YearsOfService: e.GetYearsOfService(),
Salary: e.GetSalary(),
LatestHikePercentage: e.GetLatestHikePercentage(),
Ssn: e.GetSsn(),
PhoneNumber: e.GetPhoneNumber(),
PlaceName: e.GetPlaceName(),
County: e.GetCounty(),
City: e.GetCity(),
State: e.GetState(),
Zip: e.GetZip(),
Region: e.GetRegion(),
Username: e.GetUsername(),
Password: e.GetPassword(),
}
}
func (el *EmployeeList) QueryEmployeesByColumn(column EmployeeField, query string) ([]*Employee, error) {
employees := make([]*Employee, 0)
for _, employee := range el.GetEmployees() {
value := reflect.ValueOf(employee).Elem().FieldByName(string(column))
if fmt.Sprintf("%v", value) == query {
employees = append(employees, employee)
}
}
return employees, nil
}
type Groups map[string][]*Employee
func (el *EmployeeList) GroupByColumn(column EmployeeField) Groups {
groups := make(map[string][]*Employee)
for _, employee := range el.GetEmployees() {
value := reflect.ValueOf(employee).Elem().FieldByName(string(column))
formattedValue := fmt.Sprintf("%v", value)
groups[formattedValue] = append(groups[formattedValue], employee)
}
return groups
}
type FilterFunction func(*Employee) bool
func (grps Groups) HavingByColumn(cb FilterFunction) Groups {
newGrps := make(map[string][]*Employee)
for groupName, group := range grps {
for _, employee := range group {
if cb(employee) {
newGrps[groupName] = append(newGrps[groupName], employee)
}
}
}
return newGrps
}
func ForEachGroup[T any](grps Groups, cb func(ep EmployeePList) T) map[string]T {
g := make(map[string]T)
for groupName, group := range grps {
g[groupName] = cb(group)
}
return g
}
func AggregateByColumn[T any](el *EmployeeList, column EmployeeField, cb func(ep EmployeePList) T) map[string]T {
grps := el.GroupByColumn(column)
res := ForEachGroup(grps, cb)
return res
}
type EmployeePList []*Employee
func Sum(ep EmployeePList, column EmployeeField) float64 {
sum := 0.0
_, fieldFound := reflect.TypeOf(Employee{}).FieldByName(string(column))
if !fieldFound {
return sum
}
for _, employee := range ep {
value := reflect.ValueOf(employee).Elem().FieldByName(string(column))
switch value.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
sum += float64(value.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
sum += float64(value.Uint())
case reflect.Float64, reflect.Float32:
sum += value.Float()
default:
return sum
}
}
return sum
}
func Average(ep EmployeePList, column EmployeeField) float64 {
return Sum(ep, column) / float64(len(ep))
}
func Max(ep EmployeePList, column EmployeeField) float64 {
max := 0.0
_, fieldFound := reflect.TypeOf(Employee{}).FieldByName(string(column))
if !fieldFound {
return max
}
for _, employee := range ep {
value := reflect.ValueOf(employee).Elem().FieldByName(string(column))
switch value.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
max = GetMax(max, float64(value.Int()))
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
max = GetMax(max, float64(value.Uint()))
case reflect.Float64, reflect.Float32:
max = GetMax(max, value.Float())
default:
return max
}
}
return max
}
func Min(ep EmployeePList, column EmployeeField) float64 {
min := math.MaxFloat64
_, fieldFound := reflect.TypeOf(Employee{}).FieldByName(string(column))
if !fieldFound {
return min
}
for _, employee := range ep {
value := reflect.ValueOf(employee).Elem().FieldByName(string(column))
switch value.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
min = GetMin(min, float64(value.Int()))
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
min = GetMin(min, float64(value.Uint()))
case reflect.Float64, reflect.Float32:
min = GetMin(min, value.Float())
default:
return min
}
}
return min
}