Translate to french, fix corsica, add more tests, improve output
This commit is contained in:
parent
8272126024
commit
40e48867fd
7 changed files with 37050 additions and 36828 deletions
|
@ -6,13 +6,13 @@ Extract data from INSEE number (France)
|
|||
### From sources
|
||||
#### Run
|
||||
```shell
|
||||
go run . 269059913116714 168127982980507
|
||||
go run . 269059913116714 168127982980507 299122A00498723 299129742398791 144089943287340
|
||||
```
|
||||
|
||||
#### Build & install
|
||||
```shell
|
||||
go install
|
||||
insee_number_translator 269059913116714 168127982980507
|
||||
insee_number_translator 269059913116714 168127982980507 299122A00498723 299129742398791 144089943287340
|
||||
```
|
||||
|
||||
## Data sources
|
||||
|
|
73491
data/cities.go
73491
data/cities.go
File diff suppressed because it is too large
Load diff
|
@ -1,23 +1,31 @@
|
|||
package data
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var Male = "homme"
|
||||
var Female = "femme"
|
||||
var Unknown = "inconnu(e)"
|
||||
|
||||
type InseeData struct {
|
||||
InseeNumber string
|
||||
Gender string
|
||||
Year int
|
||||
Month time.Month
|
||||
Department string
|
||||
City string
|
||||
Foreign bool
|
||||
Country string
|
||||
OrderOfBirth int
|
||||
ControlKey int
|
||||
InseeNumber string `json:"insee_number"`
|
||||
Gender string `json:"gender"`
|
||||
Year int `json:"year"`
|
||||
Month time.Month `json:"month"`
|
||||
Department string `json:"department"`
|
||||
City *City `json:"city"`
|
||||
CityCode string `json:"city_code"`
|
||||
Foreign bool `json:"foreign"`
|
||||
Countries []string `json:"countries"`
|
||||
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) {
|
||||
|
@ -25,23 +33,39 @@ func NewInseeData(inseeNumber string) (*InseeData, error) {
|
|||
return nil, fmt.Errorf("provided insee number must contain 15 characters")
|
||||
}
|
||||
num := inseeNumber
|
||||
department := num[5:7]
|
||||
city := num[7:10]
|
||||
if department == "97" || department == "98" {
|
||||
department = num[5:8]
|
||||
city = num[8:10]
|
||||
departmentCode := num[5:7]
|
||||
cityCode := num[7:10]
|
||||
if departmentCode == "97" || departmentCode == "98" {
|
||||
departmentCode = num[5:8]
|
||||
cityCode = num[8:10]
|
||||
}
|
||||
dep, err := strconv.Atoi(department)
|
||||
if err != nil {
|
||||
dep, err := strconv.Atoi(departmentCode)
|
||||
if err != nil && departmentCode != "2A" && departmentCode != "2B" {
|
||||
return nil, err
|
||||
}
|
||||
foreign := false
|
||||
country := "FR"
|
||||
if (dep >= 91 && dep <= 96) || dep == 99 {
|
||||
var city *City
|
||||
var department string
|
||||
countries_ := []string{"FRANCE"}
|
||||
countryCode := ""
|
||||
continent := "Europe"
|
||||
foreign := (dep >= 91 && dep <= 96) || dep == 99
|
||||
if foreign {
|
||||
foreign = true
|
||||
country = city
|
||||
city = "unknown"
|
||||
department = "unknown"
|
||||
countryCode = cityCode
|
||||
cityCode = ""
|
||||
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])
|
||||
if err != nil {
|
||||
|
@ -68,9 +92,9 @@ func NewInseeData(inseeNumber string) (*InseeData, error) {
|
|||
}
|
||||
gender := num[0:1]
|
||||
if gender == "1" {
|
||||
gender = "Male"
|
||||
gender = Male
|
||||
} else {
|
||||
gender = "Female"
|
||||
gender = Female
|
||||
}
|
||||
return &InseeData{
|
||||
InseeNumber: num,
|
||||
|
@ -79,16 +103,22 @@ func NewInseeData(inseeNumber string) (*InseeData, error) {
|
|||
Month: month,
|
||||
Department: department,
|
||||
City: city,
|
||||
CityCode: cityCode,
|
||||
Foreign: foreign,
|
||||
Country: country,
|
||||
Countries: countries_,
|
||||
CountryCode: countryCode,
|
||||
Continent: continent,
|
||||
OrderOfBirth: order,
|
||||
ControlKey: controlKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (insee InseeData) IsValid() (bool, error) {
|
||||
num := strings.Replace(insee.InseeNumber, "2A", "19", 1)
|
||||
num = strings.Replace(num, "2B", "18", 1)[:len(num)-2]
|
||||
r := strings.NewReplacer(
|
||||
"2A", "19",
|
||||
"2B", "18",
|
||||
)
|
||||
num := r.Replace(insee.InseeNumber[:len(insee.InseeNumber)-2])
|
||||
numInt, err := strconv.Atoi(num)
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
@ -98,53 +128,56 @@ func (insee InseeData) IsValid() (bool, error) {
|
|||
}
|
||||
|
||||
func (insee InseeData) String() string {
|
||||
var message []string
|
||||
var result []string
|
||||
result = append(result, insee.InseeNumber)
|
||||
var line string
|
||||
valid, err := insee.IsValid()
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
if valid {
|
||||
message = append(message, "The number is valid.")
|
||||
line = "Erreur lors de la vérification de la validité : " + err.Error()
|
||||
} else if valid {
|
||||
line = "Le numéro est valide."
|
||||
} 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)
|
||||
message = append(message, msg)
|
||||
|
||||
result = append(result, line)
|
||||
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 line string
|
||||
if insee.Foreign {
|
||||
zoneType = "country"
|
||||
line = "You were born outside France, "
|
||||
country, present := countries["99"+insee.Country]
|
||||
continent := continents[insee.Country[0:1]]
|
||||
continent = fmt.Sprintf(" (%s)", 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)
|
||||
zoneType = "ce pays"
|
||||
if len(insee.Countries) > 1 {
|
||||
line = fmt.Sprintf("Vous êtes %s dans l'un de ces pays/territoires: %s (%s)", born, strings.Join(insee.Countries, ", "), insee.Continent)
|
||||
} else if len(insee.Countries) == 1 {
|
||||
line = fmt.Sprintf("Vous êtes %s en %s (%s).", born, insee.Countries[0], insee.Continent)
|
||||
} 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 {
|
||||
zoneType = "city"
|
||||
city, cityPresent := cities[insee.Department+insee.City]
|
||||
department, depPresent := departments[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)
|
||||
zoneType = "cette ville"
|
||||
if insee.City != (*City)(nil) {
|
||||
line = fmt.Sprintf("Vous êtes %s à %s (%s %s, France)", born, insee.City.Name, insee.City.ZipCode, insee.Department)
|
||||
} 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)
|
||||
line = fmt.Sprintf("You were the %dth to be born in this %s on this month.", insee.OrderOfBirth, zoneType)
|
||||
message = append(message, line)
|
||||
|
||||
return strings.Join(message, "\n")
|
||||
result = append(result, line)
|
||||
line = fmt.Sprintf("Vous êtes la %de personne née dans %s le mois de votre naissance.", insee.OrderOfBirth, zoneType)
|
||||
result = append(result, line)
|
||||
lineB, err := json.Marshal(insee)
|
||||
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")
|
||||
}
|
||||
|
|
|
@ -1,26 +1,179 @@
|
|||
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"
|
||||
insee, err := NewInseeData(number)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if insee.InseeNumber != number {
|
||||
t.Errorf("InseeNumber KO. Got %s, expected %s", insee.InseeNumber, number)
|
||||
valid, err := insee.IsValid()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
foreign := true
|
||||
if insee.Foreign != foreign {
|
||||
t.Errorf("Foreign KO. Got %t, expected %t", insee.Foreign, foreign)
|
||||
assert.True(valid)
|
||||
assert.Equal(number, insee.InseeNumber)
|
||||
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 {
|
||||
t.Errorf("Gender KO. Got %s, expected %s", insee.Gender, gender)
|
||||
|
||||
func TestNewInseeData_InvalidFrench(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
number := "168127982980507"
|
||||
insee, err := NewInseeData(number)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
year := 1969
|
||||
if insee.Year != year {
|
||||
t.Errorf("Year KO. Got %d, expected %d", insee.Year, year)
|
||||
valid, err := insee.IsValid()
|
||||
if err != nil {
|
||||
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
22
data/months.go
Normal 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
2
go.mod
|
@ -1,3 +1,5 @@
|
|||
module insee_number_translator
|
||||
|
||||
go 1.16
|
||||
|
||||
require github.com/stretchr/testify v1.7.0
|
||||
|
|
11
go.sum
Normal file
11
go.sum
Normal 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=
|
Loading…
Reference in a new issue