anchor.diff:    isNew: Boolean;
     socChart: TChart;
     t: TDateTime;
  +  tableExists: boolean;
   const
     SocChartID = 'santosSoc';
   begin
     zero := SantosTimeToDateTime('00:00', fBaseDay);
  -  //StrToTime('00:00');
  -
  -  TMonitor.Enter(fProjectCurrentScenario.Charts);
  +  tableName := aTablePrefix + 'EBUS_INDIC_DAT' + cINDIC_DAT_TYPE_BLOCK +
  +               fCurrentBusBlock.ToString.PadLeft(2,'0') + cINDIC_DAT_BLOCK_SOC;
  +
  +  tableExists := MyOraLib.tableExists(aSession, tableName);
  +
  +  TMonitor.Enter(aScenario.Charts);
     try
  -    isNew := not fProjectCurrentScenario.Charts.TryGetValue(SocChartID, socChart);
  +    isNew := not aScenario.Charts.TryGetValue(SocChartID, socChart);
     finally
  -    TMonitor.Exit(fProjectCurrentScenario.Charts);
  -  end;
  -
  -  if isNew then
  -  begin
  -    socChart := TChartLines.Create(fProjectCurrentScenario, 'Santos' , SocChartID, 'State of Charge',
  +    TMonitor.Exit(aScenario.Charts);
  +  end;
  +
  +  if isNew and tableExists then
  +  begin
  +    socChart := TChartLines.Create(aScenario, 'Santos' , SocChartID, 'State of Charge',
                    'State of Charge', True, 'line',
  -              TChartAxis.Create('Time (hour of day)', 'lightBlue', 'Time', 'h'),
  -              [ TChartAxis.Create('State of Charge (%)', 'lightBlue', 'Dimensionless', '%')]);
  -  end;
  -
  -  TMonitor.enter(socChart);
  -  try
  -     // Clear
  -    if not isNew then
  -      socChart.reset;
  -
  -    tableName := aTablePrefix + 'EBUS_INDIC_DAT' + cINDIC_DAT_TYPE_BLOCK + fCurrentBusBlock.ToString.PadLeft(2,'0') + cINDIC_DAT_BLOCK_SOC;
  -
  -    query := TOraQuery.Create(nil);
  +              TChartAxis.Create('Time (hour of day)', 'lightBlue', 'Time', 'h'{, True, 0, 36*60*60}),
  +              [ TChartAxis.Create('State of Charge (%)', 'lightBlue', 'Dimensionless', '%'{, True, 0, 100})]);
  +  end;
  +
  +  if Assigned(socChart) then
  +  begin
  +    TMonitor.enter(socChart);
       try
  -      query.Session := aSession;
  -      query.SQL.Text := 'SELECT X,Y,LPAD(TRIM(TIME), 5, ''0'') as TIME ' +
  -                        'FROM ' + tableName + ' ORDER BY TIME ASC';
  -      query.Open;
  -        while not Query.Eof do
  -        begin
  -          t := SantosTimeToDateTime(Query.FieldByName('TIME').AsString, fBaseDay);
  -          minOfDay := MinutesBetween(zero, t) *60;
  -          (socChart as TChartLines).AddValue(
  -            minOfDay,
  -            [Query.FieldByName('Y').AsFloat/100]
  -          );
  -          Query.Next;
  -        end;
  -
  +       // Clear
  +      if not isNew then
  +        socChart.reset;
  +
  +      if tableExists then
  +      begin
  +        query := TOraQuery.Create(nil);
  +        try
  +          query.Session := aSession;
  +          query.SQL.Text := 'SELECT X,Y,LPAD(TRIM(TIME), 5, ''0'') as TIME ' +
  +                            'FROM ' + tableName + ' ORDER BY TIME ASC';
  +          query.Open;
  +            while not Query.Eof do
  +            begin
  +              t := SantosTimeToDateTime(Query.FieldByName('TIME').AsString, fBaseDay);
  +              minOfDay := MinutesBetween(zero, t) *60;
  +              (socChart as TChartLines).AddValue(
  +                minOfDay,
  +                [Query.FieldByName('Y').AsFloat/100]
  +              );
  +              Query.Next;
  +            end;
  +
  +        finally
  +          query.Free;
  +        end;
  +
  +        if isNew then
  +          aScenario.addChart(socChart);
  +      end;
       finally
  -      query.Free;
  +      TMonitor.Exit(socChart);
       end;
  -
  -    if isNew then
  -      fProjectCurrentScenario.addChart(socChart);
  -  finally
  -    TMonitor.Exit(socChart);
  -  end;
  -end;
  -
  -procedure TSantosProject.ReadChartChargerTotalPower(aSession: TOraSession;
  +  end;
  +end;
  +
  +procedure TSantosProject.ReadChartChargerTotalPower(aSession: TOraSession; aScenario: TScenario;
     const aTablePrefix: string; aCharger: Integer);
   var
     zero, t: TDateTime;
     minOfDay: Integer;
     query: TOraQuery;
     tableName: String;
  -  isNew: Boolean;
  -  socChart: TChart;
  +  isNew, tableExists: Boolean;
  +  chgTotalPowerChart: TChart;
     chartID: string;
   const
     ChgPwrChartID = 'santosChgPwr';
   begin
     zero := SantosTimeToDateTime('00:00', fBaseDay);
  +  tableName := aTablePrefix + 'EBUS_INDIC_DAT' + cINDIC_DAT_TYPE_GRID + aCharger.ToString.PadLeft(2,'0') + cINDIC_DAT_GRID_TOTALPOWER;
  +
  +  tableExists := MyOraLib.TableExists(aSession, tableName);
  +
     chartID := ChgPwrChartID + aCharger.ToString;
   
  -  TMonitor.Enter(fProjectCurrentScenario.Charts);
  +  TMonitor.Enter(aScenario.Charts);
     try
  -    isNew := not fProjectCurrentScenario.Charts.TryGetValue(chartID, socChart);
  +    isNew := not aScenario.Charts.TryGetValue(chartID, chgTotalPowerChart);
     finally
  -    TMonitor.Exit(fProjectCurrentScenario.Charts);
  -  end;
  -
  -  if isNew then
  -  begin
  -    socChart := TChartLines.Create(fProjectCurrentScenario, 'Santos' , chartID, 'Charge Location ' + aCharger.ToString + ' Total Power',
  +    TMonitor.Exit(aScenario.Charts);
  +  end;
  +
  +  if isNew and tableExists then
  +  begin
  +    chgTotalPowerChart := TChartLines.Create(aScenario, 'Santos' , chartID, 'Charge Location ' + aCharger.ToString + ' Total Power',
                     'Charge Location ' + aCharger.ToString + ' Total Power', True, 'line',
                 TChartAxis.Create('Time (hour of day)', 'lightBlue', 'Time', 'h'),
                 [ TChartAxis.Create('Total Power (-)', 'lightBlue', 'Dimensionless', '-')]);
     end;
   
  -  TMonitor.enter(socChart);
  -  try
  -     // Clear
  -    if not isNew then
  -      socChart.reset;
  -
  -    tableName := aTablePrefix + 'EBUS_INDIC_DAT' + cINDIC_DAT_TYPE_GRID + aCharger.ToString.PadLeft(2,'0') + cINDIC_DAT_GRID_TOTALPOWER;
  -
  -    query := TOraQuery.Create(nil);
  +  if Assigned(chgTotalPowerChart) then
  +  begin
  +    TMonitor.enter(chgTotalPowerChart);
       try
  -      query.Session := aSession;
  -      query.SQL.Text := 'SELECT LPAD(TRIM(X), 5, ''0'') as TIME,Y ' +
  -                        'FROM ' + tableName + ' ORDER BY TIME ASC';
  -      query.Open;
  -        while not Query.Eof do
  -        begin
  -          t := SantosTimeToDateTime(Query.FieldByName('TIME').AsString,fBaseDay);
  -          minOfDay := MinutesBetween(zero, t) *60;
  -          (socChart as TChartLines).AddValue(
  -            minOfDay,
  -            [Query.FieldByName('Y').AsFloat]
  -          );
  -          Query.Next;
  -        end;
  -
  +       // Clear
  +      if not isNew then
  +        chgTotalPowerChart.reset;
  +
  +      if tableExists then
  +      begin
  +        query := TOraQuery.Create(nil);
  +        try
  +          query.Session := aSession;
  +          query.SQL.Text := 'SELECT LPAD(TRIM(X), 5, ''0'') as TIME,Y ' +
  +                            'FROM ' + tableName + ' ORDER BY TIME ASC';
  +          query.Open;
  +            while not Query.Eof do
  +            begin
  +              t := SantosTimeToDateTime(Query.FieldByName('TIME').AsString,fBaseDay);
  +              minOfDay := MinutesBetween(zero, t) *60;
  +              (chgTotalPowerChart as TChartLines).AddValue(
  +                minOfDay,
  +                [Query.FieldByName('Y').AsFloat]
  +              );
  +              Query.Next;
  +            end;
  +
  +        finally
  +          query.Free;
  +        end;
  +      end;
  +
  +      if isNew then
  +        aScenario.addChart(chgTotalPowerChart);
       finally
  -      query.Free;
  +      TMonitor.Exit(chgTotalPowerChart);
       end;
  -
  -    if isNew then
  -      fProjectCurrentScenario.addChart(socChart);
  -  finally
  -    TMonitor.Exit(socChart);
  +  end;
  +end;
  +
  +function TSantosProject.ReadScenario(const aID: string): TScenario;
  +var
  +  dbScenario: TUSDBScenario;
  +  oraSession: TOraSession;
  +  tablePrefix: string;
  +  santosLayer: TSantosLayer;
  +begin
  +  Result := inherited; // TUSStuff
  +  if Assigned(Result) then
  +  begin
  +    TMonitor.Enter(fSantosLayers);
  +    try
  +      if not fSantosLayers.TryGetValue(Result, santosLayer) then
  +      begin
  +        // Scenario found, add to it
  +        oraSession := TOraSession.Create(nil);
  +        try
  +          oraSession.ConnectString := (self as TMCProject).controlInterface.DataSource;
  +          oraSession.Open;
  +
  +          tablePrefix := (Result as TUSScenario).Tableprefix;
  +//          GetScenarioTablePrefix(oraSession,  aID);
  +          ReadChartBlockSoC(oraSession, Result, tablePrefix);
  +          ReadChartChargerTotalPower(oraSession, Result, tablePrefix, 2); // TODO
  +        finally
  +          oraSession.Free;
  +        end;
  +
  +        santosLayer := TSantosLayer.Create(Result, fCurrentBusBlock, fBaseDay[0], fBaseDay[1], fBaseDay[2], 'Santos', 'Santos'+fCurrentBusBlock.ToString,
  +          'Bus block '+fCurrentBusBlock.ToString, 'Bus block '+fCurrentBusBlock.ToString+' stops',
  +          (self as TMCProject).controlInterface.DataSource, tablePrefix, fIMB3Connection.Publish('EBUS_CHARGELOCATION'));
  +
  +        Result.AddLayer(santosLayer);
  +        fSantosLayers.Add(Result, santosLayer);
  +      end;
  +    finally
  +      System.TMonitor.Exit(fSantosLayers);
  +    end;
     end;
   end;
   
  
positive.code:       active: Boolean;
        selectedEvent: TJSONValue;
        brush: TJSONValue;
      begin
        if aPayload.TryGetValue<boolean>('active', active) then
        begin
          // layer.live[aClient] := not active;
        end;
        if aPayload.TryGetValue<string>('selectedTime', selectedTime) then
        begin
          fTimeSliderTimer.Arm(DateTimeDelta2HRT(0.1*dtOneSecond),
            procedure (aTimer: TTimer; aTime: THighResTicks)
            begin
              fSantosLayer.handleNewTime(aClient, selectedTime);
            end);
        end;
        if aPayload.TryGetValue<TJSONValue>('selectedEvent', selectedEvent) then
        begin
            fSantosLayer.HandleSelectedEvent(aClient, selectedEvent);
        end;
        if aPayload.TryGetValue<TJSONValue>('brush', brush) then
        begin  // Time range selection
          Log.WriteLn('brush: '+brush.toJSON, llWarning);
        end;
      end);
    // Add the layer
    fProjectCurrentScenario.AddLayer(fSantosLayer);
  end;
  
  procedure TSantosProject.ReadChartBlockSoC(aSession: TOraSession; const aTablePrefix: string);
  var
    zero: TDateTime;
    minOfDay: Integer;
  
negative.code:   private
      fTimeSliderTimer: TTimer;
      fCurrentBusBlock: Integer;
      fSantosLayers: TObjectDictionary<TScenario, TSantosLayer>; // ref
      fBaseDay: Array of Word;
    protected
      function  ReadScenario(const aID: string): TScenario; override;
      procedure ReadChartBlockSoC(aSession: TOraSession; aScenario: TScenario; const aTablePrefix: string);
      procedure ReadChartChargerTotalPower(aSession: TOraSession; aScenario: TScenario; const aTablePrefix: string; aCharger: Integer);
    public
      procedure ReadBasicData(); override;
      procedure handleClientMessage(aClient: TClient; aScenario: TScenario; aJSONObject: TJSONObject); override;
    end;
  
  implementation
  
  const
    // TODO: DB Legend? Ini?
    NoChargeColor: TAlphaRGBPixel = $FFFF0000;
    LowChargeColor: TAlphaRGBPixel = $FFFFA500;
    MediumChargeColor: TAlphaRGBPixel = $FFFFFF00;
    HighChargeColor: TAlphaRGBPixel = $FF008000;
    Nothing: TAlphaRGBPixel = $AAAAAAAA;
  
  function SantosTimeToDateTime(const aTime: string; aBaseDay: Array of word): TDateTime;
  var
  