← Back to team overview

widelands-dev team mailing list archive

Re: [Merge] lp:~widelands-dev/widelands/bug-1678987-save-handler into lp:widelands

 

Review is ok for me:
 * more const is never wrong
 * Did not grasp that string thing, though.

Will compile and testplay this now, perhaps fo my next youtube video?

Diff comments:

> 
> === modified file 'src/logic/player.cc'
> --- src/logic/player.cc	2018-07-12 04:41:20 +0000
> +++ src/logic/player.cc	2018-07-13 13:41:35 +0000
> @@ -1357,25 +1358,45 @@
>   *
>   * \param fr source stream
>   */
> -void Player::read_statistics(FileRead& fr) {
> +void Player::read_statistics(FileRead& fr, const uint16_t packet_version) {
>  	uint16_t nr_wares = fr.unsigned_16();
> -	uint16_t nr_entries = fr.unsigned_16();
> +	size_t nr_entries = fr.unsigned_16();
> +
> +	// Stats are saved as a single string to reduce number of hard disk write operations
> +	const auto parse_stats = [nr_entries](std::vector<std::vector<uint32_t>>* stats, const DescriptionIndex ware_index, const std::string& stats_string, const std::string& description) {
> +		if (!stats_string.empty()) {
> +			std::vector<std::string> stats_vector;
> +			boost::split(stats_vector, stats_string, boost::is_any_of("|"));
> +			if (stats_vector.size() != nr_entries) {
> +				throw GameDataError("wrong number of %s statistics - expected %" PRIuS " but got %" PRIuS, description.c_str(), nr_entries, stats_vector.size());

Hmm,  could we handle this more gracefully so the game can be loaded (with some loss perhaps)

> +			}
> +			for (size_t j = 0; j < nr_entries; ++j) {
> +				stats->at(ware_index)[j] = static_cast<unsigned int>(atoi(stats_vector.at(j).c_str()));
> +			}
> +		} else if (nr_entries > 0) {
> +			throw GameDataError("wrong number of %s statistics - expected %" PRIuS " but got 0", description.c_str(), nr_entries);
> +		}
> +	};
>  
>  	for (uint32_t i = 0; i < current_produced_statistics_.size(); ++i)
>  		ware_productions_[i].resize(nr_entries);
>  
>  	for (uint16_t i = 0; i < nr_wares; ++i) {
> -		std::string name = fr.c_string();
> -		DescriptionIndex idx = egbase().tribes().ware_index(name);
> +		const std::string name = fr.c_string();
> +		const DescriptionIndex idx = egbase().tribes().ware_index(name);
>  		if (!egbase().tribes().ware_exists(idx)) {
>  			log("Player %u statistics: unknown ware name %s", player_number(), name.c_str());
>  			continue;
>  		}
>  
>  		current_produced_statistics_[idx] = fr.unsigned_32();
> -
> -		for (uint32_t j = 0; j < nr_entries; ++j)
> -			ware_productions_[idx][j] = fr.unsigned_32();
> +		if (packet_version < 22) {

This should be kCurrentPacketVersion?

> +			for (uint32_t j = 0; j < nr_entries; ++j) {
> +				ware_productions_[idx][j] = fr.unsigned_32();
> +			}
> +		} else {
> +			parse_stats(&ware_productions_, idx, fr.c_string(), "produced");
> +		}
>  	}
>  
>  	// Read consumption statistics
> @@ -1439,39 +1470,52 @@
>  }
>  
>  /**
> - * Write statistics data to the give file
> + * Write statistics data to the given file

Please ann an example of the written string, it might be interesting to read this in the dumped fiel perhaps?

>   */
>  void Player::write_statistics(FileWrite& fw) const {
> +	// Save stats as a single string to reduce number of hard disk write operations
> +	const auto write_stats = [&fw](const std::vector<std::vector<uint32_t>>& stats, const DescriptionIndex ware_index) {
> +		std::ostringstream oss("");
> +		if (!stats[ware_index].empty()) {
> +			for (uint32_t i = 0; i < stats[ware_index].size() - 1; ++i) {
> +				oss << stats[ware_index][i] << "|";
> +			}
> +			oss << stats[ware_index][stats[ware_index].size() - 1];
> +		}
> +		fw.c_string(oss.str());
> +	};
> +
> +	const Tribes& tribes = egbase().tribes();
> +	const std::set<DescriptionIndex>& tribe_wares = tribe().wares();
> +	const size_t nr_wares = tribe_wares.size();
> +
>  	// Write produce statistics
> -	fw.unsigned_16(current_produced_statistics_.size());
> +	fw.unsigned_16(nr_wares);
>  	fw.unsigned_16(ware_productions_[0].size());
>  
> -	for (uint8_t i = 0; i < current_produced_statistics_.size(); ++i) {
> -		fw.c_string(egbase().tribes().get_ware_descr(i)->name());
> -		fw.unsigned_32(current_produced_statistics_[i]);
> -		for (uint32_t j = 0; j < ware_productions_[i].size(); ++j)
> -			fw.unsigned_32(ware_productions_[i][j]);
> +	for (const DescriptionIndex ware_index : tribe_wares) {
> +		fw.c_string(tribes.get_ware_descr(ware_index)->name());
> +		fw.unsigned_32(current_produced_statistics_[ware_index]);
> +		write_stats(ware_productions_, ware_index);
>  	}
>  
>  	// Write consume statistics
> -	fw.unsigned_16(current_consumed_statistics_.size());
> +	fw.unsigned_16(nr_wares);
>  	fw.unsigned_16(ware_consumptions_[0].size());
>  
> -	for (uint8_t i = 0; i < current_consumed_statistics_.size(); ++i) {
> -		fw.c_string(egbase().tribes().get_ware_descr(i)->name());
> -		fw.unsigned_32(current_consumed_statistics_[i]);
> -		for (uint32_t j = 0; j < ware_consumptions_[i].size(); ++j)
> -			fw.unsigned_32(ware_consumptions_[i][j]);
> +	for (const DescriptionIndex ware_index : tribe_wares) {
> +		fw.c_string(tribes.get_ware_descr(ware_index)->name());
> +		fw.unsigned_32(current_consumed_statistics_[ware_index]);
> +		write_stats(ware_consumptions_, ware_index);
>  	}
>  
>  	// Write stock statistics
> -	fw.unsigned_16(ware_stocks_.size());
> +	fw.unsigned_16(nr_wares);
>  	fw.unsigned_16(ware_stocks_[0].size());
>  
> -	for (uint8_t i = 0; i < ware_stocks_.size(); ++i) {
> -		fw.c_string(egbase().tribes().get_ware_descr(i)->name());
> -		for (uint32_t j = 0; j < ware_stocks_[i].size(); ++j)
> -			fw.unsigned_32(ware_stocks_[i][j]);
> +	for (const DescriptionIndex ware_index : tribe_wares) {
> +		fw.c_string(tribes.get_ware_descr(ware_index)->name());
> +		write_stats(ware_stocks_, ware_index);
>  	}
>  }
>  }
> 
> === modified file 'src/logic/save_handler.cc'
> --- src/logic/save_handler.cc	2018-04-07 16:59:00 +0000
> +++ src/logic/save_handler.cc	2018-07-13 13:41:35 +0000
> @@ -83,14 +83,11 @@
>   * @return true if game should be saved ad next think().

That typo was perhaps mine :-) ad -> at

>   */
>  bool SaveHandler::check_next_tick(Widelands::Game& game, uint32_t realtime) {
> -
>  	// Perhaps save is due now?
>  	if (autosave_interval_in_ms_ <= 0 || next_save_realtime_ > realtime) {
>  		return false;  // no autosave or not due, yet
>  	}
>  
> -	next_save_realtime_ = realtime + autosave_interval_in_ms_;
> -
>  	// check if game is paused (in any way)
>  	if (game.game_controller()->is_paused_or_zero_speed()) {
>  		return false;


-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-1678987-save-handler/+merge/349096
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/bug-1678987-save-handler into lp:widelands.


References