<commit_before>#include "add_or_reupload_problem_base.h"
#include "../main.h"
#include "sim/constants.h"

#include <sim/problem.hh>
#include <simlib/libzip.hh>
#include <simlib/sim/problem_package.hh>

using sim::Problem;

namespace job_handlers {

void AddOrReuploadProblemBase::load_job_log_from_DB() {
	STACK_UNWINDING_MARK;
	auto stmt = mysql.prepare("SELECT data FROM jobs WHERE id=?");
	stmt.bind_and_execute(job_id_);
	stmt.res_bind_all(job_log_holder_);
	stmt.next();
}

void AddOrReuploadProblemBase::assert_transaction_is_open() {
	STACK_UNWINDING_MARK;

	unsigned char in_transaction;
	auto stmt = mysql.prepare("SELECT @@in_transaction");
	stmt.bind_and_execute();
	stmt.res_bind_all(in_transaction);
	throw_assert(stmt.next() and in_transaction);
}

void AddOrReuploadProblemBase::build_package() {
	STACK_UNWINDING_MARK;
	if (failed())
		return;

	assert_transaction_is_open();

	replace_db_job_log_ = true;

	auto source_package = internal_file_path(job_file_id_);

	mysql.update("INSERT INTO internal_files VALUES()");
	tmp_file_id_ = mysql.insert_id();

	/* Construct Simfile */

	sim::Conver conver;
	conver.package_path(source_package.to_string());

	// Set Conver options
	sim::Conver::Options copts;
	copts.name = info_.name;
	copts.label = info_.label;
	copts.memory_limit = info_.memory_limit;
	copts.global_time_limit = info_.global_time_limit;
	copts.max_time_limit = MAX_TIME_LIMIT;
	copts.reset_time_limits_using_model_solution = info_.reset_time_limits;
	copts.ignore_simfile = info_.ignore_simfile;
	copts.seek_for_new_tests = info_.seek_for_new_tests;
	copts.reset_scoring = info_.reset_scoring;
	copts.require_statement = true;
	copts.rtl_opts.min_time_limit = MIN_TIME_LIMIT;
	copts.rtl_opts.solution_runtime_coefficient = SOLUTION_RUNTIME_COEFFICIENT;

	sim::Conver::ConstructionResult cr;
	try {
		cr = conver.construct_simfile(copts);
	} catch (const std::exception& e) {
		return set_failure(conver.report(), "Conver failed: ", e.what());
	}

	// Check problem's name's length
	if (WONT_THROW(cr.simfile.name.value()).size() >
	    decltype(Problem::name)::max_len) {
		return set_failure("Problem's name is too long (max allowed length: ",
		                   decltype(Problem::name)::max_len, ')');
	}

	// Check problem's label's length
	if (WONT_THROW(cr.simfile.label.value()).size() >
	    decltype(Problem::label)::max_len) {
		return set_failure("Problem's label is too long (max allowed length: ",
		                   decltype(Problem::label)::max_len, ')');
	}

	job_log(conver.report());

	/* Create the temporary package */

	// Update job record
	mysql.prepare("UPDATE jobs SET tmp_file_id=? WHERE id=?")
	   .bind_and_execute(tmp_file_id_.value(), job_id_);
	auto tmp_package = internal_file_path(tmp_file_id_.value());
	// Copy source_package to tmp_package, substituting Simfile in the fly
	{
		ZipFile src_zip(source_package, ZIP_RDONLY);
		simfile_str_ = cr.simfile.dump();
		auto simfile_path = concat(cr.pkg_master_dir, "Simfile");

		package_file_remover_.reset(tmp_package);
		ZipFile dest_zip(tmp_package, ZIP_CREATE | ZIP_TRUNCATE);

		auto eno = src_zip.entries_no();
		for (decltype(eno) i = 0; i < eno; ++i) {
			auto entry_name = src_zip.get_name(i);
			if (entry_name == simfile_path) {
				dest_zip.file_add(simfile_path,
				                  dest_zip.source_buffer(simfile_str_));
			} else {
				dest_zip.file_add(entry_name, dest_zip.source_zip(src_zip, i));
			}
		}

		dest_zip.close(); // Write all data to the dest_zip
	}

	switch (cr.status) {
	case sim::Conver::Status::COMPLETE:
		need_model_solution_judge_report_ = false;
		return;
	case sim::Conver::Status::NEED_MODEL_SOLUTION_JUDGE_REPORT:
		need_model_solution_judge_report_ = true;
		return;
	}
}

void AddOrReuploadProblemBase::job_done(bool& job_was_canceled) {
	STACK_UNWINDING_MARK;
	if (failed())
		return;

	EnumVal<JobStatus> status = JobStatus::DONE;
	EnumVal<JobType> type = job_type_;
	if (need_model_solution_judge_report_) {
		status = JobStatus::PENDING;
		switch (job_type_) {
		case JobType::ADD_PROBLEM:
			type = JobType::ADD_PROBLEM__JUDGE_MODEL_SOLUTION;
			break;

		case JobType::REUPLOAD_PROBLEM:
			type = JobType::REUPLOAD_PROBLEM__JUDGE_MODEL_SOLUTION;
			break;

		default: THROW("Unexpected job type");
		}

	} else {
		switch (job_type_) {
		case JobType::ADD_PROBLEM:
		case JobType::REUPLOAD_PROBLEM: break;

		case JobType::ADD_PROBLEM__JUDGE_MODEL_SOLUTION:
			status = JobStatus::PENDING;
			type = JobType::ADD_PROBLEM;
			break;

		case JobType::REUPLOAD_PROBLEM__JUDGE_MODEL_SOLUTION:
			status = JobStatus::PENDING;
			type = JobType::REUPLOAD_PROBLEM;
			break;

		default: THROW("Unexpected job type");
		}
	}

	auto stmt = mysql.prepare("UPDATE jobs "
	                          "SET tmp_file_id=?, type=?, priority=?,"
	                          " status=?, aux_id=?, info=?, data=? "
	                          "WHERE id=? AND status!=?");
	stmt.bind_and_execute(tmp_file_id_, type, priority(type), status,
	                      problem_id_, info_.dump(), get_log(), job_id_,
	                      EnumVal(JobStatus::CANCELED));
	job_was_canceled = (stmt.affected_rows() == 0);
}

static SubmissionLanguage filename_to_lang(StringView extension) {
	STACK_UNWINDING_MARK;

	auto lang = sim::filename_to_lang(extension);
	switch (lang) {
	case sim::SolutionLanguage::C11: return SubmissionLanguage::C11;
	case sim::SolutionLanguage::CPP11: return SubmissionLanguage::CPP11;
	case sim::SolutionLanguage::CPP14: return SubmissionLanguage::CPP14;
	case sim::SolutionLanguage::CPP17: return SubmissionLanguage::CPP17;
	case sim::SolutionLanguage::PASCAL: return SubmissionLanguage::PASCAL;
	case sim::SolutionLanguage::UNKNOWN: THROW("Not supported language");
	}

	throw_assert(false);
}

void AddOrReuploadProblemBase::open_package() {
	STACK_UNWINDING_MARK;
	if (failed())
		return;

	assert_transaction_is_open();

	zip_ = ZipFile(internal_file_path(tmp_file_id_.value()), ZIP_RDONLY);
	master_dir_ = sim::zip_package_master_dir(zip_);
	simfile_str_ =
	   zip_.extract_to_str(zip_.get_index(concat(master_dir_, "Simfile")));

	simfile_ = sim::Simfile(simfile_str_);
	simfile_.load_name();
	simfile_.load_label();
	simfile_.load_solutions();

	current_date_ = mysql_date();
}

void AddOrReuploadProblemBase::add_problem_to_DB() {
	STACK_UNWINDING_MARK;
	if (failed())
		return;

	open_package();

	auto stmt = mysql.prepare("INSERT INTO problems(file_id, type, name, label,"
	                          " simfile, owner, added, last_edit) "
	                          "VALUES(?,?,?,?,?,?,?,?)");
	stmt.bind_and_execute(tmp_file_id_.value(),
	                      decltype(Problem::type)(info_.problem_type),
	                      simfile_.name, simfile_.label, simfile_str_,
	                      job_creator_, current_date_, current_date_);

	tmp_file_id_ = std::nullopt;
	problem_id_ = stmt.insert_id();
}

void AddOrReuploadProblemBase::replace_problem_in_DB() {
	STACK_UNWINDING_MARK;
	if (failed())
		return;

	open_package();

	// Add job to delete old problem file
	mysql
	   .prepare("INSERT INTO jobs(file_id, creator, type, priority, status,"
	            " added, aux_id, info, data) "
	            "SELECT file_id, NULL, ?, ?, ?, ?, NULL, '', '' "
	            "FROM problems WHERE id=?")
	   .bind_and_execute(
	      EnumVal(JobType::DELETE_FILE), priority(JobType::DELETE_FILE),
	      EnumVal(JobStatus::PENDING), current_date_, problem_id_.value());

	// Update problem
	auto stmt = mysql.prepare("UPDATE problems "
	                          "SET file_id=?, type=?, name=?, label=?,"
	                          " simfile=?, last_edit=? "
	                          "WHERE id=?");
	stmt.bind_and_execute(tmp_file_id_.value(),
	                      decltype(Problem::type)(info_.problem_type),
	                      simfile_.name, simfile_.label, simfile_str_,
	                      current_date_, problem_id_.value());

	tmp_file_id_ = std::nullopt;

	// Schedule jobs to delete old solutions files
	mysql
	   .prepare("INSERT INTO jobs(file_id, creator, type, priority, status,"
	            " added, aux_id, info, data) "
	            "SELECT file_id, NULL, ?, ?, ?, ?, NULL, '', '' "
	            "FROM submissions "
	            "WHERE problem_id=? AND type=?")
	   .bind_and_execute(
	      EnumVal(JobType::DELETE_FILE), priority(JobType::DELETE_FILE),
	      EnumVal(JobStatus::PENDING), current_date_, problem_id_,
	      EnumVal(SubmissionType::PROBLEM_SOLUTION));

	// Delete old solution submissions
	mysql
	   .prepare("DELETE FROM submissions "
	            "WHERE problem_id=? AND type=?")
	   .bind_and_execute(problem_id_,
	                     EnumVal(SubmissionType::PROBLEM_SOLUTION));
}

void AddOrReuploadProblemBase::submit_solutions() {
	STACK_UNWINDING_MARK;
	if (failed())
		return;

	assert_transaction_is_open();

	job_log("Submitting solutions...");
	const auto zero_date = mysql_date(0);
	auto submission_inserter = mysql.prepare(
	   "INSERT INTO submissions (file_id, owner, problem_id, "
	   "contest_problem_id, contest_round_id, contest_id, type, language, "
	   "initial_status, full_status, submit_time, last_judgment, "
	   "initial_report, final_report) VALUES(?, NULL, ?, NULL, NULL, "
	   "NULL, ?, ?, ?, ?, ?, ?, '', '')");

	auto file_inserter = mysql.prepare("INSERT INTO internal_files VALUES()");

	for (auto const& solution : simfile_.solutions) {
		job_log("Submit: ", solution);

		file_inserter.execute();
		uint64_t file_id = file_inserter.insert_id();
		EnumVal<SubmissionLanguage> lang = filename_to_lang(solution);
		submission_inserter.bind_and_execute(
		   file_id, problem_id_, EnumVal(SubmissionType::PROBLEM_SOLUTION),
		   lang, EnumVal(SubmissionStatus::PENDING),
		   EnumVal(SubmissionStatus::PENDING), current_date_, zero_date);

		// Save the submission source code
		zip_.extract_to_file(zip_.get_index(concat(master_dir_, solution)),
		                     internal_file_path(file_id), S_0600);
	}

	// Add jobs to judge the solutions
	mysql
	   .prepare("INSERT INTO jobs(creator, type, priority, status, added,"
	            " aux_id, info, data) "
	            "SELECT NULL, ?, ?, ?, ?, id, ?, '' "
	            "FROM submissions "
	            "WHERE problem_id=? AND type=? ORDER BY id")
	   // Problem's solutions are more important than the ordinary submissions
	   .bind_and_execute(EnumVal(JobType::JUDGE_SUBMISSION),
	                     priority(JobType::JUDGE_SUBMISSION) + 1,
	                     EnumVal(JobStatus::PENDING), current_date_,
	                     jobs::dumpString(intentional_unsafe_string_view(
	                        to_string(problem_id_.value()))),
	                     problem_id_.value(),
	                     EnumVal(SubmissionType::PROBLEM_SOLUTION));

	job_log("Done.");
}

} // namespace job_handlers
<commit_msg>Fixed adding / reuploading problem without specified name or label in the Add / Reupload form<commit_after>#include "add_or_reupload_problem_base.h"
#include "../main.h"
#include "sim/constants.h"

