“Soccer Scouting System” with Neo4j, part 6

We have players, clubs, teams and leagues. The next step is to add the review system.

soccerscouting-4

We need a scout, who reviews the players. This scout can be independent or working as coach for a club or other organization.
In the example below, this scout is working as coach for the club. I have added a property named ‘level’ in the scout node, which can be used to add weight to the review. The more experienced the scout the higher the level.

The scout writes a review, with a rating (1 to 5) and a review description. That review is of a specific performance of the player, it could a (test-) match, training or more generic, like a season.

This is the code to create to reviews, for both players, already available in the demo.

// Create scout     
CREATE
     (scout:Scout {name:'Scout', function:'Head scout', level:5}),
     (scout)-[:WORKS_FOR]->(myc)

// Create review for goalie1 
CREATE 
    (perf1:Performance {type:'Training', date: 20150516}),
    (review1:Review {rating: 5, review: 'Excellent goalie'}),
    (scout)-[:WROTE_REVIEW]->(review1),
    (review1)-[:REVIEW_OF]->(perf1),
    (perf1)-[:PERFORMANCE_OF]->(goalie1)

// Create review for player1
CREATE 
    (perf2:Performance {type:'Match', date: 20150516}),
    (review2:Review {rating: 4, review: 'Good defender'}),
    (scout)-[:WROTE_REVIEW]->(review2),
    (review2)-[:REVIEW_OF]->(perf2),
    (perf2)-[:PERFORMANCE_OF]->(player1)

When add above to the existing graph, it looks like this:

Review system

“Soccer Scouting System” with Neo4j, part 5

So far we have the following:

A connected League structure

soccerscouting-1

A connected Player, Team and Club structure:

soccerscouting-2

We need to connect these together, with the “TAKING_PART” connection.

Added the following code to the one from yesterday:

// Init teams

CREATE (myc:Club {id:'myc', name:'My Club'})
CREATE (teamA:Team {id:'mycTeamA', name:'Team A', season:'2015-2016'})
CREATE
    (teamA)-[:REPRESENTS {season:'2015-2016'}]->(myc),
    (teamA)-[:TAKING_PART]->(tk1516)
    
CREATE (teamB:Team {id:'mycTeamB', name:'Team B', season:'2015-2016'})
CREATE
    (teamB)-[:REPRESENTS {season:'2015-2016'}]->(myc),
    (teamB)-[:TAKING_PART]->(eka1516)
    
// CREATE Players
    
CREATE (goalie1:Player {name:'Goalie One', birthday:20000101, position:'Goalie', handedness:'right'})
CREATE (player1:Player {name:'Left Defender', birthday:20010101, position:'Left defender', handedness:'left'})
    
CREATE
    (goalie1)-[:SELECTED_FOR]->(teamA),  
    (player1)-[:SELECTED_FOR]->(teamB)

Results in following graph:

step5

“Soccer Scouting System” with Neo4j, part 4 -update

Decided to rewrite the Leagues CREATE statement. Now you can see the relation between each league per season.

CREATE (t:Timeline {name:'Timeline'})
CREATE (s1:Season {value:'2014-2015'})
CREATE (bl:League {id:'bl', name:'BeNe League', season:'2014-2015'})
CREATE (tk1415:League {id:'tk', name:'Topklasse', season:'2014-2015'})
CREATE (hka1415:League {id:'hka', name:'Hoofdklasse A (zat)', season:'2014-2015'})
CREATE (hkb1415:League {id:'hkb', name:'Hoofdklasse B (zon)', season:'2014-2015'})
CREATE (eka1415:League {id:'eka', name:'Eerste klasse A (zat)', season:'2014-2015'})
CREATE (ekb1415:League {id:'ekb', name:'Eerste klasse B (zat)', season:'2014-2015'})
CREATE (ekc1415:League {id:'ekc', name:'Eerste klasse C (zon)', season:'2014-2015'})
CREATE (ekd1415:League {id:'ekd', name:'Eerste klasse D (zon)', season:'2014-2015'})

