Translate to french, fix corsica, add more tests, improve output

This commit is contained in:
Gabriel Augendre 2021-08-18 22:46:05 +02:00
parent 8272126024
commit 40e48867fd
7 changed files with 37050 additions and 36828 deletions

View file

@ -6,13 +6,13 @@ Extract data from INSEE number (France)
### From sources ### From sources
#### Run #### Run
```shell ```shell
go run . 269059913116714 168127982980507 go run . 269059913116714 168127982980507 299122A00498723 299129742398791 144089943287340
``` ```
#### Build & install #### Build & install
```shell ```shell
go install go install
insee_number_translator 269059913116714 168127982980507 insee_number_translator 269059913116714 168127982980507 299122A00498723 299129742398791 144089943287340
``` ```
## Data sources ## Data sources

File diff suppressed because it is too large Load diff

View file

@ -1,23 +1,31 @@
package data package data
import ( import (
"encoding/json"
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
"time" "time"
) )
var Male = "homme"
var Female = "femme"
var Unknown = "inconnu(e)"
type InseeData struct { type InseeData struct {
InseeNumber string InseeNumber string `json:"insee_number"`
Gender string Gender string `json:"gender"`
Year int Year int `json:"year"`
Month time.Month Month time.Month `json:"month"`
Department string Department string `json:"department"`
City string City *City `json:"city"`
Foreign bool CityCode string `json:"city_code"`
Country string Foreign bool `json:"foreign"`
OrderOfBirth int Countries []string `json:"countries"`
ControlKey int CountryCode string `json:"country_code"`
Continent string `json:"continent"`
OrderOfBirth int `json:"order_of_birth"`
ControlKey int `json:"control_key"`
} }
func NewInseeData(inseeNumber string) (*InseeData, error) { func NewInseeData(inseeNumber string) (*InseeData, error) {
@ -25,23 +33,39 @@ func NewInseeData(inseeNumber string) (*InseeData, error) {
return nil, fmt.Errorf("provided insee number must contain 15 characters") return nil, fmt.Errorf("provided insee number must contain 15 characters")
} }
num := inseeNumber num := inseeNumber
department := num[5:7] departmentCode := num[5:7]
city := num[7:10] cityCode := num[7:10]
if department == "97" || department == "98" { if departmentCode == "97" || departmentCode == "98" {
department = num[5:8] departmentCode = num[5:8]
city = num[8:10] cityCode = num[8:10]
} }
dep, err := strconv.Atoi(department) dep, err := strconv.Atoi(departmentCode)
if err != nil { if err != nil && departmentCode != "2A" && departmentCode != "2B" {
return nil, err return nil, err
} }
foreign := false var city *City
country := "FR" var department string
if (dep >= 91 && dep <= 96) || dep == 99 { countries_ := []string{"FRANCE"}
countryCode := ""
continent := "Europe"
foreign := (dep >= 91 && dep <= 96) || dep == 99
if foreign {
foreign = true foreign = true
country = city countryCode = cityCode
city = "unknown" cityCode = ""
department = "unknown" countries_ = countries["99"+countryCode]
continent = continents[countryCode[0:1]]
department = Unknown
} else {
c, present := cities[departmentCode+cityCode]
if present {
city = &c
}
var depPresent bool
department, depPresent = departments[departmentCode]
if !depPresent {
department = Unknown
}
} }
order, err := strconv.Atoi(num[10:13]) order, err := strconv.Atoi(num[10:13])
if err != nil { if err != nil {
@ -68,9 +92,9 @@ func NewInseeData(inseeNumber string) (*InseeData, error) {
} }
gender := num[0:1] gender := num[0:1]
if gender == "1" { if gender == "1" {
gender = "Male" gender = Male
} else { } else {
gender = "Female" gender = Female
} }
return &InseeData{ return &InseeData{
InseeNumber: num, InseeNumber: num,
@ -79,16 +103,22 @@ func NewInseeData(inseeNumber string) (*InseeData, error) {
Month: month, Month: month,
Department: department, Department: department,
City: city, City: city,
CityCode: cityCode,
Foreign: foreign, Foreign: foreign,
Country: country, Countries: countries_,
CountryCode: countryCode,
Continent: continent,
OrderOfBirth: order, OrderOfBirth: order,
ControlKey: controlKey, ControlKey: controlKey,
}, nil }, nil
} }
func (insee InseeData) IsValid() (bool, error) { func (insee InseeData) IsValid() (bool, error) {
num := strings.Replace(insee.InseeNumber, "2A", "19", 1) r := strings.NewReplacer(
num = strings.Replace(num, "2B", "18", 1)[:len(num)-2] "2A", "19",
"2B", "18",
)
num := r.Replace(insee.InseeNumber[:len(insee.InseeNumber)-2])
numInt, err := strconv.Atoi(num) numInt, err := strconv.Atoi(num)
if err != nil { if err != nil {
return false, err return false, err
@ -98,53 +128,56 @@ func (insee InseeData) IsValid() (bool, error) {
} }
func (insee InseeData) String() string { func (insee InseeData) String() string {
var message []string var result []string
result = append(result, insee.InseeNumber)
var line string
valid, err := insee.IsValid() valid, err := insee.IsValid()
if err != nil { if err != nil {
return err.Error() line = "Erreur lors de la vérification de la validité : " + err.Error()
} } else if valid {
if valid { line = "Le numéro est valide."
message = append(message, "The number is valid.")
} else { } else {
message = append(message, "The number is invalid.") line = "Le numéro est invalide."
} }
msg := fmt.Sprintf("You're a %s, born in %s, probably in %d.", insee.Gender, insee.Month, insee.Year) result = append(result, line)
message = append(message, msg) var one, born string
if insee.Gender == Male {
one = "un"
born = "né"
} else {
one = "une"
born = "née"
}
line = fmt.Sprintf("Vous êtes %s %s, %s en %s probablement en %d.", one, insee.Gender, born, frenchMonth(insee.Month), insee.Year)
result = append(result, line)
line = ""
var zoneType string var zoneType string
var line string
if insee.Foreign { if insee.Foreign {
zoneType = "country" zoneType = "ce pays"
line = "You were born outside France, " if len(insee.Countries) > 1 {
country, present := countries["99"+insee.Country] line = fmt.Sprintf("Vous êtes %s dans l'un de ces pays/territoires: %s (%s)", born, strings.Join(insee.Countries, ", "), insee.Continent)
continent := continents[insee.Country[0:1]] } else if len(insee.Countries) == 1 {
continent = fmt.Sprintf(" (%s)", continent) line = fmt.Sprintf("Vous êtes %s en %s (%s).", born, insee.Countries[0], insee.Continent)
if present && len(country) > 1 {
line += "probably in either one of these countries/territories: "
line += strings.Join(country, ", ")
line += continent
} else if present && len(country) == 1 {
line += fmt.Sprintf("in %s%s", country[0], continent)
} else { } else {
line += "in an unknown country numbered " + insee.Country line = fmt.Sprintf("Vous êtes %s dans un pays inconnu, portant l'identifiant %s.", born, insee.CountryCode)
} }
} else { } else {
zoneType = "city" zoneType = "cette ville"
city, cityPresent := cities[insee.Department+insee.City] if insee.City != (*City)(nil) {
department, depPresent := departments[insee.Department] line = fmt.Sprintf("Vous êtes %s à %s (%s %s, France)", born, insee.City.Name, insee.City.ZipCode, insee.Department)
if !depPresent {
department = "unknown department"
}
if cityPresent {
line = fmt.Sprintf("You were born in %s, %s (%s), France.", city.Name, city.ZipCode, department)
} else { } else {
line = fmt.Sprintf("You were born in an unknown city numbered %s, which is located in %s, in France", insee.City, department) line = fmt.Sprintf("Vous êtes %s dans une ville inconnue portant l'identifiant %s dans le département \"%s\"", born, insee.CityCode, insee.Department)
} }
} }
message = append(message, line) result = append(result, line)
line = fmt.Sprintf("You were the %dth to be born in this %s on this month.", insee.OrderOfBirth, zoneType) line = fmt.Sprintf("Vous êtes la %de personne née dans %s le mois de votre naissance.", insee.OrderOfBirth, zoneType)
message = append(message, line) result = append(result, line)
lineB, err := json.Marshal(insee)
return strings.Join(message, "\n") if err != nil {
line = "Erreur lors de la conversion en JSON: " + err.Error()
} else {
line = string(lineB)
}
result = append(result, line)
return strings.Join(result, "\n")
} }

View file

@ -1,26 +1,179 @@
package data package data
import "testing" import (
"github.com/stretchr/testify/assert"
"testing"
"time"
)
func TestNewInseeData_ValidForeign(t *testing.T) {
assert := assert.New(t)
func TestNewInseeDataValid(t *testing.T) {
number := "269059913116714" number := "269059913116714"
insee, err := NewInseeData(number) insee, err := NewInseeData(number)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
if insee.InseeNumber != number { valid, err := insee.IsValid()
t.Errorf("InseeNumber KO. Got %s, expected %s", insee.InseeNumber, number) if err != nil {
t.Error(err)
} }
foreign := true assert.True(valid)
if insee.Foreign != foreign { assert.Equal(number, insee.InseeNumber)
t.Errorf("Foreign KO. Got %t, expected %t", insee.Foreign, foreign) assert.Equal(Female, insee.Gender)
assert.Equal(1969, insee.Year)
assert.Equal(time.Month(5), insee.Month)
assert.Equal(Unknown, insee.Department)
assert.Nil(insee.City)
assert.True(insee.Foreign)
assert.Equal([]string{"BELGIQUE"}, insee.Countries)
assert.Equal(167, insee.OrderOfBirth)
assert.Equal(14, insee.ControlKey)
assert.Equal("131", insee.CountryCode)
assert.Equal("", insee.CityCode)
assert.Equal("Europe", insee.Continent)
} }
gender := "Female"
if insee.Gender != gender { func TestNewInseeData_InvalidFrench(t *testing.T) {
t.Errorf("Gender KO. Got %s, expected %s", insee.Gender, gender) assert := assert.New(t)
number := "168127982980507"
insee, err := NewInseeData(number)
if err != nil {
t.Error(err)
} }
year := 1969 valid, err := insee.IsValid()
if insee.Year != year { if err != nil {
t.Errorf("Year KO. Got %d, expected %d", insee.Year, year) t.Error(err)
} }
assert.False(valid)
assert.Equal(number, insee.InseeNumber)
assert.Equal(Male, insee.Gender)
assert.Equal(1968, insee.Year)
assert.Equal(time.Month(12), insee.Month)
assert.Equal("Deux-Sèvres", insee.Department)
assert.Nil(insee.City)
assert.False(insee.Foreign)
assert.Equal([]string{"FRANCE"}, insee.Countries)
assert.Equal(805, insee.OrderOfBirth)
assert.Equal(7, insee.ControlKey)
assert.Equal("", insee.CountryCode)
assert.Equal("829", insee.CityCode)
assert.Equal("Europe", insee.Continent)
}
func TestNewInseeData_ValidFrench(t *testing.T) {
assert := assert.New(t)
number := "201120100512334"
insee, err := NewInseeData(number)
if err != nil {
t.Error(err)
}
valid, err := insee.IsValid()
if err != nil {
t.Error(err)
}
assert.True(valid)
assert.Equal(number, insee.InseeNumber)
assert.Equal(Female, insee.Gender)
assert.Equal(2001, insee.Year)
assert.Equal(time.Month(12), insee.Month)
assert.Equal("Ain", insee.Department)
assert.NotNil(insee.City)
assert.Equal("AMBERIEUX-EN-DOMBES", insee.City.Name)
assert.Equal("01330", insee.City.ZipCode)
assert.False(insee.Foreign)
assert.Equal([]string{"FRANCE"}, insee.Countries)
assert.Equal(123, insee.OrderOfBirth)
assert.Equal(34, insee.ControlKey)
assert.Equal(insee.CountryCode, "")
assert.Equal(insee.CityCode, "005")
assert.Equal("Europe", insee.Continent)
}
func TestNewInseeData_ValidMultiCountry(t *testing.T) {
assert := assert.New(t)
number := "144089943287340"
insee, err := NewInseeData(number)
if err != nil {
t.Error(err)
}
valid, err := insee.IsValid()
if err != nil {
t.Error(err)
}
assert.True(valid)
assert.Equal(number, insee.InseeNumber)
assert.Equal(Male, insee.Gender)
assert.Equal(1944, insee.Year)
assert.Equal(time.Month(8), insee.Month)
assert.Equal(Unknown, insee.Department)
assert.Nil(insee.City)
assert.True(insee.Foreign)
expectedCountry := []string{
"PORTO RICO",
"VIERGES DES ETATS-UNIS (ILES)",
"TERR. DES ETATS-UNIS D'AMERIQUE EN AMERIQUE",
}
assert.Equal(expectedCountry, insee.Countries)
assert.Equal("Amérique", insee.Continent)
assert.Equal(873, insee.OrderOfBirth)
assert.Equal(40, insee.ControlKey)
assert.Equal(insee.CountryCode, "432")
assert.Equal(insee.CityCode, "")
}
func TestNewInseeData_ValidFrenchDROM(t *testing.T) {
assert := assert.New(t)
number := "299129742398791"
insee, err := NewInseeData(number)
if err != nil {
t.Error(err)
}
valid, err := insee.IsValid()
if err != nil {
t.Error(err)
}
assert.True(valid)
assert.Equal(number, insee.InseeNumber)
assert.Equal(Female, insee.Gender)
assert.Equal(1999, insee.Year)
assert.Equal(time.Month(12), insee.Month)
assert.Equal("La Réunion", insee.Department)
assert.NotNil(insee.City)
assert.Equal("LES TROIS-BASSINS", insee.City.Name)
assert.Equal("97426", insee.City.ZipCode)
assert.False(insee.Foreign)
assert.Equal([]string{"FRANCE"}, insee.Countries)
assert.Equal(987, insee.OrderOfBirth)
assert.Equal(91, insee.ControlKey)
assert.Equal(insee.CountryCode, "")
assert.Equal(insee.CityCode, "23")
assert.Equal("Europe", insee.Continent)
}
func TestNewInseeData_ValidFrenchCorsica(t *testing.T) {
assert := assert.New(t)
number := "299122A00498723"
insee, err := NewInseeData(number)
if err != nil {
t.Error(err)
}
valid, err := insee.IsValid()
if err != nil {
t.Error(err)
}
assert.True(valid)
assert.Equal(number, insee.InseeNumber)
assert.Equal("Corse-du-Sud", insee.Department)
assert.NotNil(insee.City)
assert.Equal("AJACCIO", insee.City.Name)
assert.Equal("20000", insee.City.ZipCode)
assert.False(insee.Foreign)
assert.Equal([]string{"FRANCE"}, insee.Countries)
assert.Equal(23, insee.ControlKey)
} }

22
data/months.go Normal file
View file

@ -0,0 +1,22 @@
package data
import "time"
var frenchMonths = []string{
"janvier",
"février",
"mars",
"avril",
"mai",
"juin",
"juillet",
"août",
"septembre",
"octobre",
"novembre",
"décembre",
}
func frenchMonth(month time.Month) string {
return frenchMonths[month-1]
}

2
go.mod
View file

@ -1,3 +1,5 @@
module insee_number_translator module insee_number_translator
go 1.16 go 1.16
require github.com/stretchr/testify v1.7.0

11
go.sum Normal file
View file

@ -0,0 +1,11 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=