<commit_before>#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>

#include "state.h"
#include "io.h"
#include "os.h"
#include "wizard.h"
#include "rogue.h"
#include "level.h"
#include "death.h"
#include "pack.h"

#include "score.h"

#define LOCKFILE ".rogue14_lockfile"

struct score {
  unsigned uid;
  int      score;
  int      flags;
  int      monster;
  char     name[MAXSTR];
  int      level;
  unsigned time;
};

static FILE* scoreboard = NULL; /* File descriptor for score file */
static FILE* lock = NULL;

static bool
lock_sc(void)
{
  lock = fopen(LOCKFILE, "w+");
  if (lock != NULL)
    return true;

  for (int cnt = 0; cnt < 5; cnt++)
  {
    sleep(1);
    lock = fopen(LOCKFILE, "w+");
    if (lock != NULL)
      return true;
  }

  struct stat sbuf;
  if (stat(LOCKFILE, &sbuf) < 0)
  {
    lock = fopen(LOCKFILE, "w+");
    return true;
  }

  if (time(NULL) - sbuf.st_mtime > 10)
    return unlink(LOCKFILE) < 0
      ? false
      : lock_sc();

  printf("The score file is very busy.  Do you want to wait longer\n"
         "for it to become free so your score can get posted?\n"
         "If so, type \"y\"\n");

  return io_readchar(true) == 'y'
    ? lock_sc()
    : false;
}


static void
unlock_sc(void)
{
  if (lock != NULL)
    fclose(lock);
  lock = NULL;
  unlink(LOCKFILE);
}

static void
score_read(struct score* top_ten)
{
  if (scoreboard == NULL || !lock_sc())
    return;

  rewind(scoreboard);

  for (unsigned i = 0; i < SCORE_MAX; i++)
  {
    char buf[100];
    io_encread(top_ten[i].name, MAXSTR, scoreboard);
    io_encread(buf, sizeof(buf), scoreboard);
    sscanf(buf, " %u %d %d %d %d %x \n",
        &top_ten[i].uid, &top_ten[i].score,
        &top_ten[i].flags, &top_ten[i].monster,
        &top_ten[i].level, &top_ten[i].time);
  }

  rewind(scoreboard);

  unlock_sc();
}

static void
score_write(struct score* top_ten)
{
  if (scoreboard == NULL || !lock_sc())
    return;

  rewind(scoreboard);

  for(unsigned i = 0; i < SCORE_MAX; i++)
  {
    char buf[100];
    io_encwrite(top_ten[i].name, MAXSTR, scoreboard);
    memset(buf, '\0', sizeof(buf));
    sprintf(buf, " %u %d %d %d %d %x \n",
        top_ten[i].uid, top_ten[i].score,
        top_ten[i].flags, top_ten[i].monster,
        top_ten[i].level, top_ten[i].time);
    io_encwrite(buf, sizeof(buf), scoreboard);
  }

  rewind(scoreboard);

  unlock_sc();
}



static void
score_insert(struct score* top_ten, int amount, int flags, char monst)
{
  unsigned uid = getuid();
  for (unsigned i = 0; i < SCORE_MAX; ++i)
    if (amount > top_ten[i].score)
    {
      /* Move all scores a step down */
      size_t scores_to_move = SCORE_MAX - i - 1;
      memmove(&top_ten[i +1], &top_ten[i], sizeof(*top_ten) * scores_to_move);

      /* Add new scores */
      top_ten[i].score = amount;
      strcpy(top_ten[i].name, whoami);
      top_ten[i].flags = flags;
      top_ten[i].level = flags == 2
        ? level_max
        : level;
      top_ten[i].monster = monst;
      top_ten[i].uid = uid;

      /* Write score to disk */
      score_write(top_ten);
    }
}

