public void AddRunner(Runner runner) { lock (dbLock) { dbRoot.runnerFirstNameIndex.Put(runner.FirstName, runner); dbRoot.runnerLastNameIndex.Put(runner.LastName, runner); db.Commit(); } }
/// <summary> /// Loads a CSV file containing race entrant information. /// </summary> public dynamic LoadCsvFile(string filename) { // ToDo: Long term, make this more configurable. At the moment we're only interested // in Runner's World files. dynamic result = new ExpandoObject(); result.Imported = 0; result.AlreadyExisting = 0; result.Ignored = 0; using (var reader = new StreamReader(File.OpenRead(filename))) { string line; // Count number of lines - can specify which line throws error var lineCount = 0; // Do process while line is not empty while ((line = reader.ReadLine()) != null) { lineCount++; // If line throws exception then skip try { // Split line into array of info (\\s* removes space around object) var runnerInfo = SplitCSV( line ).ToArray(); var runner = new Runner { FirstName = runnerInfo[0].ToUpper(), LastName = runnerInfo[1].ToUpper(), Gender = ( runnerInfo[2] == "F" ) ? GenderEnum.Female : GenderEnum.Male, DateOfBirth = DateParser.ParseRwDate( runnerInfo[4] ), Club = RemoveUnwantedAttributes( runnerInfo[5] ), Team = RemoveUnwantedAttributes( runnerInfo[6] ), Email = ( runnerInfo.Count() > 15 ) ? RemoveUnwantedAttributes( runnerInfo[15] ) : null, Urn = ( runnerInfo.Count() > 33 ) ? RemoveUnwantedAttributes( runnerInfo[33] ) : null, Number = db.GetNextNumber(), }; var addressFields = runnerInfo .Skip( 8 ).Take( 6 ) .Where( s => !string.IsNullOrEmpty( s ) ).ToList(); if ( addressFields.Any() ) { runner.Address = addressFields.Aggregate( ( current, next ) => current + ", " + next ); } // If a club is given, then assume the runner is affiliated runner.Affiliated = !string.IsNullOrEmpty( runner.Club ); // ToDo: Check for invalid team names - 'NONE' or 'N/A'. // Check that they don't already exist in the DB (use firstname, lastname and DoB) if (!db.TestDuplicate(runner)) { db.AddRunner(runner); result.Imported++; } else { result.AlreadyExisting++; } } catch (Exception ex) { Trace.WriteLineIf( traceSwitch.TraceWarning, string.Format( "Error with line {0}: {1}. Line is '{2} ", lineCount, ex.Message, line ) ); result.Ignored++; } } } return result; }
public ApiModule( ControllerFactory controllerFactory ) : base("/api") { Get["/raceinfo"] = parameters => { try { return Response.AsJson( GetRaceInfo( controllerFactory ) ); } catch ( Exception ex ) { return Response.AsJson(ex.Message, HttpStatusCode.InternalServerError); } }; Get["/runner"] = parameters => { var number = Request.Query["number"]; var runner = GetRunner( controllerFactory, number ); var statusCode = HttpStatusCode.OK; if ( runner == null ) { statusCode = HttpStatusCode.InternalServerError; } return Response.AsJson( new {runner = runner}, statusCode); }; Get["/runners"] = parameters => Response.AsJson( GetRunners( controllerFactory ) ); Get["/results"] = parameters => { try { var resultsToList = 0; int.TryParse( Request.Query["resultsToList"], out resultsToList ); if ( resultsToList == 0 ) { resultsToList = int.MaxValue; } return Response.AsJson( GetResults( controllerFactory, resultsToList ) ); } catch ( Exception ex ) { return HandleException(ex); } }; Get["/result"] = parameters => { var position = Request.Query["position"]; var raceResult = GetResult(controllerFactory, position); var statusCode = HttpStatusCode.OK; if (raceResult == null) { statusCode = HttpStatusCode.InternalServerError; } return Response.AsJson(new { raceResult = raceResult }, statusCode); }; Post["/updateresult"] = ( x ) => { var appController = controllerFactory.AppController; var message = ""; var statusCode = HttpStatusCode.OK; try { var newResult = this.Bind<NewResult>(); var result = new Result() { Position = newResult.Position, RaceNumber = newResult.RaceNumber, Time = new TimeSpan( newResult.Hours, newResult.Minutes, newResult.Seconds ), }; appController.UpdateResult( result ); return Response.AsJson(message, statusCode); } catch (Exception ex) { return HandleException(ex); } }; Post["/addresult"] = ( x ) => { var appController = controllerFactory.AppController; var message = ""; var statusCode = HttpStatusCode.OK; try { var newResult = this.Bind<NewResult>(); var result = new Result() { Position = newResult.Position, RaceNumber = newResult.RaceNumber, Time = new TimeSpan( newResult.Hours, newResult.Minutes, newResult.Seconds ), }; appController.InsertResult( result ); return Response.AsJson( message, statusCode ); } catch ( Exception ex ) { return HandleException( ex ); } }; Post["/deleteresult"] = ( x ) => { var appController = controllerFactory.AppController; var message = ""; var statusCode = HttpStatusCode.OK; try { var deleteResult = this.Bind<DeleteResult>(); // Neither selected if ( !deleteResult.DeleteNumber && !deleteResult.DeleteTime ) { throw new Exception("Nothing selected to delete..."); } // Both selected if ( deleteResult.DeleteNumber && deleteResult.DeleteTime ) { appController.DeleteResultAtPosition( deleteResult.Position ); } // Delete just the number - shifting numbers down else if ( deleteResult.DeleteNumber && !deleteResult.DeleteTime ) { appController.DeleteRunnerNumberShiftDown(deleteResult.Position); } // Delete the result time, shifting times down else if (!deleteResult.DeleteNumber && deleteResult.DeleteTime) { appController.DeleteTimeShiftDown(deleteResult.Position); } return Response.AsJson(message, statusCode); } catch (Exception ex) { return HandleException( ex ); } }; Get["/finishers"] = parameters => Response.AsJson( GetFinishers( controllerFactory ) ); Get["/winners"] = parameters => Response.AsJson( GetWinners( controllerFactory ) ); Get["/teams"] = parameters => Response.AsJson( GetTeams( controllerFactory ) ); Post["/addrunner"] = ( x ) => { var appController = controllerFactory.AppController; var message = ""; var statusCode = HttpStatusCode.OK; try { var newRunner = this.Bind<NewRunner>(); // Check fields CheckField( newRunner.FirstName, "First Name" ); CheckField( newRunner.LastName, "Last Name" ); CheckField( newRunner.Gender, "Gender" ); CheckField( newRunner.DoB, "DoB" ); int number; if ( !int.TryParse( newRunner.Number, out number ) ) { throw new Exception( "Race number format is incorrect." ); } var runners = appController.GetRunners(); if ( runners.Any( r => r.Number == number ) ) { throw new Exception("A runner with this number already exists."); } var runner = new Runner { FirstName = newRunner.FirstName, LastName = newRunner.LastName, Gender = ( newRunner.Gender == "F" ) ? GenderEnum.Female : GenderEnum.Male, DateOfBirth = DateTime.Parse( newRunner.DoB ), Email = newRunner.Email, Number = number, Club = newRunner.Club, Team = newRunner.Team, Urn = newRunner.Urn, }; runner.ToUpperCase(); var db = appController.DbService; if ( !db.TestDuplicate( runner ) ) { db.AddRunner( runner ); message = string.Format( "'{0}' added to database OK.", runner.ToString() ); } else { throw new Exception(string.Format("'{0}' with this DoB already exists in database.", runner.ToString())); } return Response.AsJson( message, statusCode ); } catch ( Exception ex ) { return HandleException(ex); } }; Post["/updaterunner"] = ( x ) => { var appController = controllerFactory.AppController; var message = ""; var statusCode = HttpStatusCode.OK; try { var newRunner = this.Bind<NewRunner>(); // Check fields CheckField( newRunner.FirstName, "First Name" ); CheckField( newRunner.LastName, "Last Name" ); CheckField( newRunner.Gender, "Gender" ); CheckField( newRunner.DoB, "DoB" ); int number; if ( !int.TryParse( newRunner.Number, out number ) ) { throw new Exception( "Race number format is incorrect." ); } int newNumber = 0; var haveNewNumber = false; if ( !string.IsNullOrEmpty( newRunner.NewNumber ) ) { if ( !int.TryParse( newRunner.NewNumber, out newNumber ) ) { throw new Exception( "The format of the new race number is not correct." ); } haveNewNumber = true; } // Update var runner = new Runner { Number = number, FirstName = newRunner.FirstName, LastName = newRunner.LastName, Gender = ( newRunner.Gender == "Female" ) ? GenderEnum.Female : GenderEnum.Male, DateOfBirth = DateTime.Parse( newRunner.DoB ), Email = newRunner.Email, Club = newRunner.Club, Team = newRunner.Team, Urn = newRunner.Urn, HaveNewNumber = haveNewNumber, NewNumber = newNumber, }; runner.ToUpperCase(); appController.DbService.UpdateRunner( runner ); return Response.AsJson( message, statusCode ); } catch ( Exception ex ) { return HandleException( ex ); } }; Post["/deleterunner"] = ( x ) => { var appController = controllerFactory.AppController; var message = ""; var statusCode = HttpStatusCode.OK; try { var number = this.Bind<RunnerNumber>(); appController.DbService.DeleteRunner(number.Number); Trace.WriteLineIf( AppController.traceSwitch.TraceInfo, string.Format( "Runner with number {0} deleted.", number.Number ) ); return Response.AsJson( message, statusCode ); } catch ( Exception ex ) { return HandleException(ex); } }; Post["/addfinishposition"] = ( x ) => { var appController = controllerFactory.AppController; var message = ""; var statusCode = HttpStatusCode.OK; try { var posResult = this.Bind<PositionResult>(); if ( !appController.IsClockRunning ) { throw new Exception( "Race is not in progress (clock not running)." ); } if ( posResult.Position <= 0 ) { message = "Race number must be > 0"; statusCode = HttpStatusCode.BadRequest; } else { appController.AddResultRunnerNumber( posResult.Position ); Trace.WriteLineIf( AppController.traceSwitch.TraceInfo, "Runner number added: " + posResult.Position ); } return Response.AsJson( message, statusCode ); } catch ( Exception ex ) { return HandleException( ex ); } }; }