#include <sim/problem.hh>
#include <simlib/libzip.hh>
#include <simlib/sim/problem_package.hh>

using sim::Problem;

namespace job_handlers {

void AddOrReuploadProblemBase::load_job_log_from_DB() {
	STACK_UNWINDING_MARK;
	auto stmt = mysql.prepare("SELECT data FROM jobs WHERE id=?");
	stmt.bind_and_execute(job_id_);
	stmt.res_bind_all(job_log_holder_);
	stmt.next();
}

void AddOrReuploadProblemBase::assert_transaction_is_open() {
	STACK_UNWINDING_MARK;

	unsigned char in_transaction;
	auto stmt = mysql.prepare("SELECT @@in_transaction");
	stmt.bind_and_execute();
	stmt.res_bind_all(in_transaction);
	throw_assert(stmt.next() and in_transaction);
}

void AddOrReuploadProblemBase::build_package() {
	STACK_UNWINDING_MARK;
	if (failed())
		return;

	assert_transaction_is_open();

	replace_db_job_log_ = true;

	auto source_package = internal_file_path(job_file_id_);

	mysql.update("INSERT INTO internal_files VALUES()");
	tmp_file_id_ = mysql.insert_id();

	/* Construct Simfile */

	sim::Conver conver;
	conver.package_path(source_package.to_string());

	// Set Conver options
	sim::Conver::Options copts;
	copts.name = (info_.name.empty() ? std::nullopt : std::optional(info_.name));
	copts.label = (info_.label.empty() ? std::nullopt : std::optional(info_.label));
	copts.memory_limit = info_.memory_limit;
	copts.global_time_limit = info_.global_time_limit;
	copts.max_time_limit = MAX_TIME_LIMIT;
	copts.reset_time_limits_using_model_solution = info_.reset_time_limits;
	copts.ignore_simfile = info_.ignore_simfile;
	copts.seek_for_new_tests = info_.seek_for_new_tests;
	copts.reset_scoring = info_.reset_scoring;
	copts.require_statement = true;
	copts.rtl_opts.min_time_limit = MIN_TIME_LIMIT;
	copts.rtl_opts.solution_runtime_coefficient = SOLUTION_RUNTIME_COEFFICIENT;

	sim::Conver::ConstructionResult cr;
	try {
		cr = conver.construct_simfile(copts);
	} catch (const std::exception& e) {
		return set_failure(conver.report(), "Conver failed: ", e.what());
	}

	// Check problem's name's length
	if (WONT_THROW(cr.simfile.name.value()).size() >
	    decltype(Problem::name)::max_len) {
		return set_failure("Problem's name is too long (max allowed length: ",
		                   decltype(Problem::name)::max_len, ')');
	}

	// Check problem's label's length
	if (WONT_THROW(cr.simfile.label.value()).size() >
	    decltype(Problem::label)::max_len) {
		return set_failure("Problem's label is too long (max allowed length: ",
		                   decltype(Problem::label)::max_len, ')');
	}

	job_log(conver.report());

	/* Create the temporary package */

	// Update job record
	mysql.prepare("UPDATE jobs SET tmp_file_id=? WHERE id=?")
	   .bind_and_execute(tmp_file_id_.value(), job_id_);
	auto tmp_package = internal_file_path(tmp_file_id_.value());
	// Copy source_package to tmp_package, substituting Simfile in the fly
	{
		ZipFile src_zip(source_package, ZIP_RDONLY);
		simfile_str_ = cr.simfile.dump();
		auto simfile_path = concat(cr.pkg_master_dir, "Simfile");

		package_file_remover_.reset(tmp_package);
		ZipFile dest_zip(tmp_package, ZIP_CREATE | ZIP_TRUNCATE);

		auto eno = src_zip.entries_no();
		for (decltype(eno) i = 0; i < eno; ++i) {
			auto entry_name = src_zip.get_name(i);
			if (entry_name == simfile_path) {
				dest_zip.file_add(simfile_path,
				                  dest_zip.source_buffer(simfile_str_));
			} else {
				dest_zip.file_add(entry_name, dest_zip.source_zip(src_zip, i));
			}
		}

		dest_zip.close(); // Write all data to the dest_zip
	}

	switch (cr.status) {
	case sim::Conver::Status::COMPLETE:
		need_model_solution_judge_report_ = false;
		return;
	case sim::Conver::Status::NEED_MODEL_SOLUTION_JUDGE_REPORT:
		need_model_solution_judge_report_ = true;
		return;
	}
}

void AddOrReuploadProblemBase::job_done(bool& job_was_canceled) {
	STACK_UNWINDING_MARK;
	if (failed())
		return;

	EnumVal<JobStatus> status = JobStatus::DONE;
	EnumVal<JobType> type = job_type_;
	if (need_model_solution_judge_report_) {
		status = JobStatus::PENDING;
		switch (job_type_) {
		case JobType::ADD_PROBLEM:
			type = JobType::ADD_PROBLEM__JUDGE_MODEL_SOLUTION;
			break;

		case JobType::REUPLOAD_PROBLEM:
			type = JobType::REUPLOAD_PROBLEM__JUDGE_MODEL_SOLUTION;
			break;

		default: THROW("Unexpected job type");
		}

	} else {
		switch (job_type_) {
		case JobType::ADD_PROBLEM:
		case JobType::REUPLOAD_PROBLEM: break;

		case JobType::ADD_PROBLEM__JUDGE_MODEL_SOLUTION:
			status = JobStatus::PENDING;
			type = JobType::ADD_PROBLEM;
			break;

		case JobType::REUPLOAD_PROBLEM__JUDGE_MODEL_SOLUTION:
			status = JobStatus::PENDING;
			type = JobType::REUPLOAD_PROBLEM;
			break;

		default: THROW("Unexpected job type");
		}
	}

	auto stmt = mysql.prepare("UPDATE jobs "
	                          "SET tmp_file_id=?, type=?, priority=?,"
	                          " status=?, aux_id=?, info=?, data=? "
	                          "WHERE id=? AND status!=?");
	stmt.bind_and_execute(tmp_file_id_, type, priority(type), status,
	                      problem_id_, info_.dump(), get_log(), job_id_,
	                      EnumVal(JobStatus::CANCELED));
	job_was_canceled = (stmt.affected_rows() == 0);
}

static SubmissionLanguage filename_to_lang(StringView extension) {
	STACK_UNWINDING_MARK;

	auto lang = sim::filename_to_lang(extension);
	switch (lang) {
	case sim::SolutionLanguage::C11: return SubmissionLanguage::C11;
	case sim::SolutionLanguage::CPP11: return SubmissionLanguage::CPP11;
	case sim::SolutionLanguage::CPP14: return SubmissionLanguage::CPP14;
	case sim::SolutionLanguage::CPP17: return SubmissionLanguage::CPP17;
	case sim::SolutionLanguage::PASCAL: return SubmissionLanguage::PASCAL;
	case sim::SolutionLanguage::UNKNOWN: THROW("Not supported language");
	}

	throw_assert(false);
}

void AddOrReuploadProblemBase::open_package() {
	STACK_UNWINDING_MARK;
	if (failed())
		return;

	assert_transaction_is_open();

	zip_ = ZipFile(internal_file_path(tmp_file_id_.value()), ZIP_RDONLY);
	master_dir_ = sim::zip_package_master_dir(zip_);
	simfile_str_ =
	   zip_.extract_to_str(zip_.get_index(concat(master_dir_, "Simfile")));

	simfile_ = sim::Simfile(simfile_str_);
	simfile_.load_name();
	simfile_.load_label();
	simfile_.load_solutions();

	current_date_ = mysql_date();
}

void AddOrReuploadProblemBase::add_problem_to_DB() {
	STACK_UNWINDING_MARK;
	if (failed())
		return;

	open_package();

	auto stmt = mysql.prepare("INSERT INTO problems(file_id, type, name, label,"
	                          " simfile, owner, added, last_edit) "
	                          "VALUES(?,?,?,?,?,?,?,?)");
	stmt.bind_and_execute(tmp_file_id_.value(),
	                      decltype(Problem::type)(info_.problem_type),
	                      simfile_.name, simfile_.label, simfile_str_,
	                      job_creator_, current_date_, current_date_);

	tmp_file_id_ = std::nullopt;
	problem_id_ = stmt.insert_id();
}

void AddOrReuploadProblemBase::replace_problem_in_DB() {
	STACK_UNWINDING_MARK;
	if (failed())
		return;

	open_package();

	// Add job to delete old problem file
	mysql
	   .prepare("INSERT INTO jobs(file_id, creator, type, priority, status,"
	            " added, aux_id, info, data) "
	            "SELECT file_id, NULL, ?, ?, ?, ?, NULL, '', '' "
	            "FROM problems WHERE id=?")
	   .bind_and_execute(
	      EnumVal(JobType::DELETE_FILE), priority(JobType::DELETE_FILE),
	      EnumVal(JobStatus::PENDING), current_date_, problem_id_.value());

	// Update problem
	auto stmt = mysql.prepare("UPDATE problems "
	                          "SET file_id=?, type=?, name=?, label=?,"
	                          " simfile=?, last_edit=? "
	                          "WHERE id=?");
	stmt.bind_and_execute(tmp_file_id_.value(),
	                      decltype(Problem::type)(info_.problem_type),
	                      simfile_.name, simfile_.label, simfile_str_,
	                      current_date_, problem_id_.value());

	tmp_file_id_ = std::nullopt;

	// Schedule jobs to delete old solutions files
	mysql
	   .prepare("INSERT INTO jobs(file_id, creator, type, priority, status,"
	            " added, aux_id, info, data) "
	            "SELECT file_id, NULL, ?, ?, ?, ?, NULL, '', '' "
	            "FROM submissions "
	            "WHERE problem_id=? AND type=?")
	   .bind_and_execute(
	      EnumVal(JobType::DELETE_FILE), priority(JobType::DELETE_FILE),
	      EnumVal(JobStatus::PENDING), current_date_, problem_id_,
	      EnumVal(SubmissionType::PROBLEM_SOLUTION));

	// Delete old solution submissions
	mysql
	   .prepare("DELETE FROM submissions "
	            "WHERE problem_id=? AND type=?")
	   .bind_and_execute(problem_id_,
	                     EnumVal(SubmissionType::PROBLEM_SOLUTION));
}

void AddOrReuploadProblemBase::submit_solutions() {
	STACK_UNWINDING_MARK;
	if (failed())
		return;

	assert_transaction_is_open();

	job_log("Submitting solutions...");
	const auto zero_date = mysql_date(0);
	auto submission_inserter = mysql.prepare(
	   "INSERT INTO submissions (file_id, owner, problem_id, "
	   "contest_problem_id, contest_round_id, contest_id, type, language, "
	   "initial_status, full_status, submit_time, last_judgment, "
	   "initial_report, final_report) VALUES(?, NULL, ?, NULL, NULL, "
	   "NULL, ?, ?, ?, ?, ?, ?, '', '')");

	auto file_inserter = mysql.prepare("INSERT INTO internal_files VALUES()");

	for (auto const& solution : simfile_.solutions) {
		job_log("Submit: ", solution);

		file_inserter.execute();
		uint64_t file_id = file_inserter.insert_id();
		EnumVal<SubmissionLanguage> lang = filename_to_lang(solution);
		submission_inserter.bind_and_execute(
		   file_id, problem_id_, EnumVal(SubmissionType::PROBLEM_SOLUTION),
		   lang, EnumVal(SubmissionStatus::PENDING),
		   EnumVal(SubmissionStatus::PENDING), current_date_, zero_date);

		// Save the submission source code
		zip_.extract_to_file(zip_.get_index(concat(master_dir_, solution)),
		                     internal_file_path(file_id), S_0600);
	}

	// Add jobs to judge the solutions
	mysql
	   .prepare("INSERT INTO jobs(creator, type, priority, status, added,"
	            " aux_id, info, data) "
	            "SELECT NULL, ?, ?, ?, ?, id, ?, '' "
	            "FROM submissions "
	            "WHERE problem_id=? AND type=? ORDER BY id")
	   // Problem's solutions are more important than the ordinary submissions
	   .bind_and_execute(EnumVal(JobType::JUDGE_SUBMISSION),
	                     priority(JobType::JUDGE_SUBMISSION) + 1,
	                     EnumVal(JobStatus::PENDING), current_date_,
	                     jobs::dumpString(intentional_unsafe_string_view(
	                        to_string(problem_id_.value()))),
	                     problem_id_.value(),
	                     EnumVal(SubmissionType::PROBLEM_SOLUTION));

	job_log("Done.");
}

} // namespace job_handlers
<|endoftext|>


