Alfa Battle: cómo fue, grabación de conferencias y lista de tareas

A principios de junio, lanzamos Alfa Battle para desarrolladores de Java. Es hora de hablar sobre cómo fue todo, compartir videos útiles de los ponentes de la conferencia de stream "Coding of the Future" (Alfa-Bank, Beeline, X5 Retail Group) y mostrar nuestras tareas. Por cierto, sobre las tareas. O lo exageramos y sobrestimamos a los posibles participantes, o el clima era regular, en general, de 1498 participantes de 50 ciudades, nadie resolvió completamente todos los problemas (5 piezas). Por tanto, debajo del corte encontrarás todas las tareas con una descripción y, si quieres resolverlas, podrás hacerlo sin plazos. Con mucho gusto invitaremos a quienes dominen







... Al final de la publicación, sobre una nueva estrategia para contratar especialistas. Hubo un momento en que la tecnología de la información de Alfa-Bank se concentraba principalmente en tres ciudades: Moscú, San Petersburgo y Ekaterimburgo. Ahora podemos mirar a personas de todo el país. Y no solo.



Gracias a todos los que respondieron, hubo más de 1,500 de esas personas, de las cuales 198 llegaron a la final y mostraron los mejores resultados. Sí, no fue fácil: las tareas resultaron ser más difíciles de lo que muchos participantes esperaban, y el formato del campeonato en línea con transmisión de conferencias, francamente, fue tenso. Aún así, 5 horas de programación en línea no es una experiencia retro en un equipo.



En total, tres ganadores que recibieron un premio en efectivo, así como invitaciones de trabajo para nosotros y para los socios del campeonato. Aquí están:



1er lugar: Mikhail Burshtein, Moscú (250,000 rublos)

2do lugar: Alexander Ilyushechkin, Moscú (150,000 rublos)

3er lugar: Pavel Lyubinsky, San Petersburgo (100,000 rublos)



Tareas



# 1 ¿Dónde está el cajero automático?



Detalles de la tarea

Condición



-.

REST API IP:8080.

API – api.json.



- API .

: api.alfabank.ru/node/238

API .

: api.alfabank.ru/start



* IP — IP .

* : github.com/evgenyshiryaev/alfa-battle-resources/tree/master/task1





1. deviceId



: GET IP:8080/atms/{deviceId}

:

— 200 AtmResponse

— 404 ErrorResponse ( )



:



GET http://IP:8080/atms/153463
200
{
  "deviceId": 153463,
  "latitude": "55.6610213",
  "longitude": "37.6309405",
  "city": "",
  "location": " ., 4, . 10",
  "payments": false
}




:



GET http://IP:8080/atms/1
404
{
  “status”: “atm not found”
}




18 .



2. (-)



- — .

3 ! -.



payments=true, (. - API ATMServices).



: GET IP:8080/atms/nearest?latitude=string&longitude=string&payments=boolean

: 200 AtmResponse



:
GET http://IP:8080/atms/nearest?latitude=55.66&longitude=37.63
200
{
  "deviceId": 153463,
  "latitude": "55.6610213",
  "longitude": "37.6309405",
  "city": "",
  "location": " ., 4, . 10",
  "payments": false
}




:



GET http://IP:8080/atms/nearest?latitude=55.66&longitude=37.63&payments=true
200
{
  "deviceId": 210612,
  "latitude": "55.66442",
  "longitude": "37.628051",
  "city": "",
  "location": " , . 14",
  "payments": true
}




36 .



3.



- .

, .



: GET IP:8080/atms/nearest-with-alfik?latitude=string&longitude=string&alfik=int

: 200 [AtmResponse]



, WebSocket STOMP .



:



mkdir task1 ; cd task1

wget https://raw.githubusercontent.com/evgenyshiryaev/alfa-battle-resources/master/task1/docker-compose.yml

docker-compose up -d




( task1):

docker-compose down

: ws://IP:8100

: { “deviceId”: 0 }

/topic/alfik: { “deviceId”: 0, “alfik”: 0 }



:
 GET http://IP:8080/atms/nearest-with-alfik?latitude=55.66&longitude=37.63&alfik=300000
200
[{
  "deviceId": 153463,
  "latitude": "55.6610213",
  "longitude": "37.6309405",
  "city": "",
  "location": " ., 4, . 10",
  "payments": false
}]


(.. 153463 — 383026 )



