AngularFire custom order by ranking - angularjs

I'm trying to sort teams by ranking, using AngularFire and Firebase.
In Firebase I have 4 teams where I store only the name.
I also store matches, which have a reference to both teams disputing that match and the score for each one.
The matches node looks like this:
matches
-KQgphN_5692GySN0Oxz
home_team: teamA
away_team: teamB
score
home: 1
away: 2
-KQlu6XLak6LgAr9cTty
home_team: teamC
away_team: teamD
score
home: 2
away: 2
And the teams node:
teams
teamA
name: "Team A"
teamB
name: "Team B"
teamC
name: "Team C"
teamD
name: "Team D"
So, I need to order these teams by vitories, draws and losses by watching the results in realtime.
I have a ng-repeat that lists teams like this:
<li ng-repeat="team in teams">{{team.name}}</li>
So, how can I order these teams by wins, taking in account that a win is equivalent to 3 points, a draw is 1 point and a loss is 0 points?
With the above matches example, the ranking should be:
1 - Team B
2 - Team C
3 - Team D
4 - Team A

You can order a Firebase Database query by a nested value, as long as that nested value is at a fixed path. This means you'll need to store the score for each team, e.g.
teams
teamA
name: "Team A"
score: 20
teamB
name: "Team B"
score: 12
teamC
name: "Team C"
score: 42
teamD
name: "Team D"
score: 31
With this structure, you can load the top teams in order with:
var leaders = ref.child('teams').orderByChild('score').limitToLast(3);
leaders.on('value', function(snapshot) {
leaders.forEach(function(leaderSnapshot) {
console.log(leaderSnapshot.child('name').val());
});
});
This will print:
Team A
Team D
Team C
So to get the leaderboard, you'll need to invert them.

Related

Neo4j All permutations where node type is distinct in each

What I'm trying to do is generate all the permutations of a collection of nodes but where each node type only appears once per permutation.
For example if I have a graph of u:User, l:Location, d:Device nodes, lets say 3 nodes of each type.
What I want to be able to generate is a collection that might look something like this
User ID: 1, Location ID: 1
User ID: 1, Location ID: 2
User ID: 1, Location ID: 3
User ID: 1, Device ID: 1
User ID: 1, Device ID: 2
User ID: 1, Device ID: 3
User ID: 1, Location ID: 1, Device ID: 1
User ID: 1, Location ID: 1, Device ID: 2
User ID: 1, Location ID: 1, Device ID: 3
User ID: 1, Location ID: 2, Device ID: 1
User ID: 1, Location ID: 2, Device ID: 2
User ID: 1, Location ID: 2, Device ID: 3
And so on, until I have all combinations.
What I don't want to happen is for a valid combination to include any of the node types more than once, so a combination can only have one user, one location and one device.
At the moment I'm using apoc.coll.combinations, but I don't seem to be able to work out a way to stop it from making the node type distinct.
If I were to run
MATCH (l:Location)-[]-(d:Device)-[]-(ur:User)
WITH COLLECT({l:l,ur:ur}) as coll
WITH apoc.coll.combinations(coll,1,size(coll)) as combColl
RETURN combColl
I'd run out of memory because valid combos would be all the locations and all the user risks.
You need to get one item combination per location, device and user using apoc.coll.combinations. Then do UNWIND to combine each of the items. The result is 3X3+3X3+3x3 + 3X3x3 = 54 rows
MATCH (l:Location)
MATCH (d:Device)
MATCH (u:User)
WITH collect(l) as locations, collect(d) as devices, collect(u) as users
WITH apoc.coll.combinations(locations,1,1) as locations, apoc.coll.combinations(devices,1,1) as devices, apoc.coll.combinations(users,1,1) as users
UNWIND locations as location
UNWIND devices as device
UNWIND users as user
CALL {
WITH location, device
RETURN collect(distinct location+device) as cols
UNION ALL
WITH location, user
RETURN collect(distinct location+user) as cols
UNION ALL
WITH device, user
RETURN collect(distinct device+user) as cols
UNION ALL
WITH location, device, user
RETURN collect(distinct location+device+user) as cols
}
RETURN collect(distinct cols) as combColl
Result when I unwind the final collection:
╒══════════════════════════════╕
│"combColl" │
╞══════════════════════════════╡
│[[{"ID":1},{"ID":1}]] │
├──────────────────────────────┤
│[[{"ID":1},{"ID":2}]] │
├──────────────────────────────┤
│[[{"ID":1},{"ID":3}]] │
....
├──────────────────────────────┤
│[[{"ID":3},{"ID":2},{"ID":3}]]│
├──────────────────────────────┤
│[[{"ID":3},{"ID":3},{"ID":1}]]│
├──────────────────────────────┤
│[[{"ID":3},{"ID":3},{"ID":2}]]│
├──────────────────────────────┤
│[[{"ID":3},{"ID":3},{"ID":3}]]│
└──────────────────────────────┘