static void
score_print(struct score* top_ten)
{
  char buf[2*MAXSTR];

  printf("Top %d %s:\n   Score Name\n", SCORE_MAX, "Scores");
  for (unsigned i = 0; i < SCORE_MAX; ++i)
  {
    if (!top_ten[i].score)
      break;

    printf("%2d %5d %s: "
        ,i + 1                   /* Position */
        ,top_ten[i].score     /* Score */
        ,top_ten[i].name      /* Name */
        );

    if (top_ten[i].flags == 0)
      printf("%s", death_reason(buf, top_ten[i].monster));
    else if (top_ten[i].flags == 1)
      printf("Quit");
    else if (top_ten[i].flags == 2)
      printf("A total winner");
    else if (top_ten[i].flags == 3)
      printf("%s while holding the amulet",
          death_reason(buf, top_ten[i].monster));<commit_msg>Remove bug overwriting whole highscore<commit_after>#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>

#include "state.h"
#include "io.h"
#include "os.h"
#include "wizard.h"
#include "rogue.h"
#include "level.h"
#include "death.h"
#include "pack.h"

#include "score.h"

#define LOCKFILE ".rogue14_lockfile"

struct score {
  unsigned uid;
  int      score;
  int      flags;
  int      monster;
  char     name[MAXSTR];
  int      level;
  unsigned time;
};

static FILE* scoreboard = NULL; /* File descriptor for score file */
static FILE* lock = NULL;

static bool
lock_sc(void)
{
  lock = fopen(LOCKFILE, "w+");
  if (lock != NULL)
    return true;

  for (int cnt = 0; cnt < 5; cnt++)
  {
    sleep(1);
    lock = fopen(LOCKFILE, "w+");
    if (lock != NULL)
      return true;
  }

  struct stat sbuf;
  if (stat(LOCKFILE, &sbuf) < 0)
  {
    lock = fopen(LOCKFILE, "w+");
    return true;
  }

  if (time(NULL) - sbuf.st_mtime > 10)
    return unlink(LOCKFILE) < 0
      ? false
      : lock_sc();

  printf("The score file is very busy.  Do you want to wait longer\n"
         "for it to become free so your score can get posted?\n"
         "If so, type \"y\"\n");

  return io_readchar(true) == 'y'
    ? lock_sc()
    : false;
}


static void
unlock_sc(void)
{
  if (lock != NULL)
    fclose(lock);
  lock = NULL;
  unlink(LOCKFILE);
}

static void
score_read(struct score* top_ten)
{
  if (scoreboard == NULL || !lock_sc())
    return;

  rewind(scoreboard);

  for (unsigned i = 0; i < SCORE_MAX; i++)
  {
    char buf[100];
    io_encread(top_ten[i].name, MAXSTR, scoreboard);
    io_encread(buf, sizeof(buf), scoreboard);
    sscanf(buf, " %u %d %d %d %d %x \n",
        &top_ten[i].uid, &top_ten[i].score,
        &top_ten[i].flags, &top_ten[i].monster,
        &top_ten[i].level, &top_ten[i].time);
  }

  rewind(scoreboard);

  unlock_sc();
}

static void
score_write(struct score* top_ten)
{
  if (scoreboard == NULL || !lock_sc())
    return;

  rewind(scoreboard);

  for(unsigned i = 0; i < SCORE_MAX; i++)
  {
    char buf[100];
    io_encwrite(top_ten[i].name, MAXSTR, scoreboard);
    memset(buf, '\0', sizeof(buf));
    sprintf(buf, " %u %d %d %d %d %x \n",
        top_ten[i].uid, top_ten[i].score,
        top_ten[i].flags, top_ten[i].monster,
        top_ten[i].level, top_ten[i].time);
    io_encwrite(buf, sizeof(buf), scoreboard);
  }

  rewind(scoreboard);

  unlock_sc();
}



static void
score_insert(struct score* top_ten, int amount, int flags, char monst)
{
  unsigned uid = getuid();
  for (unsigned i = 0; i < SCORE_MAX; ++i)
    if (amount > top_ten[i].score)
    {
      /* Move all scores a step down */
      size_t scores_to_move = SCORE_MAX - i - 1;
      memmove(&top_ten[i +1], &top_ten[i], sizeof(*top_ten) * scores_to_move);

      /* Add new scores */
      top_ten[i].score = amount;
      strcpy(top_ten[i].name, whoami);
      top_ten[i].flags = flags;
      top_ten[i].level = flags == 2
        ? level_max
        : level;
      top_ten[i].monster = monst;
      top_ten[i].uid = uid;

      /* Write score to disk */
      score_write(top_ten);
      break;
    }
}

static void
score_print(struct score* top_ten)
{
  char buf[2*MAXSTR];

  printf("Top %d %s:\n   Score Name\n", SCORE_MAX, "Scores");
  for (unsigned i = 0; i < SCORE_MAX; ++i)
  {
    if (!top_ten[i].score)
      break;

    printf("%2d %5d %s: "
        ,i + 1                   /* Position */
        ,top_ten[i].score     /* Score */
        ,top_ten[i].name      /* Name */
        );

    if (top_ten[i].flags == 0)
      printf("%s", death_reason(buf, top_ten[i].monster));
    else if (top_ten[i].flags == 1)
      printf("Quit");
    else if (top_ten[i].flags == 2)
      printf("A total winner");
    else if (top_ten[i].flags == 3)
      printf("%s while holding the amulet",
          death_reason(buf, top_ten[i].monster));
{'fraction_non_alphanumeric': 0.1635549872122762, 'fraction_numerical': 0.007928388746803069, 'mean_word_length': 2.6478544776119404, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5950152', 'n_tokens_mistral': 3083, 'n_tokens_neox': 3002, 'n_words': 732}