CREATE 
	(t)-[:SEASON]->(s1),
	(s1)-[:LEAGUES]->(bl),
	(bl)-[:LOWER_LEVEL]->(tk1415),
	(tk1415)-[:LOWER_LEVEL]->(hka1415),
	(tk1415)-[:LOWER_LEVEL]->(hkb1415),
	(hka1415)-[:LOWER_LEVEL]->(eka1415),
	(hka1415)-[:LOWER_LEVEL]->(ekb1415),
	(hkb1415)-[:LOWER_LEVEL]->(ekc1415),
	(hkb1415)-[:LOWER_LEVEL]->(ekd1415)

CREATE (s2:Season {value:'2015-2016'})
CREATE (ed1516:League {id:'ed', name:'Eredivisie', season:'2015-2016'})
CREATE (tk1516:League {id:'tk', name:'Topklasse', season:'2015-2016'})
CREATE (hka1516:League {id:'hka', name:'Hoofdklasse A (zat)', season:'2015-2016'})
CREATE (hkb1516:League {id:'hkb', name:'Hoofdklasse B (zon)', season:'2015-2016'})
CREATE (eka1516:League {id:'eka', name:'Eerste klasse A (zat)', season:'2015-2016'})
CREATE (ekb1516:League {id:'ekb', name:'Eerste klasse B (zat)', season:'2015-2016'})
CREATE (ekc1516:League {id:'ekc', name:'Eerste klasse C (zon)', season:'2015-2016'})
CREATE (ekd1516:League {id:'ekd', name:'Eerste klasse D (zon)', season:'2015-2016'})

CREATE 
	(t)-[:SEASON]->(s2),
	(s2)-[:LEAGUES]->(ed1516),	
	(ed1516)-[:LOWER_LEVEL]->(tk1516),
	(tk1516)-[:LOWER_LEVEL]->(hka1516),
	(tk1516)-[:LOWER_LEVEL]->(hkb1516),
	(hka1516)-[:LOWER_LEVEL]->(eka1516),
	(hka1516)-[:LOWER_LEVEL]->(ekb1516),
	(hkb1516)-[:LOWER_LEVEL]->(ekc1516),
	(hkb1516)-[:LOWER_LEVEL]->(ekd1516)

This results in following picture:

intLeague-2

“Soccer Scouting System” with Neo4j, part 4

To have an indication on what level the players are playing, it’s useful to know at what league level the team, they play for, is playing.

As an example, since I am currently working for a women team, I have used the league structure used for women soccer in the Netherlands, the first four levels.
This is the structure of leagues from top to the fourth level:competitieThe toplevel is named ‘Eredivisie’. I decided not to translate the names. The ‘Eredivisie’ is the highest level, but only consists of teams that are part of a professional soccer club, like Ajax or PSV. One level below the ‘Eredivisie’ is the highest amateur league named, ‘Topklasse’. Unlike with the men soccer, here there is only one ‘Topklasse’.
One step below the ‘Topklasse’, we have two leagues named ‘Hoofdklasse’, one for the teams playing on Saturday (‘zaterdag’) and one for the teams playing on Sunday (‘zondag’).
The fourth level is named ‘Eerste Klasse’, two leagues for Saturday (A and B) and two for Sunday (C and D).

You can extend this with the next level, but for the example I am using this is enough.

What do we know about these leagues?
Well, the formation of teams is different each season, so we need to add season dependency in our graph, we need a description of a team for each season.

