Commits

David Stone  committed 0ad3bb8

Removed random string generation into its own header file.

  • Participants
  • Parent commits 74fa8a4

Comments (0)

Files changed (5)

File source/clients/battle.cpp

 #include <string>
 #include <vector>
 
+#include <boost/filesystem.hpp>
+
 #include "battle_result.hpp"
+#include "random_string.hpp"
 
 #include "network/client.hpp"
 #include "network/invalid_simulator_data.hpp"
 	updated_hp.faint(team.is_me(), team.pokemon());
 }
 
-void Battle::handle_end (network::Client & client, Result const result) const {
-	std::string const verb = to_string (result);
-	client.print_with_time_stamp(std::cout, verb + " a battle vs. " + opponent());
+namespace {
+
+std::string get_extension() {
+	// TODO: add support for other formats
+	return ".sbt";
+}
+
+template<typename RandomEngine>
+std::string generate_team_file_name(RandomEngine & random_engine) {
+	// Randomly generates a file name in 8.3 format. It then checks to see if
+	// that file name already exists. If it does, it randomly generates a new
+	// file name, and continues until it generates a name that does not exist.
+	// This limits the potential for a race condition down to a 1 / 36^8 chance
+	// (about 1 / 2 ^ 41), assuming that another process / thread is also
+	// trying to save an 8 character file name with an identical extension at
+	// the same time. The result of this is that a team file would not be saved
+	// when it should have been, which is not a major issue.
+	constexpr unsigned file_name_length = 8;
+	std::string foe_team_file;
+	do {
+		foe_team_file = "teams/foe/";
+		foe_team_file += random_string(random_engine, file_name_length);
+		foe_team_file += get_extension();
+	} while (boost::filesystem::exists(foe_team_file));
+	return foe_team_file;
+}
+
+}	// namespace
+
+void Battle::handle_end (network::Client const & client, Result const result) const {
+	client.print_with_time_stamp(std::cout, to_string(result) + " a battle vs. " + opponent());
 	if (result == Result::lost) {
-		pl::write_team(predict_foe_team(client.detailed()), client.generate_team_file_name());
+		pl::write_team(predict_foe_team(client.detailed()), generate_team_file_name(random_engine));
 	}
 }
 

File source/clients/battle.hpp

 		void handle_send_out (Party switcher, uint8_t slot, uint8_t index, std::string const & nickname, Species species, Gender gender, uint8_t level);
 		void handle_set_pp (Party changer, uint8_t slot, uint8_t pp);
 		void handle_fainted (Party fainter, uint8_t slot);
-		void handle_end (network::Client & client, Result const result) const;
+		void handle_end (network::Client const & client, Result const result) const;
 		std::string const & opponent() const;
 		Battle(Battle const &) = delete;
 		Battle & operator= (Battle const &) = delete;

File source/clients/network/client.cpp

 #include "outmessage.hpp"
 
 #include "../battle.hpp"
+#include "../random_string.hpp"
 
 #include "../../exit_program.hpp"
 #include "../../settings_file.hpp"
 		port = server.port;
 		current_username = server.username;
 		if (server.password.empty()) {
-			server.password = get_random_string (31);
+			server.password = random_string(random_engine, 31);
 			settings.write();
 		}
 		current_password = server.password;
 	return current_password;
 }
 
-namespace {
-
-std::string get_extension () {
-	// TODO: add support for other formats
-	return ".sbt";
-}
-
-}	// unnamed namespace
-
 void Client::handle_battle_end (uint32_t const battle_id, Result const result) {
 	auto const & battle = battles.find(battle_id);
 	battle.handle_end (*this, result);
 	return Team(random_engine, team_file_name);
 }
 
-std::string Client::generate_team_file_name () {
-	// Randomly generates a file name in 8.3 format. It then checks to see if
-	// that file name already exists. If it does, it randomly generates a new
-	// file name, and continues until it generates a name that does not exist.
-	// This limits the potential for a race condition down to a 1 / 36^8 chance
-	// (about 1 / 2 ^ 41), assuming that another process / thread is also
-	// trying to save an 8 character file name with an identical extension at
-	// the same time. The result of this is that a team file would not be saved
-	// when it should have been, which is not a major issue.
-	std::string foe_team_file;
-	do {
-		foe_team_file = "teams/foe/";
-		foe_team_file += get_random_string (8);
-		foe_team_file += get_extension ();
-	} while (boost::filesystem::exists (foe_team_file));
-	return foe_team_file;
-}
-
-std::string Client::get_random_string (unsigned size) {
-	constexpr unsigned range = 36;
-	static constexpr char legal_characters [] = "abcdefghijklmnopqrstuvwxyz0123456789";
-	static_assert(sizeof(legal_characters) == range + 1, "Invalid amount of legal random characters.");
-	std::uniform_int_distribution<unsigned> distribution { 0, range - 1 };
-	std::string str;
-	str.resize(size);
-	std::generate(std::begin(str), std::end(str), [&]() { return legal_characters[distribution(random_engine)]; });
-	return str;
-}
-
 bool Client::is_highlighted (std::string const & message) const {
 	// Easiest way I've thought of to see if anything in highlights is in the
 	// message is to do a search in the message on each of the elements in

File source/clients/network/client.hpp

 	public:
 		void print_with_time_stamp(std::ostream & stream, std::string const & message) const;
 		void handle_channel_message (uint32_t channel_id, std::string const & user, std::string const & message) const;
-		std::string generate_team_file_name();
 		Evaluate const & evaluation_constants() const;
 		DetailedStats const & detailed() const;
 		void send_message(OutMessage & msg);
 		virtual void part_channel (std::string const & channel) = 0;
 		std::string time_stamp () const;
 		bool is_highlighted (std::string const & message) const;
-		std::string get_random_string (unsigned size);
 		void do_request (std::string const & user, std::string const & request);
 		void handle_challenge_command (std::string const & request, size_t start);
 		void handle_depth_change_command (std::string const & user, std::string const & request, size_t start);

File source/clients/random_string.hpp

+// Generate a random string of arbitrary length
+// Copyright (C) 2013 David Stone
+//
+// This file is part of Technical Machine.
+//
+// Technical Machine is free software: you can redistribute it and / or modify
+// it under the terms of the GNU Affero 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 Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef CLIENT__RANDOM_STRING_HPP_
+#define CLIENT__RANDOM_STRING_HPP_
+
+#include <algorithm>
+#include <random>
+#include <string>
+
+namespace technicalmachine {
+
+template<typename RandomEngine>
+char random_character(RandomEngine & random_engine) {
+	static constexpr char legal_characters[] = "abcdefghijklmnopqrstuvwxyz0123456789";
+	static constexpr auto number_of_characters = sizeof(legal_characters) - 1;
+	std::uniform_int_distribution<size_t> distribution(0, number_of_characters - 1);
+	return legal_characters[distribution(random_engine)];
+}
+
+template<typename RandomEngine>
+std::string random_string(RandomEngine & random_engine, size_t const size) {
+	std::string str;
+	str.resize(size);
+	std::generate(std::begin(str), std::end(str), [&]() { return random_character(random_engine); });
+	return str;
+}
+
+}	// namespace technicalmachine
+#endif	// CLIENT__RANDOM_STRING_HPP_