public static IRobot Create( IterativeRobotConfiguration configuration, SCG.IReadOnlyDictionary <int, ISubsystem> subsystems, SCG.IReadOnlyList <ICommand> commands, IDebugRenderContext debugRenderContext ) { var userCode = new UserCode(subsystems, commands); return(new SubsystemCommandBasedIterativeRobot(configuration, userCode, debugRenderContext)); }
public Task BatchUpdateAsync(SCG.IReadOnlyList <PendingUpdate <K, V> > inputPendingUpdates) { return(ExecCommandAsync(async cmd => { var properties = typeof(V).GetProperties(); bool hasUpdatedColumn = false; var pendingUpdatesByUpdatedPropertyGroup = new MultiValueDictionary <string[], PendingUpdate <K, V> >( new LambdaEqualityComparer <string[]>( (a, b) => a.Length == b.Length && a.Zip(b, (aElement, bElement) => aElement == bElement).All(x => x), a => a.Aggregate(13, (h, x) => h * 17 + x.GetHashCode()) )); var pendingInserts = new SCG.List <PendingUpdate <K, V> >(); foreach (var pendingUpdate in inputPendingUpdates) { if (!pendingUpdate.Base.Exists) { pendingInserts.Add(pendingUpdate); } else { SortedSet <string> updatedProperties = new SortedSet <string>(); foreach (var p in properties) { var columnName = p.Name.ToLower(); if (columnName == "updated") { hasUpdatedColumn = true; continue; } if (object.Equals(p.GetValue(pendingUpdate.Base.Value), p.GetValue(pendingUpdate.Updated.Value))) { continue; } if (columnName == "id") { throw new InvalidStateException(); } else { updatedProperties.Add(p.Name); } } pendingUpdatesByUpdatedPropertyGroup.Add(updatedProperties.ToArray(), pendingUpdate); } } var commandTextBuilder = new StringBuilder(); /* * INSERT INTO test (id, name, updated) * SELECT * unnest(@ids), unnest(@names), unnest(@updateds) * ON CONFLICT (id) DO UPDATE * SET * name = excluded.name, updated = excluded.updated */ var batchIndex = 0; foreach (var kvp in pendingUpdatesByUpdatedPropertyGroup) { var updatedPropertyNames = kvp.Key; var updatedProperties = updatedPropertyNames.Map(n => typeof(V).GetProperty(n)); var updatedColumnNames = kvp.Key.Map(x => x.ToLower()); var pendingUpdates = kvp.Value.ToArray(); var additionalColumns = new SCG.List <string>(); var idParameter = cmd.CreateParameter(); idParameter.ParameterName = "id" + batchIndex; idParameter.Value = pendingUpdates.Map(p => p.Base.Key); cmd.Parameters.Add(idParameter); if (hasUpdatedColumn) { var updatedParameter = cmd.CreateParameter(); updatedParameter.ParameterName = "updated" + batchIndex; updatedParameter.Value = pendingUpdates.Map(p => DateTime.Now); cmd.Parameters.Add(updatedParameter); additionalColumns.Add("updated"); } for (var i = 0; i < updatedPropertyNames.Length; i++) { var updatedPropertyName = updatedPropertyNames[i]; var updatedProperty = typeof(V).GetProperty(updatedPropertyName); var array = Array.CreateInstance(updatedProperty.PropertyType, pendingUpdates.Length); for (var j = 0; j < pendingUpdates.Length; j++) { array.SetValue(updatedProperty.GetValue(pendingUpdates[j].Updated.Value), j); } var parameter = cmd.CreateParameter(); parameter.ParameterName = updatedColumnNames[i] + batchIndex; parameter.Value = array; cmd.Parameters.Add(parameter); } var query = $"UPDATE {tableName} " + "SET " + updatedColumnNames.Concat(additionalColumns).Select(n => $"{n} = temp.{n}").Join(", ") + " " + "FROM ( select " + updatedColumnNames.Concat("id").Concat(additionalColumns).Select(n => $"unnest(@{n}{batchIndex}) as {n}").Join(", ") + " ) as temp " + $"where {tableName}.id = temp.id"; commandTextBuilder.Append(query); commandTextBuilder.Append("; "); batchIndex++; } // inserts; if (pendingInserts.Any()) { var propertyNames = properties.Map(p => p.Name); var columnNames = properties.Map(p => p.Name.ToLower()); var idParameter = cmd.CreateParameter(); idParameter.ParameterName = "id_ins"; idParameter.Value = pendingInserts.Map(p => p.Base.Key); cmd.Parameters.Add(idParameter); for (var i = 0; i < properties.Length; i++) { var property = properties[i]; var array = Array.CreateInstance(property.PropertyType, pendingInserts.Count); for (var j = 0; j < pendingInserts.Count; j++) { object propertyValue; if (columnNames[i] == "updated" || columnNames[i] == "created") { propertyValue = DateTime.Now; } else { propertyValue = property.GetValue(pendingInserts[j].Updated.Value); } array.SetValue(propertyValue, j); } var parameter = cmd.CreateParameter(); parameter.ParameterName = columnNames[i] + "_ins"; parameter.Value = array; cmd.Parameters.Add(parameter); } var query = $"INSERT INTO {tableName} ({columnNames.Concat("id").Join(", ")}) " + "SELECT " + columnNames.Concat("id").Select(n => $"unnest(@{n}_ins)").Join(", ") + " " + "ON CONFLICT (id) DO UPDATE " + "SET " + columnNames.Select(n => $"{n} = excluded.{n}").Join(", "); commandTextBuilder.Append(query); commandTextBuilder.Append("; "); } cmd.CommandText = commandTextBuilder.ToString(); await cmd.ExecuteNonQueryAsync().ConfigureAwait(false); })); }
public UserCode(SCG.IReadOnlyDictionary <int, ISubsystem> subsystems, SCG.IReadOnlyList <ICommand> commands) { this.subsystems = subsystems; this.commands = commands; }
public GameState(ManagableMap map, SCG.IReadOnlyList <MobileInstance> mobiles, EventManager eventManager) { Map = map; Mobiles = mobiles; EventManager = eventManager; }
public UserCode(SCG.IReadOnlyDictionary<int, ISubsystem> subsystems, SCG.IReadOnlyList<ICommand> commands) { this.subsystems = subsystems; this.commands = commands; }