Greetings.
This is something I whipped up real quick in C++ to find unused spell ids in spells_us.txt.
It produces a list of the ids, as well as an sql file to verify the results with. The only requirements are "spells_us.txt" and a recent-ish compiler (C++ 11 compliance required). Just drop the executable once built into the same folder as your spell file and execute.
Code:
/*
main.cpp
implements entry point and all program logic.
SpellGap
Finds and records unused spell ids in spells_us.txt
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#if defined(_MSC_VER)
#pragma warning (disable : 996)
#endif
/*This header is a non standard header that can be found at:
http://codereview.stackexchange.com/questions/13176/infix-iterator-code
*/
#include "infix_iterator.h"
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
#include <fstream>
using std::ifstream;
using std::ofstream;
#include <cstdlib>
#include <vector>
using std::vector;
#include <algorithm>
using std::for_each;
using std::copy;
#include <iterator>
/*
assumes: the last valid id is the upper bound for ids
requires: spells_us.txt
*/
int main()
{
string spellFile = "spells_us.txt";
string spell_id_str;
cout << "Recording valid spell ids...\n";
ifstream infile(spellFile.c_str());
if (infile.is_open())
{
vector<int> spell_ids;
while (std::getline(infile, spell_id_str, '^').good())
{
int spell_id = atoi(spell_id_str.c_str());
spell_ids.push_back(spell_id);
// not interested in the other fields, discard them
string junk;
std::getline(infile, junk);
}
infile.close();
cout << "Done!\n";
cout << "Finding unused ids...\n";
int previd = 0;
vector<int> unused_ids;
// iterate over the valid id range, while pushing missing ids into 'unused_ids'
for_each(spell_ids.begin(), spell_ids.end(),
[&previd, &unused_ids](int& id)
{
// detect the gap and record it
if (id > previd + 1)
{
for (int i = previd + 1; i < id; i++)
{
unused_ids.push_back(i);
}
}
previd = id;
});
spell_ids.clear();
spell_ids.shrink_to_fit();
// write unused ids as a list to 'unused_spell_ids.txt'
cout << "Found " << unused_ids.size() << " unused ids. Writing them to file...\n";
ofstream outfile("unused_spell_ids.txt");
copy(unused_ids.begin(), unused_ids.end(), std::ostream_iterator<int>(outfile, "\n"));
cout << "Done!\n";
outfile.close();
cout << "Writing 'unused_ids_verify.sql' for verification...\n";
/* write a quick query to file to verify that we are not snagging valid ids*/
ofstream sqlfile("unused_ids_verify.sql");
sqlfile << "SELECT name FROM spells_new WHERE id=";
copy(unused_ids.begin(), unused_ids.end(), infix_ostream_iterator<int>(sqlfile, " OR id="));
sqlfile << ";\n";
sqlfile.close();
cout << "Done!\n";
cout << "Use mysql: 'source unused_ids_verify.sql;' to verify this process.\n";
cout << "Goodbye.\n";
}
else
{
cout << "spells_us.txt not found! Aborting...\n";
}
return 0;
}
It employs a non-standard header located here:
http://codereview.stackexchange.com/...-iterator-code
Enjoy!