<commit_before>#ifndef GENERIC_CIFY_HPP
# define GENERIC_CIFY_HPP
# pragma once

#include <utility>

namespace generic
{

namespace
{

template <typename F, typename L, int I = 0, typename R, typename ...A>
F cify(L&& l, R (*)(A...))
{
  static L const l_(::std::forward<L>(l));

  struct S
  {
    static R f(A... args)
    {
      l_(::std::forward<A>(args)...);
    }
  };

  return &S::f;
}

}

template <typename F, typename L, int I = 0>
F cify(L&& l)
{
  return cify<F>(::std::forward<L>(l), F());
}

}

#endif // GENERIC_CIFY_HPP
<commit_msg>some fixes<commit_after>#ifndef GENERIC_CIFY_HPP
# define GENERIC_CIFY_HPP
# pragma once

#include <utility>

namespace generic
{

namespace
{

template <typename F, int I, typename L, typename R, typename ...A>
F cify(L&& l, R (*)(A...))
{
  static L const l_(::std::forward<L>(l));

  struct S
  {
    static R f(A... args)
    {
      l_(::std::forward<A>(args)...);
    }
  };

  return &S::f;
}

}

template <typename F, int I = 0, typename L>
F cify(L&& l)
{
  return cify<F, I>(::std::forward<L>(l), F());
}

}

#endif // GENERIC_CIFY_HPP
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#include <GL/glut.h>

#define GL_GLEXT_PROTOTYPES
#define PI 3.1416
double scale = 1.0;
double world_y = 0, wing_z = 0, z_factor = 100.0, r_step = 5.0;
double wind_y = 0, wind_x = 0;
double progoffset = 0.0, progstep = 0.000;
void Cone(double radius, double height, double c1, double c2,bool flag = true)
{
	int steps = 1000;
	for(int i=0;i<steps;++i)
	{
		double th = (360.0/steps)*i;
		glBegin (GL_LINES);
			if(flag)
	    glColor3f  (c1,c1,c1);
			else
			glColor3f(c1,0,0);
			glVertex3f  (radius*cos(th),radius*sin(th) , 0);
			if(flag)
			glColor3f  (c2, c2, c2);
			else
			glColor3f(c2,0,0);
			glVertex3f(0,0,height);
	    glEnd ();
	}
}
void Wing(double radius, double height, double epoch)
{
	glLoadIdentity();
	glRotatef(world_y, 0.0, 1.0, 0.0);
	glTranslatef(.0,-.05,0);
	glRotatef(wing_z+epoch, 0.0, 0.0, 1.0);
	glTranslatef(.05,.0,-.07);
	glRotatef(90, 0.0, 1.0, 0.0);
	Cone(radius,height,.1,1);
}

//Arrow is from pos1 to pos2 with propagation offset of progoffset
//pos2 > pos1
//Initialize pos1 to -1.0 and pos2 to pos1 + length of the arrow
void Arrow(double radius,double x, double y, double pos1, double pos2, double c1, double c2)
{
	glLoadIdentity();
	glRotatef(world_y,0,1.0,0);
	glRotatef(wind_x,1.0,0,0);
	glRotatef(wind_y,0,1.0,0);

	if(progstep < 0)
	{
		double temp = c1;
		c1 = c2;
		c2 = temp;
	}
	else if(progstep == 0.0)
	{
		c1 = c2 = 0.0;
	}
	for(int i = 0; i < 100; i++)
	{
		double th = (360.0/100)*i;
		glBegin(GL_LINES);
			glColor3f(c1,0,0);
			glVertex3f(x+radius*cos(th),y+radius*sin(th),pos1+progoffset);
			glColor3f(c2,0,0);
			glVertex3f(x+radius*cos(th),y+radius*sin(th),pos2+progoffset);
		glEnd();
	}
	if(progstep > 0)
	{
		glTranslatef(x,y,pos2+progoffset);
		Cone(3*radius,fabs(pos2-pos1)*0.4,1.0,1.0,false);
	}
	else if(progstep < 0)
	{
		glTranslatef(x,y,pos1+progoffset);
		glRotatef(180,0,1.0,0);
		Cone(3*radius,fabs(pos2-pos1)*0.4,1.0,1.0,false);
	}

}
void drawCube()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear color and depth buffers

	glLoadIdentity();	// Reset the model-view matrix

	// rotate the cube according to rx world_y and wing_z parameters , controlled via arrow keys

	glColor3f  (.3, .3, .3);
	glRotatef(world_y, 0.0, 1.0, 0.0);
	glRotatef(90, 1.0, 0.0, 0.0);
	GLUquadricObj *quadObj = gluNewQuadric();
	gluCylinder(quadObj, .03, .05, 0.75, 100, 100);

	glLoadIdentity();
	glRotatef(world_y, 0.0, 1.0, 0.0);
	glTranslatef(0,-0.05,-.10);
	gluCylinder(quadObj, .05, .05, .07, 100, 100);

	glLoadIdentity();
	glRotatef(world_y, 0.0, 1.0, 0.0);
	glTranslatef(0,-0.05,-.1);
	glRotatef(180, 0.0, 1.0, 0.0);
	Cone(.05,.0,.3,.3);

	Wing(.04,.5,0);
	Wing(.04,.5,90);
	Wing(.04,.5,180);
	Wing(.04,.5,270);

	Arrow(0.005,0.2,0.2,-.98,-0.78,0.2,1.0);
	Arrow(0.005,0.2,-0.2,-.98,-0.78,0.2,1.0);
	Arrow(0.005,-0.2,0.2,-.98,-0.78,0.2,1.0);
	Arrow(0.005,-0.2,-0.2,-.98,-0.78,0.2,1.0);

	glLoadIdentity();
	glRotatef(-10, 1.0, 0.0, 0.0);
	glRotatef(world_y+45, 0.0, 1.0, 0.0);
	for(int i=0;i<1000;++i)
	{
		glBegin (GL_LINES);
	    glColor3f  (0,.1+.3*i/1000.0,0);
	    glVertex3f  (-.5+i/1000.0,-.75, .5);
	    glColor3f  (0,.7+.3*i/1000.0,0);
	    glVertex3f  (-.5+i/1000.0,-.75, -.5);
	    glEnd();
	}

	glFlush();
    glutSwapBuffers();
}

void specialKeys(int key, int x, int y)
{
	if ( key == GLUT_KEY_RIGHT )
		world_y += r_step;
	if ( key == GLUT_KEY_LEFT )
		world_y -= r_step;
	if ( key == GLUT_KEY_UP )
	{
		//z_step += .05;
		progstep += 0.0005;
	}
	if ( key == GLUT_KEY_DOWN )
	{
		//z_step -= .05;
		progstep -= 0.0005;
	}
	// if ( key == GLUT_KEY_PAGE_UP )
	// 	wing_z += r_step;
	// if ( key == GLUT_KEY_PAGE_DOWN )
	// 	wing_z -= r_step;

	glutPostRedisplay();
}
void rotate()
{
	wing_z += progstep*z_factor*cos(wind_x/180*PI)*cos(wind_y/180*PI);
	progoffset += progstep;
	if(-0.78 + progoffset > 0.99)
		progoffset = 0.0;
	else if(-.98 + progoffset < -0.99)
		progoffset = 1.76;
	glutPostRedisplay();
}
void rotateWind(unsigned char key, int x, int y)
{
	if(key == 'w')
		wind_x += r_step;
	else if(key == 's')
		wind_x -= r_step;
	else if(key == 'a')
		wind_y += r_step;
	else if(key == 'd')
		wind_y -= r_step;
}
int main(int argc, char* argv[])
{
	// Initialize GLUT and process user parameters
	glutInit(&argc, argv);
	// Request double buffered true color window with Z-buffer
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	// Set Window Size
	glutInitWindowSize(1000, 1000);
	// Set Window Position
	glutInitWindowPosition(100,100);
	// Create Window
	glutCreateWindow("Question 3");
	// Enable Z-buffer depth test
	glEnable(GL_DEPTH_TEST);
	// Callback Functions
	glutDisplayFunc(drawCube);
	glutIdleFunc(rotate);
	glutSpecialFunc(specialKeys);
	glutKeyboardFunc(rotateWind);
	glutMainLoop();
}<commit_msg>Added Comments and changed windmill.cpp<commit_after>#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <math.h>
#include <GL/glut.h>

#define GL_GLEXT_PROTOTYPES
#define PI 3.141592654
#define SHARPNESS_FACTOR 500	//Defines number of lines a 3d object is composed of

double floor_x = -30;	//Angle by which the floor is rotated about x-axis
double world_y = 0;	//Used for rotation of world coordinates about y-axis
double wing_z = 0;	//Angle by which wings rotate about z-axis
double wind_y = 0;	//Angle of rotation of direction of wind along y-axis
double r_step = 5.0;	//Angle by which wind_y is incremented/decremented
double scale = 1.0;	//Used for zooming in and out
double world_y_trans = 0.0;	//Used for translation along y-axis
double wing_speed = 0.0;	//Rotational speed of wings
double wind_acc_factor = .8; 	//Used in viscosity equation as coefficient of wind acceleration
double turbine_factor = 0.005;	//Used in viscosity equation as coefficient of wing speed
double progoffset = 0.0;	//Offset of arrow
double progstep = 0.000;	//Value by which progoffset is incremented/decremented
double progstep_acc = .0005;	//Rate of change of progstep
double torqueFact = 0.00002;	//Used for calculation of power