:
GET http://IP:8080/atms/nearest-with-alfik?latitude=55.66&longitude=37.63&alfik=400000
200
[{
  "deviceId": 153463,
  "latitude": "55.6610213",
  "longitude": "37.6309405",
  "city": "",
  "location": " ., 4, . 10",
  "payments": false
},
{
  “deviceId": 153465,
  "latitude": "55.6602801",
  "longitude": "37.633823",
  "city": "",
  "location":"  ., 18",
  "payments": false
}]


( , )



# 2 Analízalo



Detalles de la tarea



Kafka RAW_PAYMENTS .

docker IP:29092 .



Kafka.



:

mkdir task2 ; cd task2

wget https://raw.githubusercontent.com/evgenyshiryaev/alfa-battle-resources/master/task2/data.txt

wget https://raw.githubusercontent.com/evgenyshiryaev/alfa-battle-resources/master/task2/docker-compose.yml

wget https://raw.githubusercontent.com/evgenyshiryaev/alfa-battle-resources/master/task2/start.sh

bash start.sh


.



( task2):

docker-compose down



* IP — IP .

* : github.com/evgenyshiryaev/alfa-battle-resources/tree/master/task2



:



key1:{"ref":"U030306190000188", "categoryId":1, "userId":"XAABAA", "recipientId":"XA3SZV", "desc":"  ", "amount":10.0}




, key1 — .

.



:

  • Kafka.
  • .
  • REST API . 8081.




RAW_PAYMENTS. .



, .



, Kafka .



.





, , . , ( , - ).



:

  1. consumer-group-id. .
  2. consumer-group. , , ,




docker exec -i broker kafka-consumer-groups --bootstrap-server broker:9092 --all-groups --all-topics --reset-offsets --to-earliest --execute



start.sh, . ,



Swagger-



Swagger- api-swagger.json .





:



key1:{"ref":"ref1", "categoryId":1, "userId":"User_1", "recipientId":"User_2", "desc":" _1", "amount":10.0}
key2:{"ref":"ref2", "categoryId":2, "userId":"User_1", "recipientId":"User_2", "desc":" _2", "amount":350.56}
key3:{"ref":"ref3", "categoryId":1, "userId":"User_1", "recipientId":"User_2", "desc":" _3", "amount":700.0}
key4:{"ref":"ref4", "categoryId":3, "userId":"User_1", "recipientId":"User_2", "desc":" _4", "amount":5.99}
key5:{"ref":"ref5", "categoryId":1, "userId":"User_1", "recipientId":"User_2", "desc":" _5", "amount":10.0}
key6:{"ref":"ref6", "categoryId":2, "userId":"User_2", "recipientId":"User_3", "desc":" _6", "amount":350.56}
key7:{"ref":"ref7", "categoryId":1, "userId":"User_1", "recipientId":"User_2", "desc":" _7", "amount":890.0}
key8:{"ref":"ref8", "categoryId":3, "userId":"User_3", "recipientId":"User_2", "desc":" _8", "amount":35.99}
key9:{"ref":"ref9", "categoryId":1, "userId":"User_1", "recipientId":"User_2", "desc":" _9", "amount":890.0}
key10:{"ref":"ref10", "categoryId":3, "userId":"User_3", "recipientId":"User_2", "desc":" _10", "amount":35.9910}
key11:{"ref":"ref11", "categoryId":1, "userId":"User_1", "recipientId":"User_2", "desc":" _11", "amount":10.0}
key12:{"ref":"ref12", "categoryId":2, "userId":"User_2", "recipientId":"User_3", "desc":" _12", "amount":350.56}
key13:{"ref":"ref13", "categoryId":1, "userId":"User_1", "recipientId":"User_2", "desc":" _13", "amount":10.0}
key14:{"ref":"ref14", "categoryId":2, "userId":"User_2", "recipientId":"User_3", "desc":" _14", "amount":350.56}
key15:{"ref":"ref15", "categoryId":4, "userId":"User_1", "recipientId":"User_4", "desc":" _15", "amount":15.00}




1.



( categoryId).

, .



.



GET IP:8081/admin/health



200



:

{"status":"UP"}

<h4>GET http://IP:8081/analytic</h4>
200








:

