|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Spell Support Broken Spells? Want them Fixed? Request it here. |
|
|
|
01-25-2014, 11:44 PM
|
Sarnak
|
|
Join Date: Nov 2009
Posts: 45
|
|
SpellGap : Native Utility to find unused spell ids
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!
|
|
|
|
01-26-2014, 02:20 AM
|
Developer
|
|
Join Date: Mar 2009
Location: -
Posts: 228
|
|
Good work.
Alternatively, SQL query to return gaps in spell file.
Code:
SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
FROM spells_new AS a, spells_new AS b
WHERE a.id < b.id
GROUP BY a.id
HAVING start < MIN(b.id);
Kayen
GM Storm Haven
|
01-26-2014, 02:31 AM
|
Hill Giant
|
|
Join Date: Oct 2002
Location: Rockville, MD
Posts: 124
|
|
Thanks for both! Will save us a ton of time lol.
__________________
Bront -Server Admin/Owner and Lead Quest Dev for Kildrukaun's Prophecy
http://kpemu.com/
|
01-26-2014, 09:36 AM
|
|
Discordant
|
|
Join Date: Sep 2009
Posts: 269
|
|
You can also look for name like '%test%' or name like '%placeholder%'
|
|
|
|
01-30-2014, 01:36 PM
|
Sarnak
|
|
Join Date: Nov 2009
Posts: 45
|
|
I've updated the source for those interested to now offer a command line parameter to filter out 'test' and 'placeholder' spells.
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(int argc, char*argv[])
{
// filter out 'test' and 'placeholder' spells
bool useFilter = (argc >= 2 && ((strcmp(argv[1], "-f") == 0) || (strcmp(argv[1], "-F") == 0))) ? true : false;
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())
{
string spell_name;
std::getline(infile, spell_name, '^');
if (useFilter)
{
std::transform(spell_name.begin(), spell_name.end(), spell_name.begin(), ::toupper);
// conditional insert
if (spell_name.find("TEST") == string::npos && spell_name.find("PLACEHOLDER") == string::npos)
{
spell_ids.push_back(atoi(spell_id_str.c_str()));
}
}
else
{
// unconditional insert
spell_ids.push_back(atoi(spell_id_str.c_str()));
}
// 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;
}
Enjoy.
|
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -4. The time now is 10:31 AM.
|
|
|
|
|
|
|
|
|
|
|
|
|