#include "shapes.h"
#include "user.h"

//Utility Function to reload identity matrix for objects
void resetIdentity()
{
	glLoadIdentity();
	glTranslatef(0.0,world_y_trans,0.0);
	glScalef(scale,scale,scale);	//Scaling used for zooming in and out
}

//Display Function
void drawWindMill()
{
	GLUquadricObj *quadObj = gluNewQuadric();	//Used for constructing wing axle
	char* st = new char[100];	//Used for printing DASHBOARD
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear color and depth buffers

	resetIdentity();
	glRotatef(world_y+90, 0.0, 1.0, 0.0);
	glRotatef(90, 1.0, 0.0, 0.0);
	Shaft(.03,.02,.75);

	resetIdentity();
	glRotatef(world_y, 0.0, 1.0, 0.0);
	glTranslatef(0,-0.03,-.07);
	gluCylinder(quadObj, .03, .03, .05, 100, 100);

	resetIdentity();
	glRotatef(world_y, 0.0, 1.0, 0.0);
	glTranslatef(0,-0.03,-.07);
	Cone(.03,.0,.6,.6);

	glLoadIdentity();
	glOrtho(-500, 500, -500, 500, -100000.0, 100000.0);
	glColor4f(0.20, 0.20, 0.20, 0.0);
	glRasterPos2f(200, 280.0);
	strcpy(st,"DASHBOARD");
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18,st);

	//Wing speed
	glColor4f(0.0, .7, 0.7, 0.0);
	glRasterPos2f(200, 240.0);
	strcpy(st,"Wing Speed(deg/frame): ");
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18,st);
	ftoa(fabs(wing_speed),st,4);
	if(wing_speed<0.0)
	{
		strcpy(st,"-");
		print_bitmap_string(GLUT_BITMAP_HELVETICA_12,st);
	}
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18, st);

	//Wind speed
	glColor4f(.7, 0.0, 0.0, 0.0);
	glRasterPos2f(200, 210.0);
	strcpy(st,"Wind Speed(km/hr):         ");
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18,st);
	if(progstep<0.0)
	{
		strcpy(st,"-");
		print_bitmap_string(GLUT_BITMAP_HELVETICA_12,st);
	}
	ftoa(1000*fabs(progstep),st,4);
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18, st);

	glColor4f(.7, 0.0, .7, 0.0);
	glRasterPos2f(200, 180.0);
	strcpy(st,"Wind Speed z(km/hr):      ");
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18,st);
	if(progstep*cos(wind_y/180*PI)<0.0)
	{
		strcpy(st,"-");
		print_bitmap_string(GLUT_BITMAP_HELVETICA_12,st);
	}
	ftoa(1000*fabs(progstep*cos(wind_y/180*PI)),st,4);
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18, st);

	glColor4f(.7, .7, .7, 0.0);
	glRasterPos2f(200, 150.0);
	strcpy(st,"Power (MW):                    ");
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18,st);
	ftoa(1000*fabs(torqueFact*wing_speed*wing_speed),st,4);
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18, st);

	//Construct Four Arrows
	Arrow(0.005,0.2,0.2,-.98,-0.78,0.2,1.0);
	Arrow(0.005,0.2,-0.2,-.98,-0.78,0.2,1.0);
	Arrow(0.005,-0.2,0.2,-.98,-0.78,0.2,1.0);
	Arrow(0.005,-0.2,-0.2,-.98,-0.78,0.2,1.0);

	//Construct Three Wings
	TriangularWing(0.055,0.05,0.4,0.025,30);
	TriangularWing(0.055,0.05,0.4,0.025,150);
	TriangularWing(0.055,0.05,0.4,0.025,270);

	//Ground below windmill
	resetIdentity();
	glRotatef(-10, 1.0, 0.0, 0.0);
	glRotatef(world_y+45, 0.0, 1.0, 0.0);
	for(int i=0;i<1000;++i)
	{
		glBegin (GL_LINES);
			glColor3f  (0,.1+.3*i/1000.0,0);
			glVertex3f  (-.5+i/1000.0,-.75, .5);
			glColor3f  (0,.7+.3*i/1000.0,0);
			glVertex3f  (-.5+i/1000.0,-.75, -.5);
		glEnd();
	}

	dashboard_arrow(0.005,.6,-.55,(progstep>0 ? .2 : -.2),.2,0.7);

	//Construct Circle around dashboard_arrow
	glLoadIdentity();
	glTranslatef(.6,-.55,0);
	glRotatef(floor_x/2,1,0,0);
	for(int i=0;i<1000;i++)
	{
		double th = (2*PI/1000)*i;
		glBegin (GL_LINES);
			glColor3f  (.6,.6,.6);
			glVertex3f  (.28*cos(th),0, .28*sin(th));
			glVertex3f  (.29*cos(th),0, .29*sin(th));
		glEnd();
	}

	glFlush();
	glutSwapBuffers();
}

int main(int argc, char* argv[])
{
	glutInit(&argc, argv); // Initialize GLUT and process user parameters
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);	// Request double buffered true color window with Z-buffer
	glutInitWindowSize(1000, 1000);	// Set Window Size
	glutInitWindowPosition(100,100);	//Specify Position of Window
	glutCreateWindow("WindMill");	// Create Window
	glEnable(GL_DEPTH_TEST);	// Enable Z-buffer depth test

	// Callback Functions
	glutDisplayFunc(drawWindMill);
	glutIdleFunc(rotate);
	glutSpecialFunc(specialKeys);
	glutKeyboardFunc(rotateWind);
	glutMouseFunc(mouseWheel);
	glutMainLoop();
}
<|endoftext|>


<commit_before>#include <bits/stdc++.h>
using namespace std;

// BIT to find number of elements <= x in range [l, r] supporting updates.
// all elements a[i] must be such that 1 <= a[i] <= N (compress if necessary!)

// maximum number of different elements
const int N = 2e5+5;

// block size
const int M = 2e3;

// input array
int a[N];

struct bit {
  int ft[N+5];
  void add(int i, int x) {
    for (; i <= N; i += i&-i) ft[i] += x;
  }
  int query(int i) {
    int ans = 0; for (; i > 0; i -= i&-i) ans += ft[i]; return ans;
  }
} block[(N+M-1)/M+5];

int getblock(int i) { return (i-1)/M+1; }
int blockright(int b) { return b*M; }
int blockleft(int b) { return blockright(b-1)+1; }

void update(int i, int x) {
  int b = getblock(i);
  block[b].add(a[i],-1);
  a[i] = x;
  block[b].add(a[i],1);
}

int query(int l, int r, int x) {
  if (r < l) return 0;
  int L = getblock(l), R = getblock(r), ans = 0;
  if (L == R) {
    for (int i = l; i <= r; i++) ans += (a[i] <= x);
    return ans;
  }
  for (int i = l; i <= blockright(L); i++) ans += (a[i] <= x);
  for (int b = L+1; b <= R-1; b++) ans += block[b].query(x);
  for (int i = blockleft(R); i <= r; i++) ans += (a[i] <= x);
  return ans;
}

int main() {
  return 0;
}
<commit_msg>Update range_countleq_query.cpp<commit_after>#include <bits/stdc++.h>
using namespace std;

// BIT to find number of elements <= x in range [l, r] supporting updates.
// all elements a[i] must be such that 1 <= a[i] <= N (but you can always
// compress the input numbers, if necessary!)

// maximum number of different elements
const int N = 2e5+5;

// block size
const int M = 2e3;

// input array
int a[N];

struct bit {
  int ft[N+5];
  void add(int i, int x) {
    for (; i <= N; i += i&-i) ft[i] += x;
  }
  int query(int i) {
    int ans = 0; for (; i > 0; i -= i&-i) ans += ft[i]; return ans;
  }
} block[(N+M-1)/M+5];

int getblock(int i) { return (i-1)/M+1; }
int blockright(int b) { return b*M; }
int blockleft(int b) { return blockright(b-1)+1; }

void update(int i, int x) {
  int b = getblock(i);
  block[b].add(a[i],-1);
  a[i] = x;
  block[b].add(a[i],1);
}

int query(int l, int r, int x) {
  if (r < l) return 0;
  int L = getblock(l), R = getblock(r), ans = 0;
  if (L == R) {
    for (int i = l; i <= r; i++) ans += (a[i] <= x);
    return ans;
  }
  for (int i = l; i <= blockright(L); i++) ans += (a[i] <= x);
  for (int b = L+1; b <= R-1; b++) ans += block[b].query(x);
  for (int i = blockleft(R); i <= r; i++) ans += (a[i] <= x);
  return ans;
}

int main() {
  return 0;
}
<|endoftext|>


<commit_before>#include <ctime>
#include <deque>
#include <GL/glut.h>
#include <unistd.h>
#include <iostream>
#include <algorithm>
#include "pipe.h"
using namespace std;

int main(int argc, char** argv){

    //Initializing variables
    title = "OpenGL Pipe";
    map_half_length = 14.0f;
    direction = 2;
    move_speed = 10;
    last_direction = 2;
    screenW = 1920;
    screenH = 1080;

    //Init glut
    glutInit(&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH);

    glutInitWindowSize(screenW, screenH);
    glutCreateWindow(title);
    glutFullScreen();

    //Set the glut functions
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(processKeys);
    glutSpecialFunc(processSpecial);

    red = rand()%255;
    green =rand()%255;
    blue =rand()%255;

    vector<float> point;
    int x = rand()%(int)(map_half_length*2);
    point.push_back((float)x);
    int y = rand()%(int)(map_half_length*2);
    point.push_back((float)y);
    int z = rand()%(int)(map_half_length*2);
    point.push_back((float)z);
    part_coords.push_back(point);
    map[x+1][y+1][z+1]=1;

    srand(time(NULL));
    constructMap();

    initGL();
    glutTimerFunc(move_speed, grow, 0);
    glutMainLoop();

    delete title;
    return 0;
}

void grow(int value){
    /*
        Directions:
        0 - up
        1 - down
        2 - right
        3 - left
        4 - out
        5 - in
    */
    UNUSED(value);

    if(part_coords.size() > 5000){
        reset();
    }

    //Get the last coordinates
    int last_part = part_coords.size() - 1;
    vector<float> new_head = part_coords[last_part];

    if(map[(int)new_head[0]+1][(int)new_head[1]+2][(int)new_head[2]+1]==0){
        directions.push_back(0);
    }
    if(map[(int)new_head[0]+1][(int)new_head[1]][(int)new_head[2]+1]==0){
        directions.push_back(1);
    }
    if(map[(int)new_head[0]+2][(int)new_head[1]+1][(int)new_head[2]+1]==0){
        directions.push_back(2);
    }
    if(map[(int)new_head[0]][(int)new_head[1]+1][(int)new_head[2]+1]==0){
        directions.push_back(3);
    }
    if(map[(int)new_head[0]+1][(int)new_head[1]+1][(int)new_head[2]+2]==0){
        directions.push_back(4);
    }
    if(map[(int)new_head[0]+1][(int)new_head[1]+1][(int)new_head[2]]==0){
        directions.push_back(5);
    }

    //Reset if no valid directions
    if(directions.empty()){
        reset();
        grow(1);
        return;
    }

    for(int n:directions){
        if(n == last_direction){
            for(int i=0; i<10; i++){
                directions.push_back(last_direction);
            }
        }
    }

    //Choose direction to move out of valid directions
    int direction = directions.at(rand()%directions.size());

    switch(direction){
        case 0:
            last_direction = 0;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1]+1;
            new_head[2] = new_head[2];
            break;
        case 1:
            last_direction = 1;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1]-1;
            new_head[2] = new_head[2];
            break;
        case 2:
            last_direction = 2;
            new_head[0] = new_head[0]+1;
            new_head[1] = new_head[1];
            new_head[2] = new_head[2];
            break;
         case 3:
            last_direction = 3;
            new_head[0] = new_head[0]-1;
            new_head[1] = new_head[1];
            new_head[2] = new_head[2];
            break;
        case 4:
            last_direction = 4;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1];
            new_head[2] = new_head[2]+1;
            break;
        case 5:
            last_direction = 5;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1];
            new_head[2] = new_head[2]-1;
            break;
    }

    map[(int)new_head[0]+1][(int)new_head[1]+1][(int)new_head[2]+1] = direction/2 + 1;

    //Push the new head onto the coords
    part_coords.push_back(new_head);

    directions.clear();
    glutTimerFunc(move_speed, grow, 0);
}