[
  {
    "userId": "User_3",
    "totalSum": 71.981,
    "analyticInfo": {
      "3": {
        "min": 35.99,
        "max": 35.991,
        "sum": 71.981
      }
    }
  },
  {
    "userId": "User_2",
    "totalSum": 1051.68,
    "analyticInfo": {
      "2": {
        "min": 350.56,
        "max": 350.56,
        "sum": 1051.68
      }
    }
  },
  {
    "userId": "User_1",
    "totalSum": 2891.55,
    "analyticInfo": {
      "1": {
        "min": 10,
        "max": 890,
        "sum": 2520
      },
      "2": {
        "min": 350.56,
        "max": 350.56,
        "sum": 350.56
      },
      "3": {
        "min": 5.99,
        "max": 5.99,
        "sum": 5.99
      },
      "4": {
        "min": 15,
        "max": 15,
        "sum": 15
      }
    }
  }
]




analyticInfo Id .



GET IP:8081/analytic/{userId}



— 200

— 404 + {«status»:”user not found"} ( )







:

GET http://IP:8081/analytic/User_1




:



{
  "userId": "User_1",
  "totalSum": 2891.55,
  "analyticInfo": {
    "1": {
      "min": 10,
      "max": 890,
      "sum": 2520
    },
    "2": {
      "min": 350.56,
      "max": 350.56,
      "sum": 350.56
    },
    "3": {
      "min": 5.99,
      "max": 5.99,
      "sum": 5.99
    },
    "4": {
      "min": 15,
      "max": 15,
      "sum": 15
    }
  }
}




40 .



2.



. :





GET IP:8081/analytic/{userId}/stats



— 200

— 404 + {«status»:”user not found"} ( )

.



:

GET http://IP:8081/analytic/User_1/stats
 :
{
  "oftenCategoryId": 1,
  "rareCategoryId": 2,
  "maxAmountCategoryId": 1,
  "minAmountCategoryId": 3
}




60



3.



.



:

  • , , (recipientId userId )




, .



GET IP:8081/analytic/{userId}/templates



— 200

— 404 + {«status»:”user not found"} ( )

, .



:

GET http://IP:8081/analytic/User_1/templates
 :
[
  {
    "recipientId": "User_2",
    "categoryId": 1,
    "amount": 10
  }
]




# 3 Caja libre



Detalles de la tarea



- .

REST API IP:8082.

API – api.json.

, , , , .



PostgreSQL.

PostgreSQL:



mkdir task3 ; cd task3

wget https://raw.githubusercontent.com/evgenyshiryaev/alfa-battle-resources/master/task3/docker-compose.yml

wget https://raw.githubusercontent.com/evgenyshiryaev/alfa-battle-resources/master/task3/Dockerfile

wget https://raw.githubusercontent.com/evgenyshiryaev/alfa-battle-resources/master/task3/init_db.sql

docker-compose up -d


( task3):

docker-compose down

: IP:5432

DB: alfa_battle

Auth: alfa_battle / qwe123



* IP — IP .

* : github.com/evgenyshiryaev/alfa-battle-resources/tree/master/task3





1. id



: GET IP:8082/branches/{id}

:

— 200 Branches

— 404 ErrorResponse ( )



:
GET http://IP:8082/branches/612
200
{
  "id": 612,
  "title": "",
  "lon": 37.6329,
  "lat": 55.7621,
  "address": " ., 13, . 1"
}




:
 GET http://IP:8082/branches/1
404
{
  “status”: “branch not found”
}




8 .



2. (-)



-, , 1.



.



, Latitude Longitude.



: GET IP:8082/branches/lat=string&lon=string

: 200 Branches



:
GET http://IP:8082/branches/lat=55.773284&lon=37.624125
200
{
  "id": 631,
  "title": " ",
  "lon": 37.6227,
  "lat": 55.7695,
  "address": " ., 16/1",
  "distance": 430
}




Distance — , , .



28 .



3.



, — , , , , .



.



: GET IP:8082/branches/{id}/predict?dayOfWeek=int&hourOfDay=int

:

— 200 BranchesWithPredicting

— 404 ErrorResponse ( )



:
GET http://IP:8082/branches/612/predict?dayOfWeek=1&hourOfDay=14
200
{
  "id": 612,
  "title": "",
  "lon": 37.6329,
  "lat": 55.7621,
  "address": " ., 13, . 1",
  "dayOfWeek": 1,
  "hourOfDay": 14,
  "predicting": 117
}




dayOfWeek — , 1, 7

hourOfDay — 0 23

Predicting — , , .



:
GET http://IP:8082/branches/1/predict?dayOfWeek=1&hourOfDay=14
404
{
  “status”: “branch not found”
}


.

, , apache-commons-math3



# 4 Préstamos elásticos



Detalles de la tarea



1 2 JSON:



person.json — , :

{
     "ID":"29",
     "DocId":"702821510",
     "FIO":"Phoebe Whitehouse",
     "Birthday":"7/12/1971",
     "Salary":"201.02",
     "Gender":"F"
}


, :

ID — ,

DocId — ( 9 )

FIO —

Birthday — MM/dd/yyyy

Salary — , , .. 201.02 20102 .

Gender —



loans.json — , :

{
     "Loan":"631553",
     "PersonId":"68",
     "Amount":"201.02",
     "StartDate":"6/1/2019",
     "Period":"1"
}


, :

Loan — ,

PersonId —

Amount — , , .. 201.02 20 102

StartDate — MM/dd/yyyy

Period —





, ElasticSearch .

REST- ElasticSearch, . IP:8083



ElasticSearch:

mkdir task4 ; cd task4

wget https://raw.githubusercontent.com/evgenyshiryaev/alfa-battle-resources/master/task4/docker-compose.yml

docker-compose up -d


ElasticSearch IP:9200



( task4):

docker-compose down



* IP — IP .

* : github.com/evgenyshiryaev/alfa-battle-resources/tree/master/task4





ElasticSearch :



persons

  • Birthday — 1945-05-03
  • Salary — ,




loans

  • PersonId — , Document, DocId Persons.
  • Amount — , .
  • StartDate — , 1945-05-03
  • Period — ,








GET IP:8083/admin/health

200

{«status»:«UP»}





ElasicSearch.



POST IP:8083/loans/loadPersons

200

{«status»:«OK»}



ElasicSearch.

, Document, ElasticSearch .



POST IP:8083/loans/loadLoans

200

{«status»:«OK»}





GET http://IP:8083/loans/getPerson/855406656/
200
{
   "docid": "855406656",
   "fio": "Celina Jackson",
   "birthday": "1961-05-22",
   "salary": 69106.0,
   "gender": "F"
}




400 ( )

{

«status»: «person not found»

}





GET http://IP:8083/loans/getLoan/692826/
200
{
   "loan": "692826",
   "amount": 448900,
   "document": "027665876",
   "startdate": "2017-01-16",
   "period": 48
}


400 ( )

{
   "status": "loan not found"
}






, — Document.



GET http://IP:8083/loans/creditHistory/737767072/
200
{
   "countLoan": 4,
   "sumAmountLoans": 1058400.0,
   "loans": [
       {
           "loan": "434224",
           "amount": 7100,
           "document": "737767072",
           "startdate": "2019-09-18",
           "period": 12
       },
       {
           "loan": "917105",
           "amount": 283600,
           "document": "737767072",
           "startdate": "2019-12-22",
           "period": 12
       },
       {
           "loan": "692147",
           "amount": 300800,
           "document": "737767072",
           "startdate": "2016-08-01",
           "period": 24
       },
       {
           "loan": "145020",
           "amount": 466900,
           "document": "737767072",
           "startdate": "2017-01-16",
           "period": 36
       }
   ]
}




, :

countLoan —

sumAmountLoans —

loans —



,



GET http://IP:8083/loans/creditClosed
200
[
   {
       "loan": "222398",
       "amount": 265400,
       "document": "074658188",
       "startdate": "2017-09-22",
       "period": 12
   },
  
       "loan": "826942",
       "amount": 329400,
       "document": "788117788",
       "startdate": "2016-01-29",
       "period": 48
   },
...
]




, ( ElasticSearch).



GET http://IP:8083/loans/loansSortByPersonBirthday
200
[
   {
       "id": null,
       "docid": "840704451",
       "fio": "John Isaac",
       "birthday": "19.08.1989",
       "salary": 58295.0,
       "gender": "M",
       "loans": [
           {
               "loan": "771916",
               "amount": 337600,
               "document": "840704451",
               "startdate": "2019-11-09",
               "period": 48
           },
           {
               "loan": "504544",
               "amount": 358900,
               "document": "840704451",
               "startdate": "2018-06-10",
               "period": 36
           },
           {
               "loan": "699247",
               "amount": 464400,
               "document": "840704451",
               "startdate": "2018-10-30",
               "period": 36
           },
           {
               "loan": "783101",
               "amount": 139300,
               "document": "840704451",
               "startdate": "2017-02-19",
               "period": 36
           }
       ]
   },
   {
       "id": null,
       "docid": "023665566",
       "fio": "Denny Tanner",
       "birthday": "25.03.1989",
       "salary": 80713.0,
       "gender": "M",
       "loans": [
           {
               "loan": "631553",
               "amount": 403000,
               "document": "023665566",
               "startdate": "2019-06-01",
               "period": 12
           },
           {
               "loan": "598452",
               "amount": 198500,
               "document": "023665566",
               "startdate": "2015-09-28",
               "period": 36
           },
           {
               "loan": "151915",
               "amount": 13600,
               "document": "023665566",
               "startdate": "2019-06-15",
               "period": 12
           },
           {
               "loan": "368342",
               "amount": 350500,
               "document": "023665566",
               "startdate": "2017-02-06",
               "period": 48
           },
           {
               "loan": "633056",
               "amount": 482900,
               "document": "023665566",
               "startdate": "2016-07-01",
               "period": 12
           }
       ]
   },
...
]




# 5 en la aguja promocional



Detalles de la tarea



.

- .

.



REST API IP:8084 :



  • /promo – POST - ( , ). .
  • /receipt – , POST id , (, ), , , .




: /promo, /receipt.



* IP — IP .

* : github.com/evgenyshiryaev/alfa-battle-resources/tree/master/task5





  1. CSV :
  2. API – api.yml






- , -, .

-, - .

- , -, .



2 RoundingMode.HALF_EVEN.



!!! , code review !!!





1. -



:

: POST IP:8084/promo

{}

: 200

: POST IP:8084/receipt

{

«shopId»: 1,

«loyaltyCard»: false,

«positions»:

[

{

«itemId»: «3432166»,

«quantity»: 1

}

]

}

: 200

{

«total»: 141.99,

«discount»: 0.00,

«positions»:

[

{

«id»: «3432166»,

«name»: «...G11 Green .1»,

«price»: 141.99,

«regularPrice»: 141.99

}

]

}



8 .



2. -



/promo - “ ” (LoyaltyCardRule). , .



- , /receipt loyaltyCard=true - , id .



:

: POST IP:8084/promo

{
  "loyaltyCardRules": 
  [
    {
      "shopId": -1,
      "discount": 0.03
    },
    {
      "shopId": 2,
      "discount": 0.05
    }
  ]
}


: 200



: POST IP:8084/receipt

{
  "shopId": 1,
  "loyaltyCard": false,
  "positions":
  [
    {
      "itemId": "3432166",
      "quantity": 1
    }
  ]
}
: 200
{
  "total": 137.73,
  "discount": 4.26,
  "positions":
  [
    {
      "id": "3432166",
      "name": "...G11 Green .1",
      "price": 137.73,
      "regularPrice": 141.99
    }
  ]
}


16 .



3. - N+k



/promo - LoyaltyCardRule ItemCountRule. , .

N+k , N ID k . N=3, k=2:



Grabaciones de video de informes







Los 16 informes de nuestros chicos y socios de Beeline y X5 Retail Group se pueden ver en el sitio web del evento .



Entonces, ¿qué pasa con la contratación?



Damir Battulin, nuestro director del departamento de desarrollo de canales online, habló sobre la contratación, las iniciativas estratégicas del banco, los principios del trabajo en equipo en los proyectos y los criterios de elección de nuevos especialistas para el desarrollo de la digitalización.



: , - . , , , , . . , .



. , . , , . , . .




Puede ver todas nuestras vacantes actuales (TI, marketing, RR.HH., etc.) en esta página.



Para los amantes de los detalles: toda la entrevista
- 100 . . , , . , - -, , .



— -, 2021 . . , , — . 7 12 . , , .



, - , . , , , , . , , ( , ): — , , -. , .



— ?



— , -.



— , , .



— . , . , , , .



, , — smart branch. – 400 . , , .



? , . , . , . , . , , .



, . , , , .



, , -. . , , , . , , , .



— ?



— : , - . , , , , . . , .



. , . , , . , . .



— ?



— – time to market. . , . . , , .



, , . smart branch , .



— , ?



— -. , . , . .

. , . — , . , . - , . . , : iOS- Lead product manager iOS, Chief product owner .



. 56, . 60%, 100%.



— ?



— , . , .

, chief product owner. , . – , , . , . , - , , , .



— , . ?



— , , , . , , , . .

. , , .



— ?



— – . . . , , , .



– . , -, . , , . , .



, , , , , . — , , , . .




All Articles