CREATE (t:Timeline {name:'Timeline'}),
    (s1:Season {value:'2014-2015'}),
    (t)-[:SEASON]->(s1),
    (bl:League {id:'bl', name:'BeNe League', season:'2014-2015'}),
    (s1)-[:LEAGUE]->(bl),
    (tk1415:League {id:'tk', name:'Topklasse', season:'2014-2015'}),
    (s1)-[:LEAGUE]->(tk1415),
    (bl)-[:LOWER_LEVEL]->(tk1415),
    (hka1415:League {id:'hka', name:'Hoofdklasse A (zat)', season:'2014-2015'}),
    (s1)-[:LEAGUE]->(hka1415),
    (tk1415)-[:LOWER_LEVEL]->(hka1415),
    (hkb1415:League {id:'hkb', name:'Hoofdklasse B (zon)', season:'2014-2015'}),
    (s1)-[:LEAGUE]->(hkb1415),
    (tk1415)-[:LOWER_LEVEL]->(hkb1415),
    (eka1415:League {id:'eka', name:'Eerste klasse A (zat)', season:'2014-2015'}),
    (s1)-[:LEAGUE]->(eka1415),
    (hka1415)-[:LOWER_LEVEL]->(eka1415),
    (ekb1415:League {id:'ekb', name:'Eerste klasse B (zat)', season:'2014-2015'}),
    (s1)-[:LEAGUE]->(ekb1415),
    (hka1415)-[:LOWER_LEVEL]->(ekb1415),
    (ekc1415:League {id:'ekc', name:'Eerste klasse C (zon)', season:'2014-2015'}),
    (s1)-[:LEAGUE]->(ekc1415),
    (hkb1415)-[:LOWER_LEVEL]->(ekc1415),
    (ekd1415:League {id:'ekd', name:'Eerste klasse D (zon)', season:'2014-2015'}),
    (s1)-[:LEAGUE]->(ekd1415),
    (hkb1415)-[:LOWER_LEVEL]->(ekd1415),
//
    (s2:Season {value:'2015-2016'}),
    (t)-[:SEASON]->(s2),
    (ed1516:League {id:'ed', name:'Eredivisie', season:'2015-2016'}),
    (s2)-[:LEAGUE]->(ed),   
    (tk1516:League {id:'tk', name:'Topklasse', season:'2015-2016'}),
    (s1)-[:LEAGUE]->(tk1516),
    (ed1516)-[:LOWER_LEVEL]->(tk1516),
    (hka1516:League {id:'hka', name:'Hoofdklasse A (zat)', season:'2015-2016'}),
    (s1)-[:LEAGUE]->(hka1516),
    (tk1516)-[:LOWER_LEVEL]->(hka1516),
    (hkb1516:League {id:'hkb', name:'Hoofdklasse B (zon)', season:'2015-2016'}),
    (s1)-[:LEAGUE]->(hkb1516),
    (tk1516)-[:LOWER_LEVEL]->(hkb1516),
    (eka1516:League {id:'eka', name:'Eerste klasse A (zat)', season:'2015-2016'}),
    (s1)-[:LEAGUE]->(eka1516),
    (hka1516)-[:LOWER_LEVEL]->(eka1516),
    (ekb1516:League {id:'ekb', name:'Eerste klasse B (zat)', season:'2015-2016'}),
    (s1)-[:LEAGUE]->(ekb1516),
    (hka1516)-[:LOWER_LEVEL]->(ekb1516),
    (ekc1516:League {id:'ekc', name:'Eerste klasse C (zon)', season:'2015-2016'}),
    (s1)-[:LEAGUE]->(ekc1516),
    (hkb1516)-[:LOWER_LEVEL]->(ekc1516),
    (ekd1516:League {id:'ekd', name:'Eerste klasse D (zon)', season:'2015-2016'}),
    (s1)-[:LEAGUE]->(ekd1516),
    (hkb1516)-[:LOWER_LEVEL]->(ekd1516)

Running this Cypher code in Neo4j, it results in following:
intLeague

One option, I haven’t implement yet is that you can connect, each league within a season, to determine the level, by adding for example, a “NEXT_LEVEL” connector.
Next step, adding teams to leagues and players to teams.