void reset(){
    cout << "RESETING "<< reset_val << endl;
    reset_val += 1;
    // keeps previous pipes on the screen
    part_coords2.insert( part_coords2.end(), part_coords.begin(), part_coords.end() );
    for (int i=0; i<HEIGHT+2; i++) {
      for (int j=0; j<WIDTH+2; j++) {
        for (int k=0; k<DEPTH+2; k++) {
          map2[i][j][k] += map[i][j][k];
        }
      }
    }

    part_coords.clear();
    constructMap();

    // glLightfv(GL_LIGHT1, GL_DIFFUSE, green);

    std::vector<float> point;
    int x = rand()%(int)(map_half_length*2);
    point.push_back((float)x);
    int y = rand()%(int)(map_half_length*2);
    point.push_back((float)y);
    int z = rand()%(int)(map_half_length*2);
    point.push_back((float)z);
    map[x+1][y+1][z+1]=1;

    part_coords.push_back(point);

    red = rand()%255;
    green =rand()%255;
    blue =rand()%255;

    //glutTimerFunc(move_speed, grow, 0);
}

void constructMap(){
    /*
        Constructs the map with walls being 1 and all other space 0
    */
    for(int row=0; row<HEIGHT+2; row++){
        for(int col=0; col<WIDTH+2; col++){
            for(int z=0; z<DEPTH+2; z++){
                if(row==0 || col==0 || z==0){
                    map[row][col][z] = 1;
                }
                else if(row==HEIGHT+1 || col==WIDTH+1 || z==DEPTH+1){
                    map[row][col][z] = 1;
                }
                else{
                    map[row][col][z] = 0;
                }
            }
        }
    }
}

void processKeys(unsigned char key, int x, int y){
    switch(key){
        case 27:
            exit(0);
            break;
        default:
            return;
    }
}
void processSpecial(int key, int x, int y){
    cout<<key<<endl;
}

void initGL(){
    glEnable(GL_DEPTH_TEST);
    // glEnable(GL_COLOR_MATERIAL);
    // glEnable(GL_LIGHTING); //Enable lighting
    // glEnable(GL_LIGHT0); //Enable light #0
    // glEnable(GL_LIGHT1); //Enable light #1
    // glEnable(GL_NORMALIZE); //Automatically normalize normals
    glMatrixMode(GL_PROJECTION);
    glDepthFunc(GL_LEQUAL);
    glShadeModel(GL_SMOOTH);
    //gluPerspective(75.0f, 1, 0.0f, 35.0f);
    gluPerspective(75.0f, (float)screenW/screenH, 0.0f, 35.0f);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

void reshape(GLsizei width, GLsizei height){
    screenW = width;
    screenH = height;
    glutReshapeWindow(width, height);
}

void display(){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);

    /*UNCOMMENT NEXT THREE LINE FOR MELLOW PARTY MODE*/
    /*red = rand()%255;
    green =rand()%255;
    blue =rand()%255;*/

    for(unsigned int a = 0; a < part_coords.size(); a++){
        glLoadIdentity();

        /*UNCOMMENT NEXT THREE LINE FOR FULL PARTY MODE*/
        // red = rand()%255;
        // green =rand()%255;
        // blue =rand()%255;

        glColor3ub(red, green, blue);

        x = part_coords[a][0];
        y = part_coords[a][1];
        z = part_coords[a][2];

        glTranslatef(x-(WIDTH+1)/2, -y+(HEIGHT+1)/2, z-2*DEPTH);

        //glutSolidSphere(12.0, 50, 50);
        if(map[x+1][y+1][z+1] == 2){
            glRotatef(90, 0.0f, 1.0f, 0.0f);
        }
        if(map[x+1][y+1][z+1] == 1){
            glRotatef(90, 1.0f, 0.0f, 0.0f);
        }

        glBegin(GL_QUAD_STRIP);
            GLfloat COSan_3 = 0.0;
            GLfloat SINan_3 = 0.0;
            for(GLfloat an = 0.0; an <= 2.0 * M_PI; an += M_PI / 12.0) {
                        glNormal3f((COSan_3 = cos(an)/3.0), (SINan_3 = sin(an)/3.0), 2.0);
                        glVertex3f(COSan_3, SINan_3, 0.5f);
                        glVertex3f(COSan_3, SINan_3, -0.5f);
        }
        glEnd();
    }
    for(unsigned int a = 0; a < part_coords2.size(); a++){
        glLoadIdentity();

        x = part_coords2[a][0];
        y = part_coords2[a][1];
        z = part_coords2[a][2];

        glTranslatef(x-(WIDTH+1)/2, -y+(HEIGHT+1)/2, z-2*DEPTH);

        //glutSolidSphere(12.0, 50, 50);
        if(map2[x+1][y+1][z+1] == 2){
            glRotatef(90, 0.0f, 1.0f, 0.0f);
        }
        if(map2[x+1][y+1][z+1] == 1){
            glRotatef(90, 1.0f, 0.0f, 0.0f);
        }

        glBegin(GL_QUAD_STRIP);
            GLfloat COSan_3 = 0.0;
            GLfloat SINan_3 = 0.0;
            for(GLfloat an = 0.0; an <= 2.0 * M_PI; an += M_PI / 12.0) {
                        glNormal3f((COSan_3 = cos(an)/3.0), (SINan_3 = sin(an)/3.0), 2.0);
                        glVertex3f(COSan_3, SINan_3, 0.5f);
                        glVertex3f(COSan_3, SINan_3, -0.5f);
        }
        glEnd();
    }
    glutSwapBuffers();
}
<commit_msg>fix: rotation problem<commit_after>#include <ctime>
#include <deque>
#include <GL/glut.h>
#include <unistd.h>
#include <iostream>
#include <algorithm>
#include "pipe.h"
using namespace std;

int main(int argc, char** argv){

    //Initializing variables
    title = "OpenGL Pipe";
    map_half_length = 14.0f;
    direction = 2;
    move_speed = 25;
    last_direction = 2;
    screenW = 1920;
    screenH = 1080;

    //Init glut
    glutInit(&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH);

    glutInitWindowSize(screenW, screenH);
    glutCreateWindow(title);
    glutFullScreen();

    //Set the glut functions
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(processKeys);
    glutSpecialFunc(processSpecial);

    red = rand()%255;
    green =rand()%255;
    blue =rand()%255;

    vector<float> point;
    int x = rand()%(int)(map_half_length*2);
    point.push_back((float)x);
    int y = rand()%(int)(map_half_length*2);
    point.push_back((float)y);
    int z = rand()%(int)(map_half_length*2);
    point.push_back((float)z);
    part_coords.push_back(point);
    map[x+1][y+1][z+1]=1;

    srand(time(NULL));
    constructMap();

    initGL();
    glutTimerFunc(move_speed, grow, 0);
    glutMainLoop();

    delete title;
    return 0;
}

void grow(int value){
    /*
        Directions:
        0 - up
        1 - down
        2 - right
        3 - left
        4 - out
        5 - in
    */
    UNUSED(value);

    if(part_coords.size() > 200){
        reset();
    }

    //Get the last coordinates
    int last_part = part_coords.size() - 1;
    vector<float> new_head = part_coords[last_part];

    if(map[(int)new_head[0]+1][(int)new_head[1]+2][(int)new_head[2]+1]==0){
        directions.push_back(0);
    }
    if(map[(int)new_head[0]+1][(int)new_head[1]][(int)new_head[2]+1]==0){
        directions.push_back(1);
    }
    if(map[(int)new_head[0]+2][(int)new_head[1]+1][(int)new_head[2]+1]==0){
        directions.push_back(2);
    }
    if(map[(int)new_head[0]][(int)new_head[1]+1][(int)new_head[2]+1]==0){
        directions.push_back(3);
    }
    if(map[(int)new_head[0]+1][(int)new_head[1]+1][(int)new_head[2]+2]==0){
        directions.push_back(4);
    }
    if(map[(int)new_head[0]+1][(int)new_head[1]+1][(int)new_head[2]]==0){
        directions.push_back(5);
    }

    //Reset if no valid directions
    if(directions.empty()){
        reset();
        grow(1);
        return;
    }

    for(int n:directions){
        if(n == last_direction){
            for(int i=0; i<10; i++){
                directions.push_back(last_direction);
            }
        }
    }

    //Choose direction to move out of valid directions
    int direction = directions.at(rand()%directions.size());

    switch(direction){
        case 0:
            last_direction = 0;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1]+1;
            new_head[2] = new_head[2];
            break;
        case 1:
            last_direction = 1;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1]-1;
            new_head[2] = new_head[2];
            break;
        case 2:
            last_direction = 2;
            new_head[0] = new_head[0]+1;
            new_head[1] = new_head[1];
            new_head[2] = new_head[2];
            break;
         case 3:
            last_direction = 3;
            new_head[0] = new_head[0]-1;
            new_head[1] = new_head[1];
            new_head[2] = new_head[2];
            break;
        case 4:
            last_direction = 4;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1];
            new_head[2] = new_head[2]+1;
            break;
        case 5:
            last_direction = 5;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1];
            new_head[2] = new_head[2]-1;
            break;
    }

    map[(int)new_head[0]+1][(int)new_head[1]+1][(int)new_head[2]+1] = direction/2 + 1;

    //Push the new head onto the coords
    part_coords.push_back(new_head);

    directions.clear();
    glutTimerFunc(move_speed, grow, 0);
}

void reset(){
    cout << "RESETING "<< reset_val << endl;
    reset_val += 1;
    // keeps previous pipes on the screen
    part_coords2.insert( part_coords2.end(), part_coords.begin(), part_coords.end() );
    for (int i=0; i<WIDTH+2; i++) {
      for (int j=0; j<HEIGHT+2; j++) {
        for (int k=0; k<DEPTH+2; k++) {
          map2[i][j][k] += map[i][j][k];
        }
      }
    }

    part_coords.clear();
    constructMap();

    // glLightfv(GL_LIGHT1, GL_DIFFUSE, green);

    std::vector<float> point;
    int x = rand()%(int)(map_half_length*2);
    point.push_back((float)x);
    int y = rand()%(int)(map_half_length*2);
    point.push_back((float)y);
    int z = rand()%(int)(map_half_length*2);
    point.push_back((float)z);
    map[x+1][y+1][z+1]=1;

    part_coords.push_back(point);

    red = rand()%255;
    green =rand()%255;
    blue =rand()%255;

    //glutTimerFunc(move_speed, grow, 0);
}

