/// <summary> /// Gets the three scores for a list of given studios. /// </summary> /// <returns>A list of KeyValuePairs in which the provided studios are the keys /// and their values are arrays of scores (of length 3).</returns> /// <param name="studios">The different studios to get scores for.</param> public static List <KeyValuePair <string, float[]> > GetScores(string[] studios, int crunches = 0) { Dictionary <string, float[]> dict = new Dictionary <string, float[]>(); foreach (string studio in studios) { try { //Gets a StudioInfo object, containing all sorts of goodies. StudioInfo si = Giantbomb.GiantBombInterfacer.GetStudio(studio, DEBUG_MODE); //Add the different values to the dictionary. dict.Add(studio + ((crunches == 2) ? " - TRUE" : (crunches == 1) ? " - FALSE" : ""), new float[] { si.CrunchOvertimeScore, si.GenreScore, si.ReviewScore, si.ConsScore }); //If we force-calculated new values or if it doesn't already exist, //cache the Studio if (MainClass.options.force || LocalCacheManager.GetCachedInfo(studio).id == "-1") { LocalCacheManager.SaveCachedInfo(studio, si); } } catch (Exception e) { Logger.Log(e.Message + ". Occurred for " + studio, Logger.LogLevel.ERROR, true); Logger.Log(e.StackTrace, Logger.LogLevel.CRITICAL, false); } } //Return return(dict.ToList()); }
// Generate root document when constructor is there. public SideloaderMod([NotNull] TextAsset file) { // check parse error var assetPath = AssetDatabase.GetAssetPath(file); AssetFolder = Path.GetDirectoryName(assetPath) ?? ""; AssetDirectory = Path.Combine(Directory.GetCurrentDirectory(), AssetFolder).Replace("\\", "/"); FileName = file.name; _outputDocumentObject = XmlUtils.GetManifestTemplate(); _inputDocumentObject = XDocument.Parse(file.text); MainData = new MainData(); DependencyData = new DependencyLoaderData(); GameMapInfo = new GameMapInfo(); StudioInfo = new StudioInfo(); MainData.ParseData(this, _inputDocumentObject.Root); DependencyData.ParseData(this, _inputDocumentObject.Root); _manifestData = new List <IManifestData> { // it should be in order, lmk if there is good way to do. I'm always learning. MainData, DependencyData, new HeelsData(), new MaterialEditorData(), new AIMapData() }; _bundleTargets = new List <BundleBase>(); GameItems = new Dictionary <string, GameInfo>(); Assets = new AssetInfo(); ParseDocument(_inputDocumentObject.Root); }
/// <summary> /// Saves Studio information to the cache. /// </summary> /// <returns><c>true</c> if the cached info was saved successfully, <c>false</c> otherwise.</returns> /// <param name="si">Si.</param> public static bool SaveCachedInfo(string saveAs, StudioInfo si) { //Read the contents and create the new value for the Studio. string[] contents = File.ReadAllLines("cache.csv"); string newValue = si.id.Replace(",", "-") + "," + saveAs.Replace(',', '-').ToLower() + "," + si.employeeCount + "," + si.gameYears.GetString() + "," + si.GenreScore + "," + si.ReviewScore + "," + si.ConsScore + "," + si.genreArray.GetString(); string toAdd = ""; bool saved = false; for (int a = 0; a < contents.Length; a++) { //Check and see if the cache already has information. If it does, //we're going to update it instead of add it. string[] split = contents[a].Split(','); if (split[0] == si.id.ToString()) { contents[a] = newValue; saved = true; } //No matter what, keep the rest of the contents for the cache. toAdd += contents[a] + "\n"; } //If it didn't exist, append the new values to the end of the cache. if (!saved) { toAdd += newValue; } //Open the File, set the Encoding, and write to it. FileStream stream = File.Open("cache.csv", FileMode.OpenOrCreate, FileAccess.ReadWrite); Encoding enc = Encoding.UTF8; stream.Write(enc.GetBytes(toAdd), 0, enc.GetByteCount(toAdd)); stream.Close(); stream.Dispose(); return(true); }
private void ProcessSendState(byte[] data) { try { StudioInfo studioInfo = StudioInfo.FromByteArray(data); CommunicationWrapper.StudioInfo = studioInfo; } catch (InvalidCastException) { string studioVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(3); object[] objects = BinaryFormatterHelper.FromByteArray <object[]>(data); string modVersion = objects.Length >= 10 ? objects[9].ToString() : "Unknown"; MessageBox.Show( $"Studio v{studioVersion} and CelesteTAS v{modVersion} do not match. Please manually extract the studio from the \"game_path\\Mods\\CelesteTAS.zip\" file.", "Communication Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); } }
/// <summary> /// Gets studio information from the Giantbomb API /// </summary> /// <returns>A struct representing the various information.</returns> /// <param name="name">The name of the studio.</param> /// <param name="DEBUG">Is the studio in debug mode?</param> public static StudioInfo GetStudio(string name, bool DEBUG) { //If the API key is not set, load it from the app.config file. if (API_KEY == "") { API_KEY = ConfigurationManager.AppSettings["GBkey"]; } //Logging if (Logger.VERBOSE) { Logger.Log(name + " in DEBUG mode: [" + DEBUG.ToString().ToUpper() + "]"); } //Check to see if there's a cached value, unless we are forcibly retrieving //new values. StudioInfo si; if (!MainClass.options.force) { si = LocalCacheManager.GetCachedInfo(name); si.aliases = Extensions.Extensions.CreateAliasList(name); if (si.id != "-1") { return(si); } } //Get the employee count from Wikipedia. int employeeCount = Extensions.Extensions.GetEmployeeCount(name); //Get an alternative topic from Wikipedia. string wikiName = Wiki.WikipediaRetriever.GetActualTopic(name); name = Regex.Replace(name, "\\(company\\)", "", RegexOptions.IgnoreCase).Trim(); //Get information on release dates of games. string[] gameInfo = GetGBInfo(name, wikiName); //Change the game info into years, excluding the last two entries, //since they're different pieces of information. int[] gameYears = new int[gameInfo.Length - 3]; //Parse all of the actual years. for (int a = 0; a < gameInfo.Length - 3; a++) { gameYears[a] = int.Parse(gameInfo[a]); } //Sort them together in ascending order. Array.Sort(gameYears); //Return the new information, including the ID and name from game info. si = new StudioInfo { id = gameInfo[gameInfo.Length - 3], name = gameInfo[gameInfo.Length - 2], companyName = gameInfo[gameInfo.Length - 1], employeeCount = employeeCount, gameYears = gameYears, aliases = Extensions.Extensions.CreateAliasList(name) }; si.aliases.Insert(0, si.companyName); //LocalCacheManager.SaveCachedInfo(si); return(si); }
/// <summary> /// Gets the likelihood of crunching based off the genres of various games /// a studio has put out. /// </summary> /// <returns>The genre score.</returns> /// <param name="name">The name of the Studio, which is passed to the IGDB API.</param> /// <param name="aliases">What it's saved as in the cache. This may differ from the name retrieved from the Giantbomb API.</param> /// <param name="DEBUG">Is this Studio in Debug mode?</param> public static float[] GetGenreScore(string name, List <string> aliases, bool DEBUG) { //Log information if (Logger.VERBOSE) { Logger.Log("Finding genre score."); } //If the Studio is not being forced to recaculate values, check if it //exists in the cache. If it does, return the values. Otherwise, continue. if (!DEBUG && !MainClass.options.force) { StudioInfo si = LocalCacheManager.GetCachedInfo(aliases[0]); if (si.id != "-1" && !DEBUG) { List <float> f = Array.ConvertAll(si.genreArray, x => (float)x).ToList(); f.Insert(0, si.GenreScore); return(f.ToArray()); } } //Get the genres of all released games from IGDB and return their average as the score. int[] genres = IGDBInterfacer.GetGenres(name); int[] genreCount = new int[7]; Logger.Log(name + ", " + aliases.ToArray().GetString(), Logger.LogLevel.DEBUG, true); //Uses a Unit Circle based system. float totalX = 0.0f; float totalY = 0.0f; if (genres != null && genres.Length > 0) { for (int i = 0; i < genres.Length; i++) { //Get the angle because it uses a unit-circle based system. //See the ReadMe or Whitepaper for more info. float angle = (float)((i / 7) * 2 * Math.PI); totalX += genres[i] * (float)Math.Cos(angle); totalY += genres[i] * (float)Math.Sin(angle); genreCount[genres[i]]++; } } else { //If an exception was thrown, it means the name doesn't exist on IGDB. //Then we use the different aliases. bool broken = false; foreach (string alias in aliases) { genres = IGDBInterfacer.GetGenres(alias); //This means this name doesn't exist either, so try the next one. if (genres == null || genres.Length <= 0) { continue; } for (int i = 0; i < genres.Length; i++) { //Get the angle because it uses a unit-circle based system. //See the ReadMe or Whitepaper for more info. float angle = (float)((i / 7) * 2 * Math.PI); totalX += genres[i] * (float)Math.Cos(angle); totalY += genres[i] * (float)Math.Sin(angle); genreCount[genres[i]]++; } broken = true; break; } //If no genres were found, throw an exception. if (!broken) { throw new Exception(name + " doesn't exist in IGDB!"); } } //Average totalX /= genres.Length; totalY /= genres.Length; //Normalize float hyp = (float)Math.Sqrt((totalX * totalX) + (totalY * totalY)); totalX /= hyp; totalY /= hyp; //Return the value. return(new float[] { (float)(Math.Atan(totalY / totalX) / (2 * Math.PI)), genreCount[0], genreCount[1], genreCount[2], genreCount[3], genreCount[4], genreCount[5], genreCount[6], }); }