@@ -161,12 +161,68 @@ def destroy
161161 end
162162
163163 def sync
164- # Sync functionality not yet implemented
165- render_error (
166- message : 'Sync functionality not yet implemented' ,
167- code : 'NOT_IMPLEMENTED' ,
168- status : :not_implemented
169- )
164+ # Sync player data from Riot API
165+ unless @target . riot_puuid . present?
166+ return render_error (
167+ message : 'Cannot sync player without Riot PUUID' ,
168+ code : 'MISSING_PUUID' ,
169+ status : :unprocessable_entity
170+ )
171+ end
172+
173+ riot_service = RiotApiService . new
174+ region = @target . region
175+
176+ begin
177+ # Fetch updated summoner data
178+ summoner_data = riot_service . get_summoner_by_puuid (
179+ puuid : @target . riot_puuid ,
180+ region : region
181+ )
182+
183+ # Fetch ranked stats
184+ league_data = riot_service . get_league_entries (
185+ summoner_id : summoner_data [ :summoner_id ] ,
186+ region : region
187+ )
188+
189+ # Fetch champion mastery
190+ mastery_data = riot_service . get_champion_mastery (
191+ puuid : @target . riot_puuid ,
192+ region : region
193+ )
194+
195+ # Update target with fresh data
196+ @target . update! (
197+ riot_summoner_id : summoner_data [ :summoner_id ] ,
198+ summoner_name : summoner_data [ :summoner_name ] ,
199+ current_tier : league_data [ :solo_queue ] &.dig ( :tier ) ,
200+ current_rank : league_data [ :solo_queue ] &.dig ( :rank ) ,
201+ current_lp : league_data [ :solo_queue ] &.dig ( :lp ) ,
202+ champion_pool : extract_champion_pool ( mastery_data ) ,
203+ performance_trend : calculate_performance_trend ( league_data )
204+ )
205+
206+ watchlist = @target . scouting_watchlists . find_by ( organization : current_organization )
207+
208+ render_success ( {
209+ scouting_target : JSON . parse (
210+ ScoutingTargetSerializer . render ( @target , watchlist : watchlist )
211+ )
212+ } , message : 'Player data synced successfully' )
213+ rescue RiotApiService ::NotFoundError
214+ render_error (
215+ message : 'Player not found in Riot API' ,
216+ code : 'PLAYER_NOT_FOUND' ,
217+ status : :not_found
218+ )
219+ rescue RiotApiService ::RiotApiError => e
220+ render_error (
221+ message : "Failed to sync player data: #{ e . message } " ,
222+ code : 'RIOT_API_ERROR' ,
223+ status : :service_unavailable
224+ )
225+ end
170226 end
171227
172228 private
@@ -304,6 +360,55 @@ def target_params
304360 champion_pool : [ ]
305361 )
306362 end
363+
364+ # Extract top champions from mastery data
365+ def extract_champion_pool ( mastery_data )
366+ return [ ] if mastery_data . blank?
367+
368+ # Get top 10 champions by mastery points
369+ mastery_data . first ( 10 ) . map do |mastery |
370+ champion_id_to_name ( mastery [ :champion_id ] )
371+ end . compact
372+ end
373+
374+ # Simple champion ID to name mapping (top champions)
375+ def champion_id_to_name ( champion_id )
376+ # This is a simplified mapping - in production you'd want a complete mapping
377+ # or fetch from Data Dragon API
378+ champion_map = {
379+ 1 => 'Annie' , 2 => 'Olaf' , 3 => 'Galio' , 4 => 'Twisted Fate' ,
380+ 5 => 'Xin Zhao' , 6 => 'Urgot' , 7 => 'LeBlanc' , 8 => 'Vladimir' ,
381+ 9 => 'Fiddlesticks' , 10 => 'Kayle' , 11 => 'Master Yi' , 12 => 'Alistar' ,
382+ 13 => 'Ryze' , 14 => 'Sion' , 15 => 'Sivir' , 16 => 'Soraka' ,
383+ 17 => 'Teemo' , 18 => 'Tristana' , 19 => 'Warwick' , 20 => 'Nunu' ,
384+ 21 => 'Miss Fortune' , 22 => 'Ashe' , 23 => 'Tryndamere' , 24 => 'Jax' ,
385+ 25 => 'Morgana' , 26 => 'Zilean' , 27 => 'Singed' , 28 => 'Evelynn' ,
386+ 29 => 'Twitch' , 30 => 'Karthus' , 31 => 'Cho\'Gath' , 32 => 'Amumu' ,
387+ 33 => 'Rammus' , 34 => 'Anivia' , 35 => 'Shaco' , 36 => 'Dr. Mundo'
388+ # Add more as needed or fetch from Data Dragon
389+ }
390+ champion_map [ champion_id ] || "Champion_#{ champion_id } "
391+ end
392+
393+ # Calculate performance trend based on win/loss ratio
394+ def calculate_performance_trend ( league_data )
395+ solo_queue = league_data [ :solo_queue ]
396+ return 'stable' unless solo_queue
397+
398+ wins = solo_queue [ :wins ] || 0
399+ losses = solo_queue [ :losses ] || 0
400+ total_games = wins + losses
401+
402+ return 'stable' if total_games . zero?
403+
404+ win_rate = ( wins . to_f / total_games * 100 ) . round ( 2 )
405+
406+ case win_rate
407+ when 0 ..45 then 'declining'
408+ when 45 ..52 then 'stable'
409+ else 'improving'
410+ end
411+ end
307412 end
308413 end
309414 end
0 commit comments