예제 #1
0
        /// <summary>
        /// Evaluates quiz and survey; stores results; returns ID so client can navigate to results page.
        /// </summary>
        /// <param name="quiz">The user's quiz choices, JSON serialized in quiz.js.</param>
        /// <param name="survey">The user's survey input (whatever was provided), JSON serialized in quiz.js.</param>
        /// <returns></returns>
        public IActionResult EvalQuiz([FromForm] string quiz, [FromForm] string survey,
                                      [FromForm] string quizCount, [FromForm] string surveyCount)
        {
            // Parse data from query
            var oQuiz   = JsonConvert.DeserializeObject <IList <string[]> >(quiz);
            var oSurvey = JsonConvert.DeserializeObject <SurveyData>(survey);
            // Have sampler evaluate result
            int score;

            char[] resCoded;
            sampler.Eval(oQuiz, out score, out resCoded);
            // Get country from remote IP. Trickier b/c of NGINX reverse proxy.
            string country;
            string xfwd = HttpContext.Request.Headers["X-Real-IP"];

            if (xfwd != null)
            {
                country = countryResolver.GetContryCode(IPAddress.Parse(xfwd));
            }
            else
            {
                country = countryResolver.GetContryCode(HttpContext.Connection.RemoteIpAddress);
            }
            // Store result
            int          nQuizCount   = int.Parse(quizCount);
            int          nSurveyCount = int.Parse(surveyCount);
            StoredResult sr           = new StoredResult(country, DateTime.Now, nQuizCount, nSurveyCount, score, new string(resCoded), oSurvey);
            string       uid          = resultRepo.StoreResult(sr);

            // Response is result code, pure and simple.
            return(new ObjectResult(uid));
        }
예제 #2
0
        /// <summary>
        /// Diagnostic function: stores same item N times in a single transaction. Used to grow DB in stress test.
        /// </summary>
        /// <returns>UID of last stored item.</returns>
        public string StoreBatch(StoredResult sr, int count)
        {
            long uid = 0;

            lock (conn)
            {
                SqliteTransaction trans = null;
                try
                {
                    trans = conn.BeginTransaction();
                    for (int i = 0; i != count; ++i)
                    {
                        uid = getNextUid(sr.Date, trans);
                        storeResult(uid, trans, sr);
                    }
                    trans.Commit(); trans.Dispose(); trans = null;
                }
                catch (Exception ex)
                {
                    logger.LogError(new EventId(), ex, "Failed to store quiz results.");
                    if (trans != null)
                    {
                        trans.Rollback();
                    }
                    throw;
                }
                finally { if (trans != null)
                          {
                              trans.Dispose();
                          }
                }
            }
            return(uidToString(uid));
        }
예제 #3
0
        /// <summary>
        /// Performs actual dump.
        /// </summary>
        private void doDumpToFile(string tsvFileName)
        {
            SqliteConnection dumpConn  = null;
            SqliteCommand    cmdSelAll = null;

            try
            {
                // For the dump, we use a separate connection
                // This allows main connection to be safely accessed from other threads while dump is in progress
                bool dbExists;
                getOpenConn(out dumpConn, out dbExists);

                using (SqliteCommand cmdPragma = dumpConn.CreateCommand())
                {
                    // This pragma is a MUST to avoid locking the DB for the duration of the dump
                    // Without it, concurrent store requests will time out.
                    cmdPragma.CommandText = "PRAGMA read_uncommitted = 1;";
                    cmdPragma.ExecuteNonQuery();
                }

                // Dumping is rare. No need to prepare and reuse this command.
                cmdSelAll             = dumpConn.CreateCommand();
                cmdSelAll.CommandText = sqlSelAll;
                cmdSelAll.Prepare();

                // Write from reader, straight to output file.
                using (FileStream fs = new FileStream(tsvFileName, FileMode.Create, FileAccess.ReadWrite))
                    using (StreamWriter sw = new StreamWriter(fs))
                        using (var rdr = cmdSelAll.ExecuteReader())
                        {
                            sw.WriteLine(StoredResult.GetTSVHeader());
                            while (rdr.Read())
                            {
                                // uid, country, quiz_ix, survey_ix, score, res_enc, survey_enc
                                int          dateNum = (int)(rdr.GetInt64(0) / 1000000);
                                int          xDay    = dateNum % 100; dateNum /= 100;
                                int          xMonth  = dateNum % 100; dateNum /= 100;
                                int          xYear   = dateNum;
                                DateTime     date    = new DateTime(xYear, xMonth, xDay);
                                StoredResult sr      = new StoredResult(rdr.GetString(1), date, rdr.GetInt32(2), rdr.GetInt32(3),
                                                                        rdr.GetInt32(4), rdr.GetString(5), rdr.GetString(6));
                                sw.WriteLine(sr.GetTSV());
                            }
                        }
                dumpConn.Close();
            }
            finally
            {
                if (cmdSelAll != null)
                {
                    cmdSelAll.Dispose();
                }
                if (dumpConn != null)
                {
                    dumpConn.Dispose();
                }
            }
        }
예제 #4
0
 /// <summary>
 /// Executes "store" SQL command within transaction.
 /// </summary>
 private void storeResult(long uid, SqliteTransaction trans, StoredResult sr)
 {
     cmdInsertResult.Transaction = trans;
     cmdInsertResult.Parameters["@uid"].Value        = uid;
     cmdInsertResult.Parameters["@country"].Value    = sr.CountryCode;
     cmdInsertResult.Parameters["@quiz_ix"].Value    = sr.PrevQuizCount;
     cmdInsertResult.Parameters["@survey_ix"].Value  = sr.PrevSurveyCount;
     cmdInsertResult.Parameters["@score"].Value      = sr.Score;
     cmdInsertResult.Parameters["@res_enc"].Value    = sr.EncodedResult;
     cmdInsertResult.Parameters["@survey_enc"].Value = sr.GetEncodedSurvey();
     cmdInsertResult.ExecuteNonQuery();
 }
예제 #5
0
 /// <summary>
 /// Stores a new quiz+survey result in the DB.
 /// </summary>
 /// <param name="sr">The data to store.</param>
 /// <returns>The stored item's ID, encoded as a 10-character alphanumeric string.</returns>
 public string StoreResult(StoredResult sr)
 {
     return(StoreBatch(sr, 1));
 }