void constructMap(){
    /*
        Constructs the map with walls being 1 and all other space 0
    */
    for(int row=0; row<HEIGHT+2; row++){
        for(int col=0; col<WIDTH+2; col++){
            for(int z=0; z<DEPTH+2; z++){
                if(row==0 || col==0 || z==0){
                    map[row][col][z] = 1;
                }
                else if(row==HEIGHT+1 || col==WIDTH+1 || z==DEPTH+1){
                    map[row][col][z] = 1;
                }
                else{
                    map[row][col][z] = 0;
                }
            }
        }
    }
}

void processKeys(unsigned char key, int x, int y){
    switch(key){
        case 27:
            exit(0);
            break;
        default:
            return;
    }
}
void processSpecial(int key, int x, int y){
    cout<<key<<endl;
}

void initGL(){
    glEnable(GL_DEPTH_TEST);
    // glEnable(GL_COLOR_MATERIAL);
    // glEnable(GL_LIGHTING); //Enable lighting
    // glEnable(GL_LIGHT0); //Enable light #0
    // glEnable(GL_LIGHT1); //Enable light #1
    // glEnable(GL_NORMALIZE); //Automatically normalize normals
    glMatrixMode(GL_PROJECTION);
    glDepthFunc(GL_LEQUAL);
    glShadeModel(GL_SMOOTH);
    //gluPerspective(75.0f, 1, 0.0f, 35.0f);
    gluPerspective(75.0f, (float)screenW/screenH, 0.0f, 35.0f);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

void reshape(GLsizei width, GLsizei height){
    screenW = width;
    screenH = height;
    glutReshapeWindow(width, height);
}

void display(){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);

    /*UNCOMMENT NEXT THREE LINE FOR MELLOW PARTY MODE*/
    /*red = rand()%255;
    green =rand()%255;
    blue =rand()%255;*/

    for(unsigned int a = 0; a < part_coords.size(); a++){
        glLoadIdentity();

        /*UNCOMMENT NEXT THREE LINE FOR FULL PARTY MODE*/
        // red = rand()%255;
        // green =rand()%255;
        // blue =rand()%255;

        glColor3ub(red, green, blue);

        x = part_coords[a][0];
        y = part_coords[a][1];
        z = part_coords[a][2];

        glTranslatef(x-(WIDTH+1)/2, -y+(HEIGHT+1)/2, z-2*DEPTH);

        //glutSolidSphere(12.0, 50, 50);
        if(map[x+1][y+1][z+1] == 2){
            glRotatef(90, 0.0f, 1.0f, 0.0f);
        }
        if(map[x+1][y+1][z+1] == 1){
            glRotatef(90, 1.0f, 0.0f, 0.0f);
        }

        glBegin(GL_QUAD_STRIP);
            GLfloat COSan_3 = 0.0;
            GLfloat SINan_3 = 0.0;
            for(GLfloat an = 0.0; an <= 2.0 * M_PI; an += M_PI / 12.0) {
                        glNormal3f((COSan_3 = cos(an)/3.0), (SINan_3 = sin(an)/3.0), 2.0);
                        glVertex3f(COSan_3, SINan_3, 0.5f);
                        glVertex3f(COSan_3, SINan_3, -0.5f);
        }
        glEnd();
    }
    for(unsigned int a = 0; a < part_coords2.size(); a++){
        glLoadIdentity();

        x = part_coords2[a][0];
        y = part_coords2[a][1];
        z = part_coords2[a][2];

        glTranslatef(x-(WIDTH+1)/2, -y+(HEIGHT+1)/2, z-2*DEPTH);

        //glutSolidSphere(12.0, 50, 50);
        if(map2[x+1][y+1][z+1] == 2){
            glRotatef(90, 0.0f, 1.0f, 0.0f);
        }
        if(map2[x+1][y+1][z+1] == 1){
            glRotatef(90, 1.0f, 0.0f, 0.0f);
        }

        glBegin(GL_QUAD_STRIP);
            GLfloat COSan_3 = 0.0;
            GLfloat SINan_3 = 0.0;
            for(GLfloat an = 0.0; an <= 2.0 * M_PI; an += M_PI / 12.0) {
                        glNormal3f((COSan_3 = cos(an)/3.0), (SINan_3 = sin(an)/3.0), 2.0);
                        glVertex3f(COSan_3, SINan_3, 0.5f);
                        glVertex3f(COSan_3, SINan_3, -0.5f);
        }
        glEnd();
    }
    glutSwapBuffers();
}
<|endoftext|>


<commit_before>/*
 *   Copyright (c) 2006, Mathieu Champlon
 *   All rights reserved.
 *
 *   Redistribution  and use  in source  and binary  forms, with  or without
 *   modification, are permitted provided  that the following conditions are
 *   met :
 *
 *   . Redistributions  of  source  code  must  retain  the  above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   . Redistributions in  binary form  must reproduce  the above  copyright
 *     notice, this list of conditions  and the following disclaimer in  the
 *     documentation and/or other materials provided with the distribution.
 *
 *   . Neither  the name  of  the  copyright  holders  nor the names  of the
 *     contributors may be used to endorse  or promote products derived from
 *     this software without specific prior written permission.
 *
 *   THIS SOFTWARE  IS  PROVIDED  BY THE  COPYRIGHT HOLDERS  AND CONTRIBUTORS
 *   ``AS IS''  AND ANY  EXPRESS OR  IMPLIED WARRANTIES,  INCLUDING,  BUT NOT
 *   LIMITED TO, THE IMPLIED  WARRANTIES  OF MERCHANTABILITY AND  FITNESS FOR
 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE THE COPYRIGHT
 *   OWNERS OR CONTRIBUTORS  BE LIABLE FOR ANY  DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL   DAMAGES  (INCLUDING,  BUT  NOT
 *   LIMITED TO,  PROCUREMENT OF SUBSTITUTE  GOODS OR SERVICES;  LOSS OF USE,
 *   DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED  AND ON  ANY
 *   THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT,  STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY  WAY  OUT OF  THE USE
 *   OF THIS SOFTWARE, EVEN  IF  ADVISED OF  THE POSSIBILITY  OF SUCH DAMAGE.
 */

#ifndef xeumeuleu_translate_hpp
#define xeumeuleu_translate_hpp

#define XEUMEULEU_TRANSCODER_ENCODING "utf-8"

#include <xeumeuleu/bridges/xerces/detail/xerces.hpp>
#include <string>

namespace xml
{
// =============================================================================
/** @class  translate
    @brief  String translation helpers
*/
// Created: MAT 2006-01-04
// =============================================================================
class translate
{
public:
    //! @name Constructors/Destructor
    //@{
    explicit translate( const std::string& str )
        : transcoder_( create() )
        , s_         ( transcode( str ) )
        , ch_        ( &s_[0] )
    {}
    explicit translate( const XMLCh* const ch )
        : transcoder_( create() )
        , ch_        ( ch )
    {}
    translate( const translate& rhs )
        : transcoder_( create() )
        , s_         ( rhs.s_ )
        , ch_        ( s_.empty() ? rhs.ch_ : &s_[0] )
    {}
    //@}

    //! @name Operators
    //@{
    operator const XMLCh*() const
    {
        return ch_;
    }
    operator std::string() const
    {
        if( ! ch_ )
            return std::string();
        XMLSize_t written = 0;
        const XMLSize_t size = XERCES_CPP_NAMESPACE::XMLString::stringLen( ch_ );
        std::vector< XMLByte > s( size * sizeof( XMLCh ) + 4 );
        XMLSize_t done = 0;
        while( done < size )
        {
            Count_t read = 0;
            written += transcoder_->transcodeTo(
                ch_ + done, size - done,
                &s[written], s.size() - written,
                read, XERCES_CPP_NAMESPACE::XMLTranscoder::UnRep_RepChar );
            if( read == 0 )
                throw xml::exception( "failed to transcode string" );
            done += read;
            if( s.size() - written < size - done )
                s.resize( s.size() * 2 );
        }
        s.resize( written + 4 );
        return std::string( reinterpret_cast< const char* >( &s[0] ), written );
    }

    bool operator==( const XMLCh* const ch ) const
    {
        return XERCES_CPP_NAMESPACE::XMLString::equals( ch, ch_ );
    }
    bool operator==( const std::string& str ) const
    {
        return translate( str ) == ch_;
    }
    bool operator!=( const XMLCh* const ch ) const
    {
        return ! XERCES_CPP_NAMESPACE::XMLString::equals( ch, ch_ );
    }
    bool operator!=( const std::string& str ) const
    {
        return translate( str ) != ch_;
    }
    //@}

private:
    //! @name Helpers
    //@{
    XERCES_CPP_NAMESPACE::XMLTranscoder* create() const
    {
        XERCES_CPP_NAMESPACE::XMLTransService::Codes result;
        XERCES_CPP_NAMESPACE::Janitor< XERCES_CPP_NAMESPACE::XMLTranscoder > transcoder
            = XERCES_CPP_NAMESPACE::XMLPlatformUtils::fgTransService->makeNewTranscoderFor(
                XEUMEULEU_TRANSCODER_ENCODING, result, 16 * 1024 );
        if( result != XERCES_CPP_NAMESPACE::XMLTransService::Ok )
            throw xml::exception( std::string( "unable to create transcoder for " ) + XEUMEULEU_TRANSCODER_ENCODING );
        return transcoder.release();
    }
    std::vector< XMLCh > transcode( const std::string& str ) const
    {
        const XMLByte* in = reinterpret_cast< const XMLByte* >( str.c_str() );
        const XMLSize_t length = str.length();
        XMLSize_t written = 0;
        std::vector< XMLCh > s( length + 1 );
        std::vector< unsigned char > sizes;
        XMLSize_t done = 0;
        while( done < length )
        {
            sizes.resize( s.size() - written );
            Count_t read = 0;
            written += transcoder_->transcodeFrom(
                in + done, length - done,
                &s[0] + written, s.size() - written,
                read, &sizes[0] );
            if( read == 0 )
                throw xml::exception( "failed to transcode string" );
            done += read;
            if( ( s.size() - written ) * sizeof( XMLCh ) < length - done )
                s.resize( 2 * s.size() );
        }
        s.resize( written + 1 );
        return s;
    }
    //@}

private:
    //! @name Copy/Assignment
    //@{
    translate& operator=( const translate& ); //!< Assignment operator
    //@}

private:
    //! @name Member data
    //@{
    XERCES_CPP_NAMESPACE::Janitor< XERCES_CPP_NAMESPACE::XMLTranscoder > transcoder_;
    const std::vector< XMLCh > s_;
    const XMLCh* const ch_;
    //@}
};

inline bool operator==( const XMLCh* const ch, const translate& tr )
{
    return tr == ch;
}
inline bool operator==( const std::string& str, const translate& tr )
{
    return tr == str;
}

inline bool operator!=( const XMLCh* const ch, const translate& tr )
{
    return tr != ch;
}
inline bool operator!=( const std::string& str, const translate& tr )
{
    return tr != str;
}

inline std::string operator+( const translate& tr, const std::string& str )
{
    return std::string( tr ) + str;
}
inline std::string operator+( const std::string& str, const translate& tr )
{
    return str + std::string( tr );
}

}

