private void CleanUpUnusedFiles(ChannelSubscriptions channelSubscriptions, Playlist playlist) { _logger.WriteTimestampedMessage("Cleaning up unused files"); ReportProgress(0, 30, "Cleaning up files..."); // 1. channel data try { CleanUpUnsubscribedChannelFiles(channelSubscriptions); } catch (Exception ex) { _logger.WriteError(ex); } ReportProgress(50, 40); // 2. assets HashSet <string> playlistAssetsToKeep = GetAssetsToKeep(playlist); try { CleanUpAssetFolder(playlistAssetsToKeep); } catch (Exception ex) { _logger.WriteError(ex); } ReportProgress(100, 50); }
/// <summary> /// Executes LogExchanger steps. /// </summary> public void Execute() { if (!_bGlobalsSet) { return; } if (!FileAccessRights()) { return; } if (!TryRecreateDirectoryStructureIfNecessary()) { return; } ChannelSubscriptions channelSubscriptions = GetChannelSubscriptions(); _logger.WriteMessage("GetChannelSubscriptions returned."); if (channelSubscriptions == null) { return; // log exchanger cannot run without channel subscriptions } // lock and load raw logs. bool bRawLogsExist = LoadRawAll(); TimeSpanWrapperClass dateTimeDiff = GetDateTimeDiff(); foreach (ChannelSubscription channelSubscription in channelSubscriptions.SubscriptionSet) { if (!AggregateAndUploadNonAdvertSpecificLogs(channelSubscription.ChannelID, channelSubscription.GetGUIDSuffix(), dateTimeDiff, bRawLogsExist)) { return; } } // adverts: channel 0 if (!AggregateAndUploadNonAdvertSpecificLogs(0, "", dateTimeDiff, bRawLogsExist)) { return; } // advert-specific logs (adverts - channel weighting calculations) AggregateAndUploadAdvertSpecificLogs(channelSubscriptions, dateTimeDiff, bRawLogsExist); // if raw files can't be truncated they will be reprocessed. if (!TruncateRawFiles()) { ReleaseRawFiles(); } TryUploadTruncateReleaseUsageCountFile(bRawLogsExist); _userDataMarshallerStreamerClient.Dispose(); }
private static void GetNonAdvertisingPlaylist(ChannelData channelData, string password, Playlist playlist, DemographicRangeVerifier demographicRangeVerifier, ChannelSubscriptions channelSubscriptions, DateTime now, float defaultDisplayDuration, Logger logger) { // // calculate content playlist // // calculate average play times var avgPlayTimeQuery = from Channel channel in channelData.Channels join channelSubscription in channelSubscriptions.SubscriptionSet on channel.ChannelID equals channelSubscription.ChannelID from ChannelAsset channelAsset in channel.ChannelAssets group channelAsset by channel.ChannelID into groupedAssets select new { ChannelID = groupedAssets.Key, AveragePlayTime = (float)groupedAssets.Average(channelAsset => channelAsset.DisplayDuration == -1F ? defaultDisplayDuration : channelAsset.DisplayDuration) }; float sumAveragePlayTimes = 0F; foreach (var channel in avgPlayTimeQuery) { sumAveragePlayTimes += channel.AveragePlayTime; } // calculate playing probability of each channel var channelBuckets = HashSetLinqAccess.ToHashSet <ChannelBucket>(from ChannelSubscription channelSubscription in channelSubscriptions.SubscriptionSet join channel in avgPlayTimeQuery on channelSubscription.ChannelID equals channel.ChannelID join channelDataChannel in channelData.Channels on channel.ChannelID equals channelDataChannel.ChannelID select new ChannelBucket { ChannelID = channel.ChannelID, ChannelName = channelSubscription.ChannelName, AveragePlayTime = channel.AveragePlayTime, PlayingProbabilityUnnormalized = channel.AveragePlayTime > 0 && sumAveragePlayTimes > 0 ? (float)channelSubscription.ChannelWeightingUnnormalised / (channel.AveragePlayTime / sumAveragePlayTimes) : 0, ContentAssets = ConvertChannelAssetsToPlayListAssetsIfDateTimeDemoPermits(channelDataChannel, demographicRangeVerifier, now) }); if (channelBuckets.Count == 0) { return; } playlist.ChannelBuckets = channelBuckets; // normalize playing probabilities NormalizeChannelBucketPlayingProbabilities(playlist.ChannelBuckets, logger); }
private bool AggregateAndUploadAdvertSpecificLogs(ChannelSubscriptions channelSubscriptions, TimeSpanWrapperClass dateTimeDiff, bool bRawLogsExist) { // work unit 1: aggregate to flat aggregated files bool bAggregatedAdvertSpecificLogsExist = LoadAggregatedAdvertSpecific(); // if no logs exist, return. if (!bRawLogsExist && !bAggregatedAdvertSpecificLogsExist) { ReleaseAggregatedFiles(); return(true); } // if we have the time difference, time-correct if (dateTimeDiff != null) { TimeCorrect(dateTimeDiff.TimeSpan); } AggregateRawDataToMemoryAdvertSpecific(channelSubscriptions); // append aggregated data from memory to files. AppendAggregatedDataAdvertSpecific(); ReleaseAggregatedFiles(); // // Work unit 2: upload data from aggregated files and truncate if successful // // search again for responsive server string sendLogURI = GetResponsiveServer(ServerType.RelayLogAdv, _maxNoRelayLogServers, _machineGUIDSuffix, "UserDataMarshaller.svc"); // if no responsive servers found, return if (sendLogURI == "") { _logger.WriteTimestampedMessage("AggregateAndUploadNonAdvertSpecificLogs: URL not found"); return(true); } _logger.WriteTimestampedMessage("AggregateAndUploadNonAdvertSpecificLogs: URL: " + sendLogURI + "/file"); _userDataMarshallerStreamerClient.Endpoint.Address = new EndpointAddress(sendLogURI + "/file"); UploadAdvertSpecificAggregatedFiles(); // truncate aggregated files. no need to check if there was an error as this is near the end of the LogExchanger TruncateAdvertSpecificAggregatedFilesIfUploaded(); ReleaseAggregatedFiles(); return(true); }
[DynamicContent(MaxAgeInSeconds = 10800)] // 3 hours public ActionResult Subscriptions(string id) { ChannelSubscriptions subscriptions = (new DAService("Oxigen")).GetUserChannelSubscriptions(null, id); // for backwards compatibility, unused userGUID param is set to null instead of creating another method and propagating it to the WCF contracts. if (subscriptions.SubscriptionSet == null) { return(HttpNotFound()); } byte[] subscriptionsInBytes = Serializer.SerializeClearToByteArray(subscriptions); var fileContentResult = new FileContentResult(subscriptionsInBytes, System.Net.Mime.MediaTypeNames.Application.Octet); fileContentResult.FileDownloadName = "ss_channel_subscription_data.dat"; return(fileContentResult); }
private static void GetAdvertisingPlaylist(string advertListPath, string demographicDataPath, DemographicRangeVerifier demographicRangeVerifier, string password, Playlist playlist, ChannelData channelData, ChannelSubscriptions channelSubscriptions, DateTime now, Logger logger) { // if the advertisment or the demographic data file is not found, an exception will be thrown // if user has corrupted any of the files, an exception will be thrown AdvertList advertList = (AdvertList)Serializer.Deserialize(typeof(AdvertList), advertListPath, password); // flatten channel definitions HashSet <string> channelDefinitions = new HashSet <string>(); foreach (Channel channel in channelData.Channels) { SplitAndInsertChannelDefinitions(ref channelDefinitions, channel.ChannelDefinitions); } // flatten advert definitions HashSet <string> advertDefinitions = new HashSet <string>(); foreach (AdvertAsset advertasset in advertList.Adverts) { SplitAndInsertChannelDefinitions(ref advertDefinitions, advertasset.AdvertDefinitions); } var advertListsFiltered = HashSetLinqAccess.ToHashSet <AdvertPlaylistAsset>(from AdvertAsset advertAsset in advertList.Adverts where demographicRangeVerifier.IsAssetDemoSyntaxPlayable(advertAsset.DemoRequirements) && TreeSearch.IncludeByChannelClassifications(channelDefinitions, advertAsset.InclusionExclusionList) == true && TreeSearch.IncludeByAdvertClassifications(advertDefinitions, channelData, channelSubscriptions) == true && now >= advertAsset.StartDateTime && now <= advertAsset.EndDateTime select new AdvertPlaylistAsset { AssetID = advertAsset.AssetID, AssetFilename = advertAsset.AssetFilename, ClickDestination = advertAsset.ClickDestination, AssetWebSite = advertAsset.AssetWebSite, PlayerType = advertAsset.PlayerType, ScheduleInfo = advertAsset.ScheduleInfo, DisplayLength = advertAsset.DisplayDuration, WeightingUnnormalized = advertAsset.Weighting, StartDateTime = advertAsset.StartDateTime, EndDateTime = advertAsset.EndDateTime }); playlist.AdvertBucket.AdvertAssets = advertListsFiltered; }
private ChannelSubscriptions FilterChannelSubscriptionsByLock(ChannelSubscriptions channelSubscriptions) { ChannelSubscriptions newSubscriptions = new ChannelSubscriptions(); if (channelSubscriptions == null || channelSubscriptions.SubscriptionSet.Count == 0) { return(newSubscriptions); } foreach (ChannelSubscription subscription in channelSubscriptions.SubscriptionSet) { if (!subscription.Locked) { newSubscriptions.SubscriptionSet.Add(subscription); } } return(newSubscriptions); }
private void GetChannelDataFiles(ChannelSubscriptions channelSubscriptions, ref bool bCancelled, WebClient client) { ReportProgress(0, 10, "Updating your subscriptions' playlist"); _logger.WriteTimestampedMessage("Getting channel data files"); int noSubscriptions = channelSubscriptions.SubscriptionSet.Count; float step = 100F / (float)noSubscriptions; float count = 0; RequestCacheLevel cacheLevel = _verboseMode ? RequestCacheLevel.Revalidate : RequestCacheLevel.Default; client.CachePolicy = new RequestCachePolicy(cacheLevel); // get channel data for each channel subscription foreach (ChannelSubscription channelSubscription in channelSubscriptions.SubscriptionSet) { if (_worker != null && _worker.CancellationPending) { bCancelled = true; return; } ReportProgress(count * step, 10, "Updating playlist for Stream: " + channelSubscription.ChannelName); // checksum of channel file string channelFileFullPath = _channelDataPath + channelSubscription.ChannelID + "_channel.dat"; try { _logger.WriteTimestampedMessage("Attempting to get Channel " + channelSubscription.ChannelID); client.DownloadFile(_cdnSubdomain + "channel/" + channelSubscription.ChannelID + "_channel.dat", channelFileFullPath); } catch (Exception ex) { // write error but do not return. continue with the other channels. _logger.WriteError(ex); } } ReportProgress(100, 20); }
private void CleanUpUnsubscribedChannelFiles(ChannelSubscriptions channelSubscriptions) { string[] allChannelDataFilenames = Directory.GetFiles(_channelDataPath, "*.dat"); int noSubscriptions = channelSubscriptions.SubscriptionSet.Count; if (allChannelDataFilenames.Length == 0) { //_logger.WriteTimestampedMessage("No channel data files."); return; } int subscriptionCount = 0; // create an array to contain the files that correspond to the updates subscribed channel list string[] channelSubscriptionFiles = new string[noSubscriptions]; foreach (ChannelSubscription channelSubscription in channelSubscriptions.SubscriptionSet) { channelSubscriptionFiles[subscriptionCount] = _channelDataPath + channelSubscription.ChannelID.ToString() + "_channel.dat"; subscriptionCount++; } int noAllChannelDataFileNames = allChannelDataFilenames.Length; if (noAllChannelDataFileNames > 0) { // search the two arrays and clean the files that no longer match the subscription list foreach (string existingFileName in allChannelDataFilenames) { if (Array.IndexOf <string>(channelSubscriptionFiles, existingFileName) == -1) { _logger.WriteTimestampedMessage("Deleting " + existingFileName); File.Delete(existingFileName); } } } }
private ChannelSubscriptions GetChannelSubscriptions() { if (!File.Exists(_userChannelSubscriptionsPath)) { _logger.WriteTimestampedMessage("Channel subscriptions don't exist"); return(null); } ChannelSubscriptions channelSubscriptions = null; try { channelSubscriptions = (ChannelSubscriptions)Serializer.Deserialize(typeof(ChannelSubscriptions), _userChannelSubscriptionsPath, _systemPassPhrase); } catch (Exception ex) { _logger.WriteError(ex); return(null); } return(channelSubscriptions); }
/// <summary> /// Gets the channel subscriptions from disk and normalizes their channel weightings /// </summary> /// <returns>a ChannelSubscriptions object with channel subscription information</returns> private ChannelSubscriptions GetChannelSubscriptions() { if (!File.Exists(_channelSubscriptionPath)) { return(null); } ChannelSubscriptions channelSubscriptions = null; try { channelSubscriptions = (ChannelSubscriptions)Serializer.Deserialize(typeof(ChannelSubscriptions), _channelSubscriptionPath, _password); } catch (Exception ex) { _logger.WriteError(ex); return(null); } channelSubscriptions.NormalizeChannelWeightings(); return(channelSubscriptions); }
/// <summary> /// Creates the playlist for the user /// </summary> /// <param name="channelDataPath">Directory on the end user's computer where channel content files reside</param> /// <param name="advertListPath">Fully qualified path of the advert list file on the end user's computer</param> /// <param name="demographicDataPath">Fully qualified path of the demographic data path on the end user's computer</param> /// <param name="playlistDataPath">Fully qualified path on the end user's computer to save the playlist to</param> /// <param name="password">Encryption password</param> /// <param name="channelSubscriptions">ChannelSubscriptions object with the user's channel subscriptions</param> /// <param name="logger">Logger to log debug/error messages</param> /// <exception cref="System.Runtime.Serialization.SerializationException">Thrown when an error occurs during serialization/deserializaton</exception> /// <exception cref="InvalidOperationException">Thrown when file to be serialized don't match the deserializer's expected type</exception> /// <exception cref="DirectoryNotFoundException">thrown when directory to save or load a file from is not found</exception> /// <exception cref="FileNotFoundException">thrown when a file is not found</exception> /// <exception cref="CryptographicException">thrown when a serialized file is corrupted</exception> public static Playlist CreatePlaylist(string channelDataPath, string advertListPath, string demographicDataPath, string playlistDataPath, string password, float defaultDisplayDuration, ChannelSubscriptions channelSubscriptions, Logger logger) { Playlist playlist = new Playlist(); // holds the channels to which the user is subscribed ChannelData channelData = new ChannelData(); // check if channel data directory exists! if (!Directory.Exists(channelDataPath)) { return(null); } string[] fileEntries = Directory.GetFiles(channelDataPath, "*.dat"); if (channelSubscriptions.SubscriptionSet.Count == 0 || fileEntries.Length == 0) { return(playlist); } foreach (string file in fileEntries) { channelData.Channels.Add((Channel)Serializer.Deserialize(typeof(Channel), file, "password")); } if (!File.Exists(demographicDataPath)) { return(null); } DateTime now = DateTime.Now; DemographicData demographicData = (DemographicData)Serializer.Deserialize(typeof(DemographicData), demographicDataPath, password); DemographicRangeVerifier demographicRangeVerifier = new DemographicRangeVerifier(demographicData); GetNonAdvertisingPlaylist(channelData, password, playlist, demographicRangeVerifier, channelSubscriptions, now, defaultDisplayDuration, logger); // advertising playlist GetAdvertisingPlaylist(advertListPath, demographicDataPath, demographicRangeVerifier, password, playlist, channelData, channelSubscriptions, now, logger); Serializer.Serialize(playlist, playlistDataPath, password); return(playlist); }
/// <summary> /// Updates application data and asset files from the relay server, generates the user's playlist /// and cleans up any old files /// </summary> internal ExchangeStatus Execute() { CELog log = null; ExchangeStatus status = new ExchangeStatus(); bool bContentDownloaded = false; if (!_bGlobalsSet) { _logger.WriteTimestampedMessage("Error Setting Globals. Exiting Content Exchanger"); status.ExitWithError = true; status.ContentDownloaded = false; log = new CELog(DateTime.Now, status.ContentDownloaded, status.ExitWithError); log.SaveLog(); return(status); } status.LowDiskSpace = IsDiskSpaceLow(); if (status.LowDiskSpace) { _logger.WriteTimestampedMessage("Low Disk Space. Exiting Content Exchanger"); status.ExitWithError = true; status.ContentDownloaded = false; log = new CELog(DateTime.Now, status.ContentDownloaded, status.ExitWithError); log.SaveLog(); return(status); } if (!DirStructureOK()) { _logger.WriteTimestampedMessage("Error checking disk structure. Exiting Content Exchanger"); status.ExitWithError = true; status.ContentDownloaded = false; log = new CELog(DateTime.Now, status.ContentDownloaded, status.ExitWithError); log.SaveLog(); return(status); } if (!FileAccessRights()) { _logger.WriteTimestampedMessage("Insufficient file access rights. Exiting Content Exchanger"); status.ExitWithError = true; status.ContentDownloaded = false; log = new CELog(DateTime.Now, status.ContentDownloaded, status.ExitWithError); log.SaveLog(); return(status); } try { FailedInternetConnectionAttemptFileAccessor failedAttemptAccessor = new FailedInternetConnectionAttemptFileAccessor(); try { SendHeartbeat(_machineGUID); failedAttemptAccessor.ResetFailedAttempts(); } catch (WebException) { failedAttemptAccessor.RecordFailedAttempt(); if (RunsInTheBackground) { if (failedAttemptAccessor.GetFailedAttempts() >= MAX_NO_FAILED_INTERNET_CONNECTION_ATTEMPTS) { MessageBox.Show("Oxigen is having trouble communicating via the Internet. Please see the FAQs to ensure your PC is correctly configured.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); failedAttemptAccessor.ResetFailedAttempts(); status.ExitWithError = true; status.ContentDownloaded = false; return(status); } } throw; } // update config files bool bCancelled = false; using (WebClient client = new WebClient()) { if (client.Proxy != null) { client.Proxy.Credentials = CredentialCache.DefaultCredentials; } UpdateConfigFiles(client, ref bCancelled); if (bCancelled) { status.ExitWithError = false; log = new CELog(DateTime.Now, status.ContentDownloaded, status.ExitWithError); log.SaveLog(); return(status); } // raed the downloaded channel subscriptions ChannelSubscriptions channelSubscriptions = GetChannelSubscriptions(); if (channelSubscriptions == null) { _logger.WriteTimestampedMessage("No channel subscripitions found. Exiting Content Exchanger"); ReportProgress(100, 100); status.ExitWithError = false; status.ContentDownloaded = false; log = new CELog(DateTime.Now, status.ContentDownloaded, status.ExitWithError); log.SaveLog(); return(status); } channelSubscriptions = FilterChannelSubscriptionsByLock(channelSubscriptions); // get the channel data files GetChannelDataFiles(channelSubscriptions, ref bCancelled, client); if (bCancelled) { status.ExitWithError = false; log = new CELog(DateTime.Now, status.ContentDownloaded, status.ExitWithError); log.SaveLog(); return(status); } // Generate Playlist Playlist playlist = null; ReportProgress(0, 20, "Creating the local playlist"); try { playlist = PlaylistMaker.CreatePlaylist(_channelDataPath, _advertDataPath, _demographicDataPath, _playlistPath, _password, _defaultDisplayDuration, channelSubscriptions, _logger); } catch (Exception ex) { _logger.WriteError(ex); _logger.WriteTimestampedMessage("Exiting Content Exchanger"); ReportProgress(100, 100); status.ExitWithError = true; status.ContentDownloaded = false; log = new CELog(DateTime.Now, status.ContentDownloaded, status.ExitWithError); log.SaveLog(); return(status); } ReportProgress(100, 30); // clean up unused files CleanUpUnusedFiles(channelSubscriptions, playlist); if (_worker != null && _worker.CancellationPending) { status.ExitWithError = false; log = new CELog(DateTime.Now, status.ContentDownloaded, status.ExitWithError); log.SaveLog(); return(status); } bool bLowAssetSpace = false; // Get content and advert files bool bAssetFilesSuccessful = GetAssetFiles(playlist, ref bLowAssetSpace, ref bContentDownloaded, ref bCancelled, client); if (bCancelled) { status.ContentDownloaded = bContentDownloaded; status.ExitWithError = false; log = new CELog(DateTime.Now, status.ContentDownloaded, status.ExitWithError); log.SaveLog(); return(status); } status.ContentDownloaded = bContentDownloaded; status.ExitWithError = !bAssetFilesSuccessful; status.LowAssetSpace = bLowAssetSpace; } } catch (Exception ex) { _logger.WriteError(ex); status.ExitWithError = true; } _logger.WriteTimestampedMessage("Exiting Content Exchanger"); ReportProgress(100, 100); log = new CELog(DateTime.Now, status.ContentDownloaded, status.ExitWithError); log.SaveLog(); return(status); }
/// <summary> /// Calculates the Advert click proportions per channel according to channel weighting /// </summary> /// <param name="advertClickLog">advert click log</param> /// <param name="channelSubscriptions">user channel subscriptions with normalized channel weightings</param> /// <returns>a List with the proportions</returns> public static List <AdvertChannelOperationProportions> GetAdvertChannelClickProportions(List <ClickLogEntry> advertClickLog, ChannelSubscriptions channelSubscriptions) { var advertTotalClicks = from ClickLogEntry clickLogEntry in advertClickLog group clickLogEntry by clickLogEntry.AssetID into groupedAdvertsByID select new { AdvertID = groupedAdvertsByID.Key, AdvertTotalClicks = groupedAdvertsByID.Count() }; var advertChannelClickProportions = from advert in advertTotalClicks select new AdvertChannelOperationProportions { AdvertAssetID = advert.AdvertID, ChannelAdvertOperationStats = (from ChannelSubscription channelSubscription in channelSubscriptions.SubscriptionSet select new ChannelAdvertOperationStat { ChannelID = channelSubscription.ChannelID, AdvertOperationProportion = (float)advert.AdvertTotalClicks * channelSubscription.ChannelWeightingNormalised }).ToList <ChannelAdvertOperationStat>() }; return(advertChannelClickProportions.ToList <AdvertChannelOperationProportions>()); }
/// <summary> /// Calculates the Advert show proportions per channel according to channel weighting /// </summary> /// <param name="advertImpressionLog">advert show log</param> /// <param name="channelSubscriptions">user channel subscriptions with normalized channel weightings</param> /// <returns>a List with the proportions</returns> public static List <AdvertChannelOperationProportions> GetAdvertChannelImpressionProportions(List <ImpressionLogEntry> advertImpressionLog, ChannelSubscriptions channelSubscriptions) { var advertTotalPlayTimes = from ImpressionLogEntry impressionLogEntry in advertImpressionLog group impressionLogEntry by impressionLogEntry.AssetID into groupedAdvertsByID select new { AdvertID = groupedAdvertsByID.Key, AdvertTotalPlayTime = groupedAdvertsByID.Sum(impressionLogEntry => impressionLogEntry.Duration) }; var advertChannelPlayProportions = from advert in advertTotalPlayTimes select new AdvertChannelOperationProportions { AdvertAssetID = advert.AdvertID, ChannelAdvertOperationStats = (from ChannelSubscription channelSubscription in channelSubscriptions.SubscriptionSet select new ChannelAdvertOperationStat { ChannelID = channelSubscription.ChannelID, AdvertOperationProportion = (float)advert.AdvertTotalPlayTime * channelSubscription.ChannelWeightingNormalised }).ToList <ChannelAdvertOperationStat>() }; return(advertChannelPlayProportions.ToList <AdvertChannelOperationProportions>()); }
/// <summary> /// Checks if an advert is to be included in the playlist by checking the advert's classifications against the channel's rules /// (channels selecting which adverts to feature). /// The list that holds the inclusion and exclusion rules.It has already been sorted from least specific to most specific. /// </summary> /// <param name="advertDefinitions">All the advert definitions of all the adverts in the Advert Taxonomy tree</param> /// <param name="channelData">The Channel Data with advert exclusion/inclusion listings. The listings are already sorted from less to more specific (per channel and not overall).</param> /// <param name="channelSubscriptions">User's channel subscription class. Used to extract channel weighting information.</param> /// <returns>true means advert is included in the playlist</returns> public static bool IncludeByAdvertClassifications(HashSet <string> advertDefinitions, ChannelData channelData, ChannelSubscriptions channelSubscriptions) { // initialize the 'decision lolipop' bool bInclude = true; // initialize a Dictionary with channel inclusions exclusions Dictionary <Channel, bool> channelInclusionsExclusions = new Dictionary <Channel, bool>(); // fill in the dictionary of channel inclusions exclusions with all the channels. // default all inclusions/exclusions to true, as bool is value-type foreach (Channel channel in channelData.Channels) { channelInclusionsExclusions.Add(channel, true); } // keep the voting thresholds of the channels who vote to exclude the advert HashSet <float> excludingVotingThresholds = new HashSet <float>(); float currentChannelWeighting = 0F; float totalChannelWeighting = 0F; float totalExcludeChannelWeighting = 0F; float averageExclusionPercentage = 0F; // Algorithm starts here foreach (Channel channel in channelData.Channels) { channelInclusionsExclusions[channel] = true; foreach (string advertDefinition in advertDefinitions) { bInclude = true; foreach (InclusionExclusionRule inclusionExclusionRule in channel.InclusionExclusionList) { if (advertDefinition.StartsWith(inclusionExclusionRule.Rule)) { bInclude = inclusionExclusionRule.IncEx == IncludeExclude.Include; } } // Until either an Advert Classification (Definition) is classsified as Excluded if (!bInclude) { channelInclusionsExclusions[channel] = false; break; } } } // calculate the AEP foreach (Channel channel in channelData.Channels) { currentChannelWeighting = (float)channelSubscriptions.GetChannelWeightingUnnormalisedByChannelID(channel.ChannelID); totalChannelWeighting += currentChannelWeighting; // The channel weightings between 0 - 100 if (!channelInclusionsExclusions[channel]) { totalExcludeChannelWeighting += currentChannelWeighting; } } averageExclusionPercentage = (totalExcludeChannelWeighting / totalChannelWeighting) * 100F; foreach (Channel channel in channelData.Channels) { if (!channelInclusionsExclusions[channel]) { // The voting thresholds are between 0 - 100 if (averageExclusionPercentage >= channel.VotingThreshold) { return(false); } } } return(true); }
private void AggregateRawDataToMemoryAdvertSpecific(ChannelSubscriptions channelSubscriptions) { _advertChannelClickProportionsSet = LogStatsCalculator.GetAdvertChannelClickProportions(_advertClickLog, channelSubscriptions); _advertChannelImpressionProportionsSet = LogStatsCalculator.GetAdvertChannelImpressionProportions(_advertImpressionLog, channelSubscriptions); }