// add the new user to the encrypted users file which has the detailed stats for all users // synchronize to make sure that only one thread can be inside this block at a time. public static synchronized String addUserAndIssueCode(UserStats stats) throws IOException, GeneralSecurityException, ClassNotFoundException, NoMoreCodesException { // ok, now we have a list of stats objects, representing all users. // add this user to the list. // the code assigned to this user will simply be codes.get(users.size()) // but do an error check first to be sure we're not out of codes List<UserStats> users = readUsersFile(); if (users.size() >= MemoryStudy.codes.size()) { log.warn("NOC WARNING: codes file exhausted!!!!"); throw new NoMoreCodesException(); } // ok, we have enough codes, just give out one String passkey = MemoryStudy.codes.get(users.size()); int USERID_BASE = 100; // userid numbering starts from USERID_BASE, new id is base + # existing codes stats.userid = Integer.toString(USERID_BASE + users.size()); stats.code = passkey; users.add(stats); // encrypt and write the users file back ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(users); oos.close(); CryptoUtils.writeEncryptedBytes(baos.toByteArray(), USERS_FILE); return passkey; }
private static List<UserStats> readUsersFile() throws IOException, GeneralSecurityException, ClassNotFoundException { // read the bytes, decrypt them and read a list object, with stats for each user if (!new File(USERS_FILE).exists()) return new ArrayList<MemoryStudy.UserStats>(); byte[] b = CryptoUtils.readEncryptedBytes(USERS_FILE); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(b)); ois.close(); return (List<UserStats>) ois.readObject(); }
/** writes out csv stats as an encrypted file in RESULTS_DIR/<userid>/filename */ public void logStats(String filename, boolean nullClues) { Indexer.IndexStats stats = archive.getIndexStats(); StringBuilder statsLog = new StringBuilder(); Pair<String, String> indexStats = Util.fieldsToCSV(stats, true); Pair<String, String> addressBookStats = Util.fieldsToCSV(archive.addressBook.getStats(), true); Pair<String, String> studyStats = Util.fieldsToCSV(stats, true); Pair<String, String> archiveStats = Util.fieldsToCSV(archive.stats, true); statsLog.append( "STUDYSTATS-1: " + studyStats.getFirst() + indexStats.getFirst() + addressBookStats.getFirst() + archiveStats.getFirst() + "\n"); statsLog.append( "STUDYSTATS-2: " + studyStats.getSecond() + indexStats.getSecond() + addressBookStats.getSecond() + archiveStats.getSecond() + "\n"); int idx = 1; for (MemoryQuestion mq : this.getQuestions()) { if (nullClues) mq.clue.clue = null; Pair<String, String> p = Util.fieldsToCSV(mq.clue.clueStats, true); Pair<String, String> p1 = Util.fieldsToCSV(mq.stats, true); if (idx == 1) statsLog.append( "QUESTIONSTATS-header: " + p.getFirst() + ',' + p1.getFirst() + "correct answer, user answer, user answer before hint, clue" + "\n"); // statsLog.append("QUESTIONSTATS-2: " + p.getSecond() + ',' + p1.getSecond() + // mq.correctAnswer + "," + mq.userAnswer + "," + mq.userAnswerBeforeHint + "," + // mq.clue.clue.replaceAll(",", " ") + "\n"); statsLog.append( "QUESTIONSTATS-2: " + p.getSecond() + ',' + p1.getSecond() + mq.correctAnswer + "," + mq.userAnswer + "," + mq.userAnswerBeforeHint + "\n"); idx = idx + 1; } String RESULTS_DIR = System.getProperty("user.home") + File.separator + "results" + File.separator + this.stats.userid; new File(RESULTS_DIR).mkdirs(); String file = RESULTS_DIR + File.separator + filename; try { CryptoUtils.writeEncryptedBytes(statsLog.toString().getBytes("UTF-8"), file); } catch (UnsupportedEncodingException e) { Util.print_exception(e, log); } catch (Exception e) { Util.print_exception("NOC ERROR: encryption failed!", e, log); } log.info(statsLog); }