#endif // xeumeuleu_translate_hpp
<commit_msg>Added missing include<commit_after>/*
 *   Copyright (c) 2006, Mathieu Champlon
 *   All rights reserved.
 *
 *   Redistribution  and use  in source  and binary  forms, with  or without
 *   modification, are permitted provided  that the following conditions are
 *   met :
 *
 *   . Redistributions  of  source  code  must  retain  the  above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   . Redistributions in  binary form  must reproduce  the above  copyright
 *     notice, this list of conditions  and the following disclaimer in  the
 *     documentation and/or other materials provided with the distribution.
 *
 *   . Neither  the name  of  the  copyright  holders  nor the names  of the
 *     contributors may be used to endorse  or promote products derived from
 *     this software without specific prior written permission.
 *
 *   THIS SOFTWARE  IS  PROVIDED  BY THE  COPYRIGHT HOLDERS  AND CONTRIBUTORS
 *   ``AS IS''  AND ANY  EXPRESS OR  IMPLIED WARRANTIES,  INCLUDING,  BUT NOT
 *   LIMITED TO, THE IMPLIED  WARRANTIES  OF MERCHANTABILITY AND  FITNESS FOR
 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE THE COPYRIGHT
 *   OWNERS OR CONTRIBUTORS  BE LIABLE FOR ANY  DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL   DAMAGES  (INCLUDING,  BUT  NOT
 *   LIMITED TO,  PROCUREMENT OF SUBSTITUTE  GOODS OR SERVICES;  LOSS OF USE,
 *   DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED  AND ON  ANY
 *   THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT,  STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY  WAY  OUT OF  THE USE
 *   OF THIS SOFTWARE, EVEN  IF  ADVISED OF  THE POSSIBILITY  OF SUCH DAMAGE.
 */

#ifndef xeumeuleu_translate_hpp
#define xeumeuleu_translate_hpp

#define XEUMEULEU_TRANSCODER_ENCODING "utf-8"

#include <xeumeuleu/bridges/xerces/detail/xerces.hpp>
#include <vector>
#include <string>

namespace xml
{
// =============================================================================
/** @class  translate
    @brief  String translation helpers
*/
// Created: MAT 2006-01-04
// =============================================================================
class translate
{
public:
    //! @name Constructors/Destructor
    //@{
    explicit translate( const std::string& str )
        : transcoder_( create() )
        , s_         ( transcode( str ) )
        , ch_        ( &s_[0] )
    {}
    explicit translate( const XMLCh* const ch )
        : transcoder_( create() )
        , ch_        ( ch )
    {}
    translate( const translate& rhs )
        : transcoder_( create() )
        , s_         ( rhs.s_ )
        , ch_        ( s_.empty() ? rhs.ch_ : &s_[0] )
    {}
    //@}

    //! @name Operators
    //@{
    operator const XMLCh*() const
    {
        return ch_;
    }
    operator std::string() const
    {
        if( ! ch_ )
            return std::string();
        XMLSize_t written = 0;
        const XMLSize_t size = XERCES_CPP_NAMESPACE::XMLString::stringLen( ch_ );
        std::vector< XMLByte > s( size * sizeof( XMLCh ) + 4 );
        XMLSize_t done = 0;
        while( done < size )
        {
            Count_t read = 0;
            written += transcoder_->transcodeTo(
                ch_ + done, size - done,
                &s[written], s.size() - written,
                read, XERCES_CPP_NAMESPACE::XMLTranscoder::UnRep_RepChar );
            if( read == 0 )
                throw xml::exception( "failed to transcode string" );
            done += read;
            if( s.size() - written < size - done )
                s.resize( s.size() * 2 );
        }
        s.resize( written + 4 );
        return std::string( reinterpret_cast< const char* >( &s[0] ), written );
    }

    bool operator==( const XMLCh* const ch ) const
    {
        return XERCES_CPP_NAMESPACE::XMLString::equals( ch, ch_ );
    }
    bool operator==( const std::string& str ) const
    {
        return translate( str ) == ch_;
    }
    bool operator!=( const XMLCh* const ch ) const
    {
        return ! XERCES_CPP_NAMESPACE::XMLString::equals( ch, ch_ );
    }
    bool operator!=( const std::string& str ) const
    {
        return translate( str ) != ch_;
    }
    //@}

private:
    //! @name Helpers
    //@{
    XERCES_CPP_NAMESPACE::XMLTranscoder* create() const
    {
        XERCES_CPP_NAMESPACE::XMLTransService::Codes result;
        XERCES_CPP_NAMESPACE::Janitor< XERCES_CPP_NAMESPACE::XMLTranscoder > transcoder
            = XERCES_CPP_NAMESPACE::XMLPlatformUtils::fgTransService->makeNewTranscoderFor(
                XEUMEULEU_TRANSCODER_ENCODING, result, 16 * 1024 );
        if( result != XERCES_CPP_NAMESPACE::XMLTransService::Ok )
            throw xml::exception( std::string( "unable to create transcoder for " ) + XEUMEULEU_TRANSCODER_ENCODING );
        return transcoder.release();
    }
    std::vector< XMLCh > transcode( const std::string& str ) const
    {
        const XMLByte* in = reinterpret_cast< const XMLByte* >( str.c_str() );
        const XMLSize_t length = str.length();
        XMLSize_t written = 0;
        std::vector< XMLCh > s( length + 1 );
        std::vector< unsigned char > sizes;
        XMLSize_t done = 0;
        while( done < length )
        {
            sizes.resize( s.size() - written );
            Count_t read = 0;
            written += transcoder_->transcodeFrom(
                in + done, length - done,
                &s[0] + written, s.size() - written,
                read, &sizes[0] );
            if( read == 0 )
                throw xml::exception( "failed to transcode string" );
            done += read;
            if( ( s.size() - written ) * sizeof( XMLCh ) < length - done )
                s.resize( 2 * s.size() );
        }
        s.resize( written + 1 );
        return s;
    }
    //@}

private:
    //! @name Copy/Assignment
    //@{
    translate& operator=( const translate& ); //!< Assignment operator
    //@}

private:
    //! @name Member data
    //@{
    XERCES_CPP_NAMESPACE::Janitor< XERCES_CPP_NAMESPACE::XMLTranscoder > transcoder_;
    const std::vector< XMLCh > s_;
    const XMLCh* const ch_;
    //@}
};

inline bool operator==( const XMLCh* const ch, const translate& tr )
{
    return tr == ch;
}
inline bool operator==( const std::string& str, const translate& tr )
{
    return tr == str;
}

inline bool operator!=( const XMLCh* const ch, const translate& tr )
{
    return tr != ch;
}
inline bool operator!=( const std::string& str, const translate& tr )
{
    return tr != str;
}

inline std::string operator+( const translate& tr, const std::string& str )
{
    return std::string( tr ) + str;
}
inline std::string operator+( const std::string& str, const translate& tr )
{
    return str + std::string( tr );
}

}

#endif // xeumeuleu_translate_hpp
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Contains the definition of a few helper functions used for generating sync
// URLs.

#include "sync/engine/net/url_translator.h"

#include "base/basictypes.h"
#include "base/port.h"
#include "net/base/escape.h"

using std::string;

namespace browser_sync {

namespace {
// Parameters that the server understands. (here, a-Z)
const char kParameterAuthToken[] = "auth";
const char kParameterClientID[] = "client_id";
}

// Convenience wrappers around CgiEscapePath().
string CgiEscapeString(const char* src) {
  return CgiEscapeString(string(src));
}

string CgiEscapeString(const string& src) {
  return net::EscapeUrlEncodedData(src, true);
}

// This method appends the query string to the sync server path.
string MakeSyncServerPath(const string& path, const string& query_string) {
  string result = path;
  result.append("?");
  result.append(query_string);
  return result;
}

string MakeSyncQueryString(const string& client_id) {
  string query;
  query += kParameterClientID;
  query += "=" + CgiEscapeString(client_id);
  return query;
}

}  // namespace browser_sync
<commit_msg>Add 'client' parameter to sync requests<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Contains the definition of a few helper functions used for generating sync
// URLs.

#include "sync/engine/net/url_translator.h"

#include "base/basictypes.h"
#include "base/port.h"
#include "net/base/escape.h"

using std::string;

namespace browser_sync {

namespace {
// Parameters that the server understands. (here, a-Z)
const char kParameterClient[] = "client";
const char kParameterClientID[] = "client_id";

#if defined(GOOGLE_CHROME_BUILD)
const char kClientName[] = "Google Chrome";
#else
const char kClientName[] = "Chromium";
#endif  // defined(GOOGLE_CHROME_BUILD)
}

// Convenience wrappers around CgiEscapePath().
string CgiEscapeString(const char* src) {
  return CgiEscapeString(string(src));
}

string CgiEscapeString(const string& src) {
  return net::EscapeUrlEncodedData(src, true);
}

// This method appends the query string to the sync server path.
string MakeSyncServerPath(const string& path, const string& query_string) {
  string result = path;
  result.append("?");
  result.append(query_string);
  return result;
}

string MakeSyncQueryString(const string& client_id) {
  string query;
  query += kParameterClient;
  query += "=" + CgiEscapeString(kClientName);
  query += "&";
  query += kParameterClientID;
  query += "=" + CgiEscapeString(client_id);
  return query;
}

}  // namespace browser_sync
<|endoftext|>


<commit_before>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post
    Copyright (C) 2017 Axel Waggershauser

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "decompressors/AbstractLJpegDecompressor.h"
#include "common/Common.h"                // for uint32, make_unique, uchar8
#include "common/Point.h"                 // for iPoint2D
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/HuffmanTable.h"   // for HuffmanTable
#include "io/ByteStream.h"                // for ByteStream
#include <array>                          // for array
#include <memory>                         // for unique_ptr, allocator
#include <utility>                        // for move
#include <vector>                         // for vector