ElasticSearch order based on type of hit

I started using ElasticSearch in my ReactJS project but I'm having some troubles with it.
When I search, I'd like to have my results ordered based on this table
Full-Hit
Start-hit
Sub-hit
Fuzzy-hit
category
1
3
5
10
trade name
2
4
6
11
official name
7
8
9
12
The definition (the way I see it, unless I'm wrong) are like this:
Full-hit
examples:
Term "John" has a full-hit on "John doe"
Term "John" doesn't have a full-hit on "JohnDoe"
Start-hit
examples:
Term "John" has a start-hit on "Johndoe"
Term "Doe" doesn't have a start-hit on "JohnDoe"
sub-hit
examples:
Term "baker" has a sub-hit on "breadbakeries"
Term "baker" doesn't have a sub-hit on "de backer"
fuzzy-hit
From my understanding fuzzy-hit is when the queried word has 1 mistake or 1 letter is missing
examples:
Term "bakker" has a fuzzy-hit on "baker"
Term "bakker" doesn't have a fuzzy-hit on "bakers"
I found out that we can boost fields like this
fields = [
`category^3`,
`name^2`,
`official name^1`,
];
But that is not based on the full-, start-, sub-, or fuzzy-hit
Is this doable in ReactJS with Elasticsearch?
I need to understand your problem.
In a nutshell
1."If a full-hit is found in the category field, then we should boost it by 1".
If a full-hit is found in the official_name field we should boost by 7..
and so on for all the 12 possibilities?
If this is what you want, you are going to need 12 seperate queries, all covered under one giant bool -> should clause.
I won't write out the query for you, but I will give you some pointers, on how to structure the 4 subtypes of the queries.
Full Hit
{
"term" : {"field" : "category/tradE_name/official_name", "value" : "the_search_term"}
}
Start-hit
{
"match_phrase_prefix" : {"category/trade_name/official_name" : "the search term"}
}
Sub-hit
{
"regexp" : {
"category/official/trade" : {"value" : "*term*"}
}
}
Fuzzy
{
"fuzzy" : {
"category/trade/official" : {"value" : "term"}
}
}
You will need one giant bool
{
"query" : {
"bool" : {
"should" : [
// category field queries, 4 total clauses.
{
}
// official field queries, 4 clauses, to each clauses assign the boost as per your table. that's it.
]
}
}
}
To each clause, assign a boost as per your table.
That;s it.
HTH.

Conditionally add properties to elements of array with yq (version 4)

I have a YAML document that contains an array. I would like to conditionally add properties to the elements of that array using yq version 4 from mikefarah.
Here is a sample YAML document.
name: "My Pets"
pets:
- name: "cat"
age: 8
- name: "dog"
age: 3
- name: "mouse"
age: 1
I would like to transform this into,
name: "My Pets"
pets:
- name: "cat"
age: 8
shots: cat.upToDate
- name: "dog"
age: 3
shots: dog.upToDate
- name: "mouse"
age: 1
shots: mouse.upToDate
where we add a shots property to each element of pets. The value of shots should be whatever the name value is, dot, upToDate.
I'm trying something like this,
yq eval '.pets[] | select(.name == "cat").shots = "cat.upToDate"' test.yaml
but that produces,
name: "cat"
age: 8
shots: cat.upToDate
name: "dog"
age: 3
name: "mouse"
age: 1
I need to preserve the entire original YAML document and just insert the shots property.
This is close but missing all of the other pets.
yq eval '.pets = (.pets[] | select(.name == "cat").shots = "cats.upToDate")' test.yaml
It produces,
name: "My Pets"
pets:
name: "cat"
age: 8
shots: cats.upToDate
I'm thinking maybe we could store the name of the pet in a variable and reference that later, but v4 is brand new to me today.
I would prefer to have a one-liner so that I don't have to filter on .name. This array has less than 10 elements so I could easily hard-code the name and call yq 10 times.
Any thoughts or suggestions? Many thanks, Weldon
Use |=, e.g. like so:
yq eval '.pets[] |= (.shots = (.name + ".upToDate"))' pets.yaml

In a Ruby on Rails app, I'm trying to loop through an array within a hash within an array. Why am I getting "syntax error" message?

I have a Ruby on Rails application to enter results and create a league table for a football competition.
I'm trying to input some results by creating records in the database through heroku and I get error messages.
The application isn't perfectly designed: to enter the results, I have to create the fixtures and enter the score for each team. Then, independently I have to record each goal scorer, creating a record for each goal which is either associated with an existing player or requires me to firstly create a new player and then create the goal.
When I ran the code below heroku, I got this error:
syntax error, unexpected ':', expecting keyword_end
Maybe I'm missing something simple about lopping through an array within a hash?
Thank you for any advice!
coalition = Team.find_by(name: "Coalition")
moscow_rebels = Team.find_by(name: "Moscow Rebels")
red_star = Team.find_by(name: "Red Star")
unsanctionables = Team.find_by(name: "The Unsanctionables")
cavalry = Team.find_by(name: "Cavalry")
galactics = Team.find_by(name: "The Galactics")
happy_sundays = Team.find_by(name: "Happy Sundays")
hardmen = Team.find_by(name: "Hardmen")
international = Team.find_by(name: "International")
evropa = Venue.find_by(name: "Evropa")
s28 = Season.find_by(number: 28)
start_time = DateTime.new(2020,9,6,11,0,0,'+03:00')
scheduled_matches_1 =
[
{team_1: cavalry, team_1_goals: 1, team_1_scorers: ["Minaev"], team_2_goals: 6, team_2_scorers: ["Kovalev", "Kovalev", "Kovalev", "Thomas", "Thomas", "Grivachev"], team_2: coalition, time: start_time, venue: evropa, season: s28},
{team_1: hardmen, team_1_goals: 4, team_1_scorers: ["Jones", "Jones", "Jones", "Fusi"], team_2_goals: 2, team_2_scorers: ["Kazamula", "Ario"], team_2: galactics, time: start_time + 1.hour, venue: evropa, season: s28},
{team_1: international, team_1_goals: 9, team_1_scorers: ["Kimonnen", "Kimonnen", "Kimonnen", "Burya", "Burya", "Zakharyaev", "Zakharyaev", "Lavruk", "Rihter"], team_2_goals: 0, team_2_scorers: [], team_2: happy_sundays, time: start_time+2.hours, venue: evropa, season: s28}
]
scheduled_matches.each do |match|
new_fixture = Fixture.create(time: match[:time], venue: match[:venue], season: match[:season])
tf1 = TeamFixture.create(team: match[:team_1], fixture: new_fixture)
tf2 = TeamFixture.create(team: match[:team_2], fixture: new_fixture)
ts1 = TeamScore.create(team_fixture: tf1, total_goals: match{:team_1_goals})
ts2 = TeamScore.create(team_fixture: tf2, total_goals: match{:team_2_goals})
match[:team_1_scorers].each do |scorer|
if Player.exists?(team: tf1.team, last_name: scorer)
Goal.create(team_score: ts1, player: Player.find_by(last_name: scorer))
else
new_player = Player.create(team: tf1.team, last_name: scorer)
Goal.create(team_score: ts1, player: new_player)
end
end
match[:team_2_scorers].each do |scorer_2|
if Player.exists?(team: tf2.team, last_name: scorer_2)
Goal.create(team_score: ts2, player: Player.find_by(last_name: scorer_2))
else
new_player = Player.create(team: tf2.team, last_name: scorer_2)
Goal.create(team_score: ts2, player: new_player)
end
end
end
It looks like you are using braces when you meant to use brackets to access the hash. Below is one of the issues, but the same issue is in ts2.
ts1 = TeamScore.create(team_fixture: tf1, total_goals: match{:team_1_goals})
should be match[:team_1_goals]
ts1 = TeamScore.create(team_fixture: tf1, total_goals: match[:team_1_goals])
It may be because you have scheduled_matches_1 at the top and scheduled_matches.each do... further down.
But the real issue here is that your variable names match the data content, rather than being used to hold the content. If a new team joins your league, you have to change the code. Next week, you are going to have to change the hard-coded date value. Your scheduled_matches_1 data structure includes the active record objects returned by the first set of Team.findByName() calls. It would be easier to fetch these objects from the database inside your loops, and just hold the team name as a string in the hash.
There is some duplication too. Consider that each fixture has a home team and an away team. Each team has a name, and an array (possibly empty) of the players who scored. We don't need the number of goals; we can just count the number of players in the 'scorers' array. The other attributes, like the location and season belong to the fixture, not the team. So your hash might be better as
{
"fixtures": [
{
"home": {
"name": "Cavalry",
"scorers": [
"Minaev"
]
},
"away": {
"name": "Coalition",
"scorers": [
"Kovalev",
"Kovalev",
"Kovalev",
"Thomas",
"Thomas",
"Grivachev"
]
},
"venue": "Evropa",
"season": "s28"
}
]
}
because then you can create a reusable method to process each team. And maybe create a new method that returns the player (which it either finds or creates) which can be called by the loop that adds the goals.
Also, as it stands, I'm not sure the code can handle 'own goals', either. Perhaps something for a future iteration :)

Parsing Attribute Data from Column- SQL Server

I have a table with column "Long Description" typically the data looks like the following.
Foundation area wall, 12" H. x 20" W. x 8" projection. Galvanized. Refer to model No. SV208 (SKU 100002) for foundation area wall cover. No. FV208-12: Height: 12", Width: 20", Projection: 8", Type: Foundation Area Wall, Material: Galvanized, Pkg Qty: 1
What I am trying to do is parse out the end attributes. For example after "area wall cover." and beginning with "No." I'd like to extract the following. (Below)
Some things to note. The string '. No.' always begins the attributes in this column. All attributes are separated by columns. The attribute names differ and the amount of attributes per product also differ. Is there a way this can be done with T-SQL?
No. FV208-12:
Height: 12"
Width: 20"
Projection: 8"
Type: Foundation Area Wall
Material: Galvanized
Pkg Qty: 1
You can use a variation of the following to achieve what I believe you're attempting to achieve:
DECLARE #StartAttributesKey VARCHAR(50) = 'area wall cover. ' ,
#LongDescription VARCHAR(MAX) = 'Foundation area wall, 12" H. x 20" W. x 8" projection. Galvanized. Refer to model No. SV208 (SKU 100002) for foundation area wall cover. No. FV208-12: Height: 12", Width: 20", Projection: 8", Type: Foundation Area Wall, Material: Galvanized, Pkg Qty: 1';
SELECT REPLACE(SUBSTRING(#LongDescription, CHARINDEX(#StartAttributesKey, #LongDescription, 0) + LEN(#StartAttributesKey),
LEN(#LongDescription) - CHARINDEX(#StartAttributesKey, #LongDescription, 0)), ',', CHAR(10));
Using this in a query would be similar to:
DECLARE #StartAttributesKey VARCHAR(50) = 'area wall cover. '
SELECT REPLACE(SUBSTRING(LongDescription, CHARINDEX(#StartAttributesKey, LongDescription, 0) + LEN(#StartAttributesKey),
LEN(LongDescription) - CHARINDEX(#StartAttributesKey, LongDescription, 0)), ',', CHAR(10))
FROM [someTable] WHERE ID = 1
If you copy (or print) the result, you will see each attribute on a separate line.

Resources