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
#### 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

File diff suppressed because it is too large Load diff

View file

@ -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")
}

View file

@ -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
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
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=