namespace rawspeed {

void AbstractLJpegDecompressor::decode() {
  if (getNextMarker(false) != M_SOI)
    ThrowRDE("Image did not start with SOI. Probably not an LJPEG");

  struct FoundMarkers {
    bool DHT = false;
    bool SOF = false;
    bool SOS = false;
  } FoundMarkers;

  JpegMarker m;
  do {
    m = getNextMarker(true);

    switch (m) {
    case M_DHT:
      if (FoundMarkers.SOS)
        ThrowRDE("Found second DHT marker after SOS");
      // there can be more than one DHT markers.
      // FIXME: do we really want to reparse and use the last one?
      parseDHT();
      FoundMarkers.DHT = true;
      break;
    case M_SOF3:
      if (FoundMarkers.SOS)
        ThrowRDE("Found second SOF marker after SOS");
      if (FoundMarkers.SOF)
        ThrowRDE("Found second SOF marker");
      // SOF is not required to be after DHT
      parseSOF(&frame);
      FoundMarkers.SOF = true;
      break;
    case M_SOS:
      if (FoundMarkers.SOS)
        ThrowRDE("Found second SOS marker");
      if (!FoundMarkers.DHT)
        ThrowRDE("Did not find DHT marker before SOS.");
      if (!FoundMarkers.SOF)
        ThrowRDE("Did not find SOF marker before SOS.");
      parseSOS();
      FoundMarkers.SOS = true;
      break;
    case M_DQT:
      ThrowRDE("Not a valid RAW file.");
    default: // Just let it skip to next marker
      break;
    }
  } while (m != M_EOI);

  if (!FoundMarkers.SOS)
    ThrowRDE("Did not find SOS marker.");
}

void AbstractLJpegDecompressor::parseSOF(SOFInfo* sof) {
  uint32 headerLength = input.getU16();
  sof->prec = input.getByte();
  sof->h = input.getU16();
  sof->w = input.getU16();
  sof->cps = input.getByte();

  if (sof->h == 0 || sof->w == 0)
    ThrowRDE("Frame width or height set to zero");

  if (sof->prec > 16)
    ThrowRDE("More than 16 bits per channel is not supported.");

  if (sof->cps > 4 || sof->cps < 1)
    ThrowRDE("Only from 1 to 4 components are supported.");

  if (headerLength != 8 + sof->cps*3)
    ThrowRDE("Header size mismatch.");

  for (uint32 i = 0; i < sof->cps; i++) {
    sof->compInfo[i].componentId = input.getByte();
    uint32 subs = input.getByte();
    frame.compInfo[i].superV = subs & 0xf;
    frame.compInfo[i].superH = subs >> 4;
    uint32 Tq = input.getByte();
    if (Tq != 0)
      ThrowRDE("Quantized components not supported.");
  }
  sof->initialized = true;

  mRaw->metadata.subsampling.x = sof->compInfo[0].superH;
  mRaw->metadata.subsampling.y = sof->compInfo[0].superV;
}

void AbstractLJpegDecompressor::parseSOS() {
  if (!frame.initialized)
    ThrowRDE("Frame not yet initialized (SOF Marker not parsed)");

  uint32 headerLength = input.getU16();
  if (headerLength != 3 + frame.cps * 2 + 3)
    ThrowRDE("Invalid SOS header length.");

  uint32 soscps = input.getByte();
  if (frame.cps != soscps)
    ThrowRDE("Component number mismatch.");

  for (uint32 i = 0; i < frame.cps; i++) {
    uint32 cs = input.getByte();
    uint32 td = input.getByte() >> 4;

    if (td > 3 || !huff[td])
      ThrowRDE("Invalid Huffman table selection.");

    int ciIndex = -1;
    for (uint32 j = 0; j < frame.cps; ++j) {
      if (frame.compInfo[j].componentId == cs)
        ciIndex = j;
    }

    if (ciIndex == -1)
      ThrowRDE("Invalid Component Selector");

    frame.compInfo[ciIndex].dcTblNo = td;
  }

  // Get predictor, see table H.1 from the JPEG spec
  predictorMode = input.getByte();
  // The spec says predictoreMode is in [0..7], but Hasselblad uses '8'.
  if (predictorMode > 8)
    ThrowRDE("Invalid predictor mode.");

  input.skipBytes(1);         // Se + Ah Not used in LJPEG
  Pt = input.getByte() & 0xf; // Point Transform

  decodeScan();
}

void AbstractLJpegDecompressor::parseDHT() {
  ByteStream dht(input.getStream(input.peekU16()));
  dht.skipBytes(2); // headerLength

  while (dht.getRemainSize() > 0) {
    uint32 b = dht.getByte();

    uint32 htClass = b >> 4;
    if (htClass != 0)
      ThrowRDE("Unsupported Table class.");

    uint32 htIndex = b & 0xf;
    if (htIndex >= huff.size())
      ThrowRDE("Invalid huffman table destination id.");

    if (huff[htIndex] != nullptr)
      ThrowRDE("Duplicate table definition");

    // copy 16 bytes from input stream to number of codes per length table
    uint32 nCodes = ht_.setNCodesPerLength(dht.getBuffer(16));

    // spec says 16 different codes is max but Hasselblad violates that -> 17
    if (nCodes > 17)
      ThrowRDE("Invalid DHT table.");

    // copy nCodes bytes from input stream to code values table
    ht_.setCodeValues(dht.getBuffer(nCodes));

    // see if we already have a HuffmanTable with the same codes
    for (const auto& i : huffmanTableStore)
      if (*i == ht_)
        huff[htIndex] = i.get();

    if (!huff[htIndex]) {
      // setup new ht_ and put it into the store
      auto dHT = std::make_unique<HuffmanTable>(ht_);
      dHT->setup(fullDecodeHT, fixDng16Bug);
      huff[htIndex] = dHT.get();
      huffmanTableStore.emplace_back(std::move(dHT));
    }
  }
}

JpegMarker AbstractLJpegDecompressor::getNextMarker(bool allowskip) {
  uchar8 c0;
  uchar8 c1 = input.getByte();
  do {
    c0 = c1;
    c1 = input.getByte();
  } while (allowskip && !(c0 == 0xFF && c1 != 0 && c1 != 0xFF));

  if (!(c0 == 0xFF && c1 != 0 && c1 != 0xFF))
    ThrowRDE("(Noskip) Expected marker not found. Propably corrupt file.");

  return static_cast<JpegMarker>(c1);
}

} // namespace rawspeed
<commit_msg>AbstractLJpegDecompressor::parseSOF(): slight cleanup<commit_after>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post
    Copyright (C) 2017 Axel Waggershauser

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "decompressors/AbstractLJpegDecompressor.h"
#include "common/Common.h"                // for uint32, make_unique, uchar8
#include "common/Point.h"                 // for iPoint2D
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/HuffmanTable.h"   // for HuffmanTable
#include "io/ByteStream.h"                // for ByteStream
#include <array>                          // for array
#include <memory>                         // for unique_ptr, allocator
#include <utility>                        // for move
#include <vector>                         // for vector

namespace rawspeed {

void AbstractLJpegDecompressor::decode() {
  if (getNextMarker(false) != M_SOI)
    ThrowRDE("Image did not start with SOI. Probably not an LJPEG");

  struct FoundMarkers {
    bool DHT = false;
    bool SOF = false;
    bool SOS = false;
  } FoundMarkers;

  JpegMarker m;
  do {
    m = getNextMarker(true);

    switch (m) {
    case M_DHT:
      if (FoundMarkers.SOS)
        ThrowRDE("Found second DHT marker after SOS");
      // there can be more than one DHT markers.
      // FIXME: do we really want to reparse and use the last one?
      parseDHT();
      FoundMarkers.DHT = true;
      break;
    case M_SOF3:
      if (FoundMarkers.SOS)
        ThrowRDE("Found second SOF marker after SOS");
      if (FoundMarkers.SOF)
        ThrowRDE("Found second SOF marker");
      // SOF is not required to be after DHT
      parseSOF(&frame);
      FoundMarkers.SOF = true;
      break;
    case M_SOS:
      if (FoundMarkers.SOS)
        ThrowRDE("Found second SOS marker");
      if (!FoundMarkers.DHT)
        ThrowRDE("Did not find DHT marker before SOS.");
      if (!FoundMarkers.SOF)
        ThrowRDE("Did not find SOF marker before SOS.");
      parseSOS();
      FoundMarkers.SOS = true;
      break;
    case M_DQT:
      ThrowRDE("Not a valid RAW file.");
    default: // Just let it skip to next marker
      break;
    }
  } while (m != M_EOI);

  if (!FoundMarkers.SOS)
    ThrowRDE("Did not find SOS marker.");
}

void AbstractLJpegDecompressor::parseSOF(SOFInfo* sof) {
  ByteStream sofInput(input.getStream(input.peekU16()));
  sofInput.skipBytes(2); // headerLength

  sof->prec = sofInput.getByte();
  sof->h = sofInput.getU16();
  sof->w = sofInput.getU16();
  sof->cps = sofInput.getByte();

  if (sof->prec < 2 || sof->prec > 16)
    ThrowRDE("Invalid precision (%u).", sof->prec);

  if (sof->h == 0 || sof->w == 0)
    ThrowRDE("Frame width or height set to zero");

  if (sof->cps > 4 || sof->cps < 1)
    ThrowRDE("Only from 1 to 4 components are supported.");

  if (sofInput.getRemainSize() != 3 * sof->cps)
    ThrowRDE("Header size mismatch.");

  for (uint32 i = 0; i < sof->cps; i++) {
    sof->compInfo[i].componentId = sofInput.getByte();

    uint32 subs = sofInput.getByte();
    frame.compInfo[i].superV = subs & 0xf;
    frame.compInfo[i].superH = subs >> 4;

    if (frame.compInfo[i].superV < 1 || frame.compInfo[i].superV > 4)
      ThrowRDE("Horizontal sampling factor is invalid.");

    if (frame.compInfo[i].superH < 1 || frame.compInfo[i].superH > 4)
      ThrowRDE("Horizontal sampling factor is invalid.");

    uint32 Tq = sofInput.getByte();
    if (Tq != 0)
      ThrowRDE("Quantized components not supported.");
  }

  sof->initialized = true;

  mRaw->metadata.subsampling.x = sof->compInfo[0].superH;
  mRaw->metadata.subsampling.y = sof->compInfo[0].superV;
}

void AbstractLJpegDecompressor::parseSOS() {
  if (!frame.initialized)
    ThrowRDE("Frame not yet initialized (SOF Marker not parsed)");

  uint32 headerLength = input.getU16();
  if (headerLength != 3 + frame.cps * 2 + 3)
    ThrowRDE("Invalid SOS header length.");

  uint32 soscps = input.getByte();
  if (frame.cps != soscps)
    ThrowRDE("Component number mismatch.");

  for (uint32 i = 0; i < frame.cps; i++) {
    uint32 cs = input.getByte();
    uint32 td = input.getByte() >> 4;

    if (td > 3 || !huff[td])
      ThrowRDE("Invalid Huffman table selection.");

    int ciIndex = -1;
    for (uint32 j = 0; j < frame.cps; ++j) {
      if (frame.compInfo[j].componentId == cs)
        ciIndex = j;
    }

    if (ciIndex == -1)
      ThrowRDE("Invalid Component Selector");

    frame.compInfo[ciIndex].dcTblNo = td;
  }

  // Get predictor, see table H.1 from the JPEG spec
  predictorMode = input.getByte();
  // The spec says predictoreMode is in [0..7], but Hasselblad uses '8'.
  if (predictorMode > 8)
    ThrowRDE("Invalid predictor mode.");

  input.skipBytes(1);         // Se + Ah Not used in LJPEG
  Pt = input.getByte() & 0xf; // Point Transform

  decodeScan();
}

void AbstractLJpegDecompressor::parseDHT() {
  ByteStream dht(input.getStream(input.peekU16()));
  dht.skipBytes(2); // headerLength

  while (dht.getRemainSize() > 0) {
    uint32 b = dht.getByte();

    uint32 htClass = b >> 4;
    if (htClass != 0)
      ThrowRDE("Unsupported Table class.");

    uint32 htIndex = b & 0xf;
    if (htIndex >= huff.size())
      ThrowRDE("Invalid huffman table destination id.");

    if (huff[htIndex] != nullptr)
      ThrowRDE("Duplicate table definition");

    // copy 16 bytes from input stream to number of codes per length table
    uint32 nCodes = ht_.setNCodesPerLength(dht.getBuffer(16));

    // spec says 16 different codes is max but Hasselblad violates that -> 17
    if (nCodes > 17)
      ThrowRDE("Invalid DHT table.");

    // copy nCodes bytes from input stream to code values table
    ht_.setCodeValues(dht.getBuffer(nCodes));

    // see if we already have a HuffmanTable with the same codes
    for (const auto& i : huffmanTableStore)
      if (*i == ht_)
        huff[htIndex] = i.get();

    if (!huff[htIndex]) {
      // setup new ht_ and put it into the store
      auto dHT = std::make_unique<HuffmanTable>(ht_);
      dHT->setup(fullDecodeHT, fixDng16Bug);
      huff[htIndex] = dHT.get();
      huffmanTableStore.emplace_back(std::move(dHT));
    }
  }
}

JpegMarker AbstractLJpegDecompressor::getNextMarker(bool allowskip) {
  uchar8 c0;
  uchar8 c1 = input.getByte();
  do {
    c0 = c1;
    c1 = input.getByte();
  } while (allowskip && !(c0 == 0xFF && c1 != 0 && c1 != 0xFF));

  if (!(c0 == 0xFF && c1 != 0 && c1 != 0xFF))
    ThrowRDE("(Noskip) Expected marker not found. Propably corrupt file.");

  return static_cast<JpegMarker>(c1);
}

} // namespace rawspeed
<|endoftext|>