Skip to content

Instantly share code, notes, and snippets.

@thomasforth
Created July 11, 2020 12:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thomasforth/9c794dd6786c59e8b5b44194f893b6de to your computer and use it in GitHub Desktop.
Save thomasforth/9c794dd6786c59e8b5b44194f893b6de to your computer and use it in GitHub Desktop.
Big Belly Analysis
using CsvHelper;
using CsvHelper.Configuration;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
namespace BigBellyAnalysis
{
class Program
{
static void Main(string[] args)
{
List<BinCollection> BigBellyBinCollections = new List<BinCollection>();
using (StreamReader reader = new StreamReader(@"Assets/Daily Collection Activity - CLEAN.csv"))
{
using (CsvReader csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
csv.Configuration.RegisterClassMap<BinsClassMap>();
BigBellyBinCollections = csv.GetRecords<BinCollection>().ToList();
}
}
foreach (BinCollection bc in BigBellyBinCollections)
{
if (bc.FullnessLevelatCollection == " Alert - Unknown Fullness")
{
bc.FullnessLevelAtCollectionDecimal = 0;
}
else
{
bc.FullnessLevelAtCollectionDecimal = Decimal.Parse(bc.FullnessLevelatCollection.Replace("%", "")) / 100;
}
}
Dictionary<string, BinLocation> BinLocationsDictionary = new Dictionary<string, BinLocation>();
using (StreamReader reader = new StreamReader(@"Assets/Account Assets - CLEAN.csv"))
{
using (CsvReader csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
csv.Configuration.RegisterClassMap<BinLocationClassMap>();
BinLocationsDictionary = csv.GetRecords<BinLocation>().ToDictionary(x => x.Serial, x => x);
}
}
List<string> UniqueBins = BigBellyBinCollections.Select(x => x.Serial).Distinct().ToList();
// We assume that a Big Belly bin at 100% holds 500 litres of uncompacted waste -- compressed by a factor of 4 to 125 litres.
// We round all of our times to days, with the cut off at midday.
// Let's assume that a Big Belly bin fills at a constant rate between emptyings.
int binvolume = 500;
List<BinCumulative> CumulativeBins = new List<BinCumulative>();
List<BinCumulative> InterpolatedWasteCollections = new List<BinCumulative>();
foreach (string BinSerial in UniqueBins)
{
DateTime StartDate = BigBellyBinCollections.Where(x => x.Serial == BinSerial).Min(x => x.CollectionTime).Date;
DateTime LatestDate = BigBellyBinCollections.Where(x => x.Serial == BinSerial).Max(x => x.CollectionTime).Date;
decimal lastCumulativeWaste = 0;
for (DateTime day = StartDate; day <= LatestDate; day = day.AddDays(1))
{
BinCumulative bc = new BinCumulative();
bc.Serial = BinSerial;
bc.Date = day;
bc.CumulativeWasteDeposited_litres = BigBellyBinCollections.Where(x => x.Serial == BinSerial &&
x.CollectionTime.Date < day.AddDays(0.5)).Sum(x => x.FullnessLevelAtCollectionDecimal) * binvolume;
bc.EstimatedWasteDepositedThisDay_litres = bc.CumulativeWasteDeposited_litres - lastCumulativeWaste;
lastCumulativeWaste = bc.CumulativeWasteDeposited_litres;
CumulativeBins.Add(bc);
}
// now interpolate
List<BinCumulative> BCsToSpreadWasteAcross = new List<BinCumulative>();
foreach (BinCumulative bc in CumulativeBins.Where(x => x.Serial == BinSerial))
{
if (bc.EstimatedWasteDepositedThisDay_litres == 0)
{
BCsToSpreadWasteAcross.Add(bc);
}
else if (BCsToSpreadWasteAcross.Count != 0)
{
BCsToSpreadWasteAcross.Add(bc);
int count = BCsToSpreadWasteAcross.Count;
decimal increment = Math.Round(bc.EstimatedWasteDepositedThisDay_litres / count, 2);
BCsToSpreadWasteAcross.ForEach(x => x.EstimatedWasteDepositedThisDay_litres = increment);
BCsToSpreadWasteAcross.Clear();
}
else
{
InterpolatedWasteCollections.Add(bc);
}
}
}
// fix cumulative and add bin location
foreach (BinCumulative bc in CumulativeBins)
{
bc.CumulativeWasteDeposited_litres = CumulativeBins.Where(x => x.Serial == bc.Serial && x.Date <= bc.Date).Sum(x => x.EstimatedWasteDepositedThisDay_litres);
bc.Latitude = Math.Round(BinLocationsDictionary[bc.Serial].Lat,5);
bc.Longitude = Math.Round(BinLocationsDictionary[bc.Serial].Lng,5);
}
using (TextWriter _textWriter = File.CreateText("CumulativeBins.csv")) {
using (CsvWriter _csvwriter = new CsvWriter(_textWriter, CultureInfo.CurrentCulture))
{
_csvwriter.WriteRecords(CumulativeBins);
}
}
}
}
public class BinCumulative
{
public string Serial { get; set; }
public DateTime Date { get; set; }
public decimal EstimatedWasteDepositedThisDay_litres { get; set; }
public decimal CumulativeWasteDeposited_litres { get; set; }
public decimal Latitude { get; set; }
public decimal Longitude { get; set; }
}
public class BinCollection
{
public string Serial { get; set; }
public string Description { get; set; }
public string Capacity { get; set; }
public string StreamType { get; set; }
public string Reason { get; set; }
public string FullnessLevelatCollection { get; set; }
public decimal FullnessLevelAtCollectionDecimal { get; set; }
public DateTime CollectionTime { get; set; }
}
public class BinsClassMap : ClassMap<BinCollection>
{
public BinsClassMap()
{
Map(m => m.Serial).Name("Serial");
Map(m => m.Description).Name("Description");
Map(m => m.Capacity).Name("Capacity");
Map(m => m.StreamType).Name("Stream Type");
Map(m => m.Reason).Name("Reason");
Map(m => m.FullnessLevelatCollection).Name("Fullness Level at Collection");
Map(m => m.CollectionTime).Name("Collection Time");
}
}
public class BinLocation
{
public string Description { get; set; }
public string Serial { get; set; }
public string Streams { get; set; }
public string Model { get; set; }
public string Capacity { get; set; }
public string Status { get; set; }
public string FullnessThreshold { get; set; }
public string AgeThreshold { get; set; }
public string LastCalled { get; set; }
public decimal Lat { get; set; }
public decimal Lng { get; set; }
}
public class BinLocationClassMap : ClassMap<BinLocation>
{
public BinLocationClassMap()
{
Map(m => m.Description).Name("Description");
Map(m => m.Serial).Name("Serial");
Map(m => m.Streams).Name("Streams");
Map(m => m.Model).Name("Model");
Map(m => m.Capacity).Name("Capacity");
Map(m => m.Status).Name("Status");
Map(m => m.FullnessThreshold).Name("Fullness Threshold");
Map(m => m.AgeThreshold).Name("Age Threshold");
Map(m => m.LastCalled).Name("Last Called");
Map(m => m.Lat).Name("Lat");
Map(m => m.Lng).Name("Lng");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment