import footballstatshelper import helper import clr import System clr.AddReference("System.Drawing") from System.Drawing import * from System.Drawing import Color as ColorDrawing from System.Drawing.Imaging import ImageFormat from System.Drawing.Drawing2D import * from System import Guid from System.Windows.Media import SolidColorBrush, Color from System.IO import Path, File, DirectoryInfo clr.AddReference("Wtvision.Sports.Tools.OptaImporter") from Wtvision.Sports import OptaProxyApi HOME_SHOTS_RGB = "255,255,0" HOME_MISS_RGB = "255,0,0" HOME_GOALS_RGB = "255,255,255" AWAY_SHOTS_RGB = "255,255,0" AWAY_MISS_RGB = "255,0,0" AWAY_GOALS_RGB = "255,255,255" def __onStart(graphicOnAirItem, momentExecution, workFlowtype): if Globals["OptionsLanguageForm"].selectedLanguage == "": momentExecution.Message = "Select language in OptionsForm !" momentExecution.Cancel = True # if workFlowtype.ToString() != "Preview": # if GameOnline.IsOnAir: # momentExecution.Message = "ONLINE IS ON AIR" # momentExecution.Cancel = True # return # def __getData(graphicOnAirItem, viewBag, momentExecution,workFlowtype): extradata = graphicOnAirItem.Graphic.ExtraData ARVisibility = "vARVisibility" ENVisibility = "vENVisibility" hometeam = Game.HomeTeam awayteam = Game.AwayTeam helper.upperTags(viewBag) # homeRGB = helper.get_team_institutional_color(hometeam.RefName) # awayRGB = helper.get_team_institutional_color(awayteam.RefName) # # viewBag.SetString("vHomeTeamRGB", homeRGB) # viewBag.SetString("vAwayTeamRGB", awayRGB) homeRGB = footballstatshelper.GetTeamRGB(hometeam) awayRGB = footballstatshelper.GetTeamRGB(awayteam) viewBag.SetString("vHomeTeamRGB", ",".join(c.ToString() for c in homeRGB)) viewBag.SetString("vAwayTeamRGB", ",".join(c.ToString() for c in awayRGB)) if workFlowtype.ToString() == "Preview": graphicOnAir = IntelliflowController.GetGraphicOnAirItems(OutputManager.ActiveChannelOutput) helper.SetExtraData(extradata, "IsOnAir", "False") for i in graphicOnAir: if i.Scene.Name == graphicOnAirItem.Scene.Name: if i.Graphic.Name == graphicOnAirItem.Graphic.Name: helper.SetExtraData(extradata, "IsOnAir", "True") #Verification if have key IsOnair in Extradata. if not extradata.ContainsKey("IsOnAir"): helper.SetExtraData(extradata, "IsOnAir", "False") graphicIsOnAir = extradata["IsOnAir"] if graphicIsOnAir == "False": if Globals["OptionsLanguageForm"].selectedLanguage == "AR": viewBag.SetString(ARVisibility, "True") viewBag.SetString(ENVisibility, "False") else: viewBag.SetString(ARVisibility, "False") viewBag.SetString(ENVisibility, "True") HomeExpectedGoalsEvents = [] AwayExpectedGoalsEvents = [] matchExpectedGoals = OptaProxyApi.GetMatchExpectedGoals(matchId=Game.ExternalId, overrideCache=True, alwaysFresh=True) if matchExpectedGoals and matchExpectedGoals.LiveData and matchExpectedGoals.LiveData.LineUps and matchExpectedGoals.LiveData.Events and matchExpectedGoals.LiveData.Events.Count: expectedGoalsEvents = matchExpectedGoals.LiveData.Events homeExpectedGoalsEvents = filter(lambda e: e.ContestantId == Game.HomeTeam.ExternalId, expectedGoalsEvents) awayExpectedGoalsEvents = filter(lambda e: e.ContestantId == Game.AwayTeam.ExternalId, expectedGoalsEvents) homeTeamData = matchExpectedGoals.LiveData.LineUps[0 if Game.HomeTeam.ExternalId == matchExpectedGoals.LiveData.LineUps[0].ContestantId else 1] awayTeamData = matchExpectedGoals.LiveData.LineUps[1 if Game.HomeTeam.ExternalId == matchExpectedGoals.LiveData.LineUps[0].ContestantId else 0] HomeTeamExpectedGoals = next((round(float(stat.Value),2) for stat in homeTeamData.Stats if stat.Type == "expectedGoals"), 0) AwayTeamExpectedGoals = next((round(float(stat.Value),2) for stat in awayTeamData.Stats if stat.Type == "expectedGoals"), 0) for e in homeExpectedGoalsEvents: expectedGoalQualifier = next((q for q in e.Qualifiers if q.QualifierId == 321), None) if not expectedGoalQualifier:continue event = ExpectedGoalsEvent(e.TimeMin, e.TimeSec, e.PlayerName, e.TypeId,e.Qualifiers, round(float(expectedGoalQualifier.Value) if expectedGoalQualifier else 0, 3), e.X, e.Y) HomeExpectedGoalsEvents.Add(event) for e in awayExpectedGoalsEvents: expectedGoalQualifier = next((q for q in e.Qualifiers if q.QualifierId == 321), None) if not expectedGoalQualifier:continue event = ExpectedGoalsEvent(e.TimeMin, e.TimeSec, e.PlayerName, e.TypeId,e.Qualifiers, round(float(expectedGoalQualifier.Value) if expectedGoalQualifier else 0, 3), e.X, e.Y) AwayExpectedGoalsEvents.Add(event) imageName,hGoals,aGoals,hTarget,aTarget,hBlocked,aBlocked = __generateTrackingImage(graphicOnAirItem, momentExecution, Game.HomeTeam, Game.AwayTeam,HomeExpectedGoalsEvents,AwayExpectedGoalsEvents) viewBag.SetImage("lgImage", "Images/Fields/%s" %imageName) statPosition = 1 statName = "GOALS" viewBag.SetTranslatedText("tAwayStatTitle%02d_AR"%(statPosition),"{{%s}}.{{AR}}" % statName) viewBag.SetTranslatedText("tHomeStatTitle%02d_AR"%(statPosition),"{{%s}}.{{AR}}" % statName) viewBag.SetTranslatedText("tAwayStatTitle%02d_EN"%(statPosition), "{{%s}}.{{EN}}" % statName) viewBag.SetTranslatedText("tHomeStatTitle%02d_EN"%(statPosition), "{{%s}}.{{EN}}" % statName) viewBag.SetString("tHomeStatValue%02d" % (statPosition), Game.HomeTeamScore) viewBag.SetString("tAwayStatValue%02d" % (statPosition), Game.AwayTeamScore) statPosition = 2 statName = "ON TARGET" viewBag.SetTranslatedText("tAwayStatTitle%02d_AR"%(statPosition),"{{%s}}.{{AR}}" % statName) viewBag.SetTranslatedText("tHomeStatTitle%02d_AR"%(statPosition),"{{%s}}.{{AR}}" % statName) viewBag.SetTranslatedText("tAwayStatTitle%02d_EN"%(statPosition), "{{%s}}.{{EN}}" % statName) viewBag.SetTranslatedText("tHomeStatTitle%02d_EN"%(statPosition), "{{%s}}.{{EN}}" % statName) viewBag.SetString("tHomeStatValue%02d" % (statPosition), hTarget if int(Game.HomeTeamScore) < int(hTarget) else int(Game.HomeTeamScore)) viewBag.SetString("tAwayStatValue%02d" % (statPosition), aTarget if int(Game.AwayTeamScore) < int(aTarget) else int(Game.AwayTeamScore)) statPosition = 3 statName = "BLOCKED & OFF TARGET" viewBag.SetTranslatedText("tAwayStatTitle%02d_AR"%(statPosition),"{{%s}}.{{AR}}" % statName) viewBag.SetTranslatedText("tHomeStatTitle%02d_AR"%(statPosition),"{{%s}}.{{AR}}" % statName) viewBag.SetTranslatedText("tAwayStatTitle%02d_EN"%(statPosition), "{{%s}}.{{EN}}" % statName) viewBag.SetTranslatedText("tHomeStatTitle%02d_EN"%(statPosition), "{{%s}}.{{EN}}" % statName) viewBag.SetString("tHomeStatValue%02d" % (statPosition), hBlocked) viewBag.SetString("tAwayStatValue%02d" % (statPosition), aBlocked) else: if Globals["OptionsLanguageForm"].selectedLanguage == "AR": viewBag.SetString(ARVisibility, "False") viewBag.SetString(ENVisibility, "True") else: viewBag.SetString(ARVisibility, "True") viewBag.SetString(ENVisibility, "False") viewBag.SetImage("lgAwayTeamBadge", "Images/Logos/%s.png" %awayteam.RefName) viewBag.SetImage("lgHomeTeamBadge", "Images/Logos/%s.png" %hometeam.RefName) viewBag.SetTranslatedText("tAwayTeamName_AR", "{{%s}}.{{AR}}" % awayteam.FullName.upper()) viewBag.SetTranslatedText("tAwayTeamName_EN", "{{%s}}.{{EN}}" % awayteam.FullName.upper()) viewBag.SetTranslatedText("tHomeTeamName_AR", "{{%s}}.{{AR}}" % hometeam.FullName.upper()) viewBag.SetTranslatedText("tHomeTeamName_EN", "{{%s}}.{{EN}}" % hometeam.FullName.upper()) def __afterProgram(graphicOnAirItem, momentExecution): extradata = graphicOnAirItem.Graphic.ExtraData graphicIsOnAir = extradata["IsOnAir"] if graphicIsOnAir == "True": return IntelliflowController.TakeIn(graphicOnAirItem.Graphic, OutputManager.ActiveChannelOutput,workflowType = IntelliflowController.EWorkflowType.Preview) def __generateTrackingImage(graphicOnAirItem, momentExecution, homeTeam, awayTeam,homeExpectedGoalsEvents,awayExpectedGoalsEvents): fieldRootPath = Path.Combine(graphicOnAirItem.GraphicsEngine.Options.RootPath, graphicOnAirItem.Scene.Path, "Images", "Fields") originalFieldPath = Path.Combine(fieldRootPath, "field.png") if not File.Exists(originalFieldPath): momentExecution.Message = "Path \"%s\" does not exists!" %originalFieldPath momentExecution.Cancel = True return None enginesRootPath = [fieldRootPath] programEngines = list(OutputManager.ActiveChannelOutput.ActiveEnginesAssignmentProfile.ProgramGraphicsEngines) for engine in programEngines: enginesRootPath.append(fieldRootPath +"\\")#r3engine for path in enginesRootPath: for file in DirectoryInfo(path).GetFiles(): if file.Name.StartsWith("field_"): file.Delete() width = 1492 height = 932 isValid, r, g, b = stringToRGB(HOME_SHOTS_RGB) brushShotsHome = SolidBrush(ColorDrawing.FromArgb(255, r, g, b)) #alpha, RED, GREEN, BLUE isValid, r, g, b = stringToRGB(HOME_GOALS_RGB) brushGoalsHome = SolidBrush(ColorDrawing.FromArgb(255, r, g, b)) #alpha, RED, GREEN, BLUE isValid, r, g, b = stringToRGB(HOME_MISS_RGB) brushMissHome = SolidBrush(ColorDrawing.FromArgb(255, r, g, b)) #alpha, RED, GREEN, BLUE isValid, r, g, b = stringToRGB(AWAY_SHOTS_RGB) brushShotsAway = SolidBrush(ColorDrawing.FromArgb(255, r, g, b)) #alpha, RED, GREEN, BLUE isValid, r, g, b = stringToRGB(AWAY_GOALS_RGB) brushGoalsAway = SolidBrush(ColorDrawing.FromArgb(255, r, g, b)) #alpha, RED, GREEN, BLUE isValid, r, g, b = stringToRGB(AWAY_MISS_RGB) brushMissAway = SolidBrush(ColorDrawing.FromArgb(255, r, g, b)) #alpha, RED, GREEN, BLUE img = Image.FromFile(originalFieldPath) bmcImg = Bitmap(width, height) gh = Graphics.FromImage(bmcImg) gh.InterpolationMode = InterpolationMode.Bilinear gh.PixelOffsetMode = PixelOffsetMode.Half gh.SmoothingMode = SmoothingMode.AntiAlias hGoals = 0 aGoals = 0 hTarget= 0 aTarget= 0 hBlocked= 0 aBlocked = 0 gh.DrawImage(img, Rectangle(0, 0, width, height)) #draw origienal field image #qualifier 82 to validate shotsOnTarget for e in homeExpectedGoalsEvents: has82Qualifier = next((q for q in e.qualifiers if q.QualifierId == 82), None) shapeSize = Scale(e.value, 1, 0, 100, 50) paint = False if e.eventType == "Goal": hGoals +=1 hTarget +=1 homeBrush = brushGoalsHome paint = True elif e.eventType == "Miss": hBlocked +=1 homeBrush = brushMissHome paint = True else: if has82Qualifier: hTarget +=1 homeBrush = brushShotsHome paint = True else: hBlocked +=1 homeBrush = brushMissHome paint = True if paint: gh.FillEllipse(homeBrush, (e.posX * width)/102, abs(height - (e.posY * height)/95), shapeSize, shapeSize) #brush, x, y, width, height for e in homeExpectedGoalsEvents: shapeSize = Scale(e.value, 1, 0, 100, 50) if e.eventType == "Goal": homeBrush = brushGoalsHome gh.FillEllipse(homeBrush, (e.posX * width)/102, abs(height - (e.posY * height)/95), shapeSize, shapeSize) #brush, x, y, width, height for e in awayExpectedGoalsEvents: has82Qualifier = next((q for q in e.qualifiers if q.QualifierId == 82), None) shapeSize = Scale(e.value, 1, 0, 100, 50) if e.eventType == "Goal": aGoals +=1 awayBrush = brushGoalsAway aTarget +=1 elif e.eventType == "Miss": aBlocked +=1 awayBrush = brushMissAway gh.FillEllipse(awayBrush, abs(width - (e.posX * width)/96), (e.posY * height)/110, shapeSize, shapeSize) else: if has82Qualifier: aTarget +=1 awayBrush = brushShotsAway gh.FillEllipse(awayBrush, abs(width - (e.posX * width)/96), (e.posY * height)/110, shapeSize, shapeSize) #brush, x, y, width, height else: aBlocked +=1 awayBrush = brushMissAway gh.FillEllipse(awayBrush, abs(width - (e.posX * width)/96), (e.posY * height)/110, shapeSize, shapeSize) for e in awayExpectedGoalsEvents: shapeSize = Scale(e.value, 1, 0, 100, 50) if e.eventType == "Goal": awayBrush = brushGoalsAway gh.FillEllipse(awayBrush, abs(width - (e.posX * width)/96), (e.posY * height)/110, shapeSize, shapeSize) #brush, x, y, width, height imageName = "field_%s.png" %Guid.NewGuid() for path in enginesRootPath: bmcImg.Save(Path.Combine(path, imageName), ImageFormat.Png) return imageName,hGoals,aGoals,hTarget,aTarget,hBlocked,aBlocked def Scale(value, maxValue, minValue, maxScale, minScale): scaledValue = ((value - minValue) / (maxValue - minValue)) * (maxScale - minScale) + minScale return scaledValue def stringToRGB(string): if not string: return False, 0, 0, 0 strSplitted = string.split(",") if len(strSplitted) != 3: return False, 0, 0, 0 r = int(strSplitted[0]) if strSplitted[0].isdigit() else -1 g = int(strSplitted[1]) if strSplitted[1].isdigit() else -1 b = int(strSplitted[2]) if strSplitted[2].isdigit() else -1 if r < 0 or r > 255: return False, 0, 0, 0 elif g < 0 or g > 255: return False, 0, 0, 0 elif b < 0 or b > 255: return False, 0, 0, 0 else: return True, r, g, b class ExpectedGoalsEvent(object): def __init__(self, timeMin, timeSec, playerName, eventType,qualifiers, value, posX, posY): self.time = timeMin.ToString().zfill(2) + ":" + timeSec.ToString().zfill(2) self.playerName = playerName self.qualifiers = qualifiers self.eventType = "" if eventType == 16: self.eventType = "Goal" elif eventType == 15: self.eventType = "Saved" elif eventType == 14: self.eventType = "Post" else: self.eventType = "Miss" self.value = value self.posX = posX self.posY = posY