text:
/* BotServ core functions
 *
 * (C) 2003-2016 Anope Team
 * Contact us at team@anope.org
 *
 * Please read COPYING and README for further details.
 *
 * Based on the original code of Epona by Lara.
 * Based on the original code of Services by Andy Church.
 */

#include "module.h"
#include "modules/bs_kick.h"
#include "modules/bs_badwords.h"

static Module *me;

struct KickerDataImpl : KickerData
{
	KickerDataImpl(Extensible *obj)
	{
		amsgs = badwords = bolds = caps = colors = flood = italics = repeat = reverses = underlines = false;
		for (int16_t i = 0; i < TTB_SIZE; ++i)
			ttb[i] = 0;
		capsmin = capspercent = 0;
		floodlines = floodsecs = 0;
		repeattimes = 0;

		dontkickops = dontkickvoices = false;
	}

	void Check(ChannelInfo *ci) anope_override
	{
		if (amsgs || badwords || bolds || caps || colors || flood || italics || repeat || reverses || underlines)
			return;

		ci->Shrink<KickerData>("kickerdata");
	}

	struct ExtensibleItem : ::ExtensibleItem<KickerDataImpl>
	{
		ExtensibleItem(Module *m, const Anope::string &ename) : ::ExtensibleItem<KickerDataImpl>(m, ename) { }

		void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override
		{
			if (s->GetSerializableType()->GetName() != "ChannelInfo")
				return;

			const ChannelInfo *ci = anope_dynamic_static_cast<const ChannelInfo *>(e);
			KickerData *kd = this->Get(ci);
			if (kd == NULL)
				return;

			data["kickerdata:amsgs"] << kd->amsgs;
			data["kickerdata:badwords"] << kd->badwords;
			data["kickerdata:bolds"] << kd->bolds;
			data["kickerdata:caps"] << kd->caps;
			data["kickerdata:colors"] << kd->colors;
			data["kickerdata:flood"] << kd->flood;
			data["kickerdata:italics"] << kd->italics;
			data["kickerdata:repeat"] << kd->repeat;
			data["kickerdata:reverses"] << kd->reverses;
			data["kickerdata:underlines"] << kd->underlines;

			data.SetType("capsmin", Serialize::Data::DT_INT); data["capsmin"] << kd->capsmin;
			data.SetType("capspercent", Serialize::Data::DT_INT); data["capspercent"] << kd->capspercent;
			data.SetType("floodlines", Serialize::Data::DT_INT); data["floodlines"] << kd->floodlines;
			data.SetType("floodsecs", Serialize::Data::DT_INT); data["floodsecs"] << kd->floodsecs;
			data.SetType("repeattimes", Serialize::Data::DT_INT); data["repeattimes"] << kd->repeattimes;
			for (int16_t i = 0; i < TTB_SIZE; ++i)
				data["ttb"] << kd->ttb[i] << " ";
		}

		void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override
		{
			if (s->GetSerializableType()->GetName() != "ChannelInfo")
				return;

			ChannelInfo *ci = anope_dynamic_static_cast<ChannelInfo *>(e);
			KickerData *kd = ci->Require<KickerData>("kickerdata");

			data["kickerdata:amsgs"] >> kd->amsgs;
			data["kickerdata:badwords"] >> kd->badwords;
			data["kickerdata:bolds"] >> kd->bolds;
			data["kickerdata:caps"] >> kd->caps;
			data["kickerdata:colors"] >> kd->colors;
			data["kickerdata:flood"] >> kd->flood;
			data["kickerdata:italics"] >> kd->italics;
			data["kickerdata:repeat"] >> kd->repeat;
			data["kickerdata:reverses"] >> kd->reverses;
			data["kickerdata:underlines"] >> kd->underlines;

			data["capsmin"] >> kd->capsmin;
			data["capspercent"] >> kd->capspercent;
			data["floodlines"] >> kd->floodlines;
			data["floodsecs"] >> kd->floodsecs;
			data["repeattimes"] >> kd->repeattimes;

			Anope::string ttb, tok;
			data["ttb"] >> ttb;
			spacesepstream sep(ttb);
			for (int i = 0; sep.GetToken(tok) && i < TTB_SIZE; ++i)
				try
				{
					kd->ttb[i] = convertTo<int16_t>(tok);
				}
				catch (const ConvertException &) { }

			kd->Check(ci);
		}
	};
};

class CommandBSKick : public Command
{
 public:
	CommandBSKick(Module *creator) : Command(creator, "botserv/kick", 0)
	{
		this->SetDesc(_("Configures kickers"));
		this->SetSyntax(_("\037option\037 \037channel\037 {\037ON|OFF\037} [\037settings\037]"));
	}

	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
	{
		this->OnSyntaxError(source, "");
	}

	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
	{
		this->SendSyntax(source);
		source.Reply(" ");
		source.Reply(_("Configures bot kickers.  \037option\037 can be one of:"));

		Anope::string this_name = source.command;
		for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it)
		{
			const Anope::string &c_name = it->first;
			const CommandInfo &info = it->second;

			if (c_name.find_ci(this_name + " ") == 0)
			{
				ServiceReference<Command> command("Command", info.name);
				if (command)
				{
					source.command = c_name;
					command->OnServHelp(source);
				}
			}
		}

		source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n"
				"on a specific option.\n"
				" \n"
				"Note: access to this command is controlled by the\n"
				"level SET."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());

		return true;
	}
};

class CommandBSKickBase : public Command
{
 public:
	CommandBSKickBase(Module *creator, const Anope::string &cname, int minarg, int maxarg) : Command(creator, cname, minarg, maxarg)
	{
	}

	virtual void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override = 0;

	virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override = 0;

 protected:
	bool CheckArguments(CommandSource &source, const std::vector<Anope::string> &params, ChannelInfo* &ci)
	{
		const Anope::string &chan = params[0];
		const Anope::string &option = params[1];

		ci = ChannelInfo::Find(chan);

		if (Anope::ReadOnly)
			source.Reply(_("Sorry, kicker configuration is temporarily disabled."));
		else if (ci == NULL)
			source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
		else if (option.empty())
			this->OnSyntaxError(source, "");
		else if (!option.equals_ci("ON") && !option.equals_ci("OFF"))
			this->OnSyntaxError(source, "");
		else if (!source.AccessFor(ci).HasPriv("SET") && !source.HasPriv("botserv/administration"))
			source.Reply(ACCESS_DENIED);
		else if (!ci->bi)
			source.Reply(BOT_NOT_ASSIGNED);
		else
			return true;

		return false;
	}

	void Process(CommandSource &source, ChannelInfo *ci, const Anope::string &param, const Anope::string &ttb, size_t ttb_idx, const Anope::string &optname, KickerData *kd, bool &val)
	{
		if (param.equals_ci("ON"))
		{
			if (!ttb.empty())
			{
				int16_t i;

				try
				{
					i = convertTo<int16_t>(ttb);
					if (i < 0)
						throw ConvertException();
				}
				catch (const ConvertException &)
				{
					source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str());
					return;
				}

				kd->ttb[ttb_idx] = i;
			}
			else
				kd->ttb[ttb_idx] = 0;

			val = true;
			if (kd->ttb[ttb_idx])
				source.Reply(_("Bot will now kick for \002%s\002, and will place a ban\n"
						"after %d kicks for the same user."), optname.c_str(), kd->ttb[ttb_idx]);
			else
				source.Reply(_("Bot will now kick for \002%s\002."), optname.c_str());

			bool override = !source.AccessFor(ci).HasPriv("SET");
			Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable the " << optname << " kicker";
		}
		else if (param.equals_ci("OFF"))
		{
			bool override = !source.AccessFor(ci).HasPriv("SET");
			Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable the " << optname << " kicker";

			val = false;
			source.Reply(_("Bot won't kick for \002%s\002 anymore."), optname.c_str());
		}
		else
			this->OnSyntaxError(source, "");
	}
};

class CommandBSKickAMSG : public CommandBSKickBase
{
 public:
	CommandBSKickAMSG(Module *creator) : CommandBSKickBase(creator, "botserv/kick/amsg", 2, 3)
	{
		this->SetDesc(_("Configures AMSG kicker"));
		this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
	}

	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
	{
		ChannelInfo *ci;
		if (CheckArguments(source, params, ci))
		{
			KickerData *kd = ci->Require<KickerData>("kickerdata");
			Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_AMSGS, "AMSG", kd, kd->amsgs);
			kd->Check(ci);
		}
	}

	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
	{
		this->SendSyntax(source);
		source.Reply(" ");
		BotInfo *bi = Config->GetClient("BotServ");
		source.Reply(_("Sets the AMSG kicker on or off. When enabled, the bot will\n"
				"kick users who send the same message to multiple channels\n"
				"where %s bots are.\n"
				" \n"
				"\037ttb\037 is the number of times a user can be kicked\n"
				"before they get banned. Don't give ttb to disable\n"
				"the ban system once activated."), bi ? bi->nick.c_str() : "BotServ");
		return true;
	}
};

class CommandBSKickBadwords : public CommandBSKickBase
{
 public:
	CommandBSKickBadwords(Module *creator) : CommandBSKickBase(creator, "botserv/kick/badwords", 2, 3)
	{
		this->SetDesc(_("Configures badwords kicker"));
		this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
	}

	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
	{
		ChannelInfo *ci;
		if (CheckArguments(source, params, ci))
		{
			KickerData *kd = ci->Require<KickerData>("kickerdata");
			Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_BADWORDS, "badwords", kd, kd->badwords);
			kd->Check(ci);
		}

	}

	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
	{
		this->SendSyntax(source);
		source.Reply(" ");
		source.Reply(_("Sets the bad words kicker on or off. When enabled, this\n"
				"option tells the bot to kick users who say certain words\n"
				"on the channels.\n"
				"You can define bad words for your channel using the\n"
				"\002BADWORDS\002 command. Type \002%s%s HELP BADWORDS\002 for\n"
				"more information.\n"
				" \n"
				"\037ttb\037 is the number of times a user can be kicked\n"
				"before it gets banned. Don't give ttb to disable\n"
				"the ban system once activated."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
		return true;
	}
};

class CommandBSKickBolds : public CommandBSKickBase
{
 public:
	CommandBSKickBolds(Module *creator) : CommandBSKickBase(creator, "botserv/kick/bolds", 2, 3)
	{
		this->SetDesc(_("Configures bolds kicker"));
		this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
	}

	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
	{
		ChannelInfo *ci;
		if (CheckArguments(source, params, ci))
		{
			KickerData *kd = ci->Require<KickerData>("kickerdata");
			Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_BOLDS, "bolds", kd, kd->bolds);
			kd->Check(ci);
		}
	}

	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
	{
		this->SendSyntax(source);
		source.Reply(" ");
		source.Reply(_("Sets the bolds kicker on or off. When enabled, this\n"
				"option tells the bot to kick users who use bolds.\n"
				" \n"
				"\037ttb\037 is the number of times a user can be kicked\n"
				"before it gets banned. Don't give ttb to disable\n"
				"the ban system once activated."));
		return true;
	}
};

class CommandBSKickCaps : public CommandBSKickBase
{
 public:
	CommandBSKickCaps(Module *creator) : CommandBSKickBase(creator, "botserv/kick/caps", 2, 5)
	{
		this->SetDesc(_("Configures caps kicker"));
		this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037 [\037min\037 [\037percent\037]]]\002"));
	}

	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
	{
		ChannelInfo *ci;
		if (!CheckArguments(source, params, ci))
			return;

		KickerData *kd = ci->Require<KickerData>("kickerdata");

		if (params[1].equals_ci("ON"))
		{
			const Anope::string &ttb = params.size() > 2 ? params[2] : "",
				&min = params.size() > 3 ? params[3] : "",
				&percent = params.size() > 4 ? params[4] : "";

			if (!ttb.empty())
			{
				try
				{
					kd->ttb[TTB_CAPS] = convertTo<int16_t>(ttb);
					if (kd->ttb[TTB_CAPS] < 0)
						throw ConvertException();
				}
				catch (const ConvertException &)
				{
					kd->ttb[TTB_CAPS] = 0;
					source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str());
					return;
				}
			}
			else
				kd->ttb[TTB_CAPS] = 0;

			kd->capsmin = 10;
			try
			{
				kd->capsmin = convertTo<int16_t>(min);
			}
			catch (const ConvertException &) { }
			if (kd->capsmin < 1)
				kd->capsmin = 10;

			kd->capspercent = 25;
			try
			{
				kd->capspercent = convertTo<int16_t>(percent);
			}
			catch (const ConvertException &) { }
			if (kd->capspercent < 1 || kd->capspercent > 100)
				kd->capspercent = 25;

			kd->caps = true;
			if (kd->ttb[TTB_CAPS])
				source.Reply(_("Bot will now kick for \002caps\002 (they must constitute at least\n"
						"%d characters and %d%% of the entire message), and will\n"
						"place a ban after %d kicks for the same user."), kd->capsmin, kd->capspercent, kd->ttb[TTB_CAPS]);
			else
				source.Reply(_("Bot will now kick for \002caps\002 (they must constitute at least\n"
						"%d characters and %d%% of the entire message)."), kd->capsmin, kd->capspercent);
		}
		else
		{
			kd->caps = false;
			source.Reply(_("Bot won't kick for \002caps\002 anymore."));
		}

		kd->Check(ci);
	}

	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
	{
		this->SendSyntax(source);
		source.Reply(" ");
		source.Reply(_("Sets the caps kicker on or off. When enabled, this\n"
				"option tells the bot to kick users who are talking in\n"
				"CAPS.\n"
				"The bot kicks only if there are at least \002min\002 caps\n"
				"and they constitute at least \002percent\002%% of the total\n"
				"text line (if not given, it defaults to 10 characters\n"
				"and 25%%).\n"
				" \n"
				"\037ttb\037 is the number of times a user can be kicked\n"
				"before it gets banned. Don't give ttb to disable\n"
				"the ban system once activated."));
		return true;
	}
};

class CommandBSKickColors : public CommandBSKickBase
{
 public:
	CommandBSKickColors(Module *creator) : CommandBSKickBase(creator, "botserv/kick/colors", 2, 3)
	{
		this->SetDesc(_("Configures color kicker"));
		this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
	}

	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
	{
		ChannelInfo *ci;
		if (CheckArguments(source, params, ci))
		{
			KickerData *kd = ci->Require<KickerData>("kickerdata");
			Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_COLORS, "colors", kd, kd->colors);
			kd->Check(ci);
		}
	}

	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
	{
		this->SendSyntax(source);
		source.Reply(" ");
		source.Reply(_("Sets the colors kicker on or off. When enabled, this\n"
				"option tells the bot to kick users who use colors.\n"
				" \n"
				"\037ttb\037 is the number of times a user can be kicked\n"
				"before it gets banned. Don't give ttb to disable\n"
				"the ban system once activated."));
		return true;
	}
};

class CommandBSKickFlood : public CommandBSKickBase
{
 public:
	CommandBSKickFlood(Module *creator) : CommandBSKickBase(creator, "botserv/kick/flood", 2, 5)
	{
		this->SetDesc(_("Configures flood kicker"));
		this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037 [\037ln\037 [\037secs\037]]]\002"));
	}

	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
	{
		ChannelInfo *ci;
		if (!CheckArguments(source, params, ci))
			return;

		KickerData *kd = ci->Require<KickerData>("kickerdata");

		if (params[1].equals_ci("ON"))
		{
			const Anope::string &ttb = params.size() > 2 ? params[2] : "",
						&lines = params.size() > 3 ? params[3] : "",
						&secs = params.size() > 4 ? params[4] : "";

			if (!ttb.empty())
			{
				int16_t i;

				try
				{
					i = convertTo<int16_t>(ttb);
					if (i < 0)
						throw ConvertException();
				}
				catch (const ConvertException &)
				{
					source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str());
					return;
				}

				kd->ttb[TTB_FLOOD] = i;
			}
			else
				kd->ttb[TTB_FLOOD] = 0;

			kd->floodlines = 6;
			try
			{
				kd->floodlines = convertTo<int16_t>(lines);
			}
			catch (const ConvertException &) { }
			if (kd->floodlines < 2)
				kd->floodlines = 6;

			kd->floodsecs = 10;
			try
			{
				kd->floodsecs = convertTo<int16_t>(secs);
			}
			catch (const ConvertException &) { }
			if (kd->floodsecs < 1)
				kd->floodsecs = 10;
			if (kd->floodsecs > Config->GetModule(me)->Get<time_t>("keepdata"))
				kd->floodsecs = Config->GetModule(me)->Get<time_t>("keepdata");

			kd->flood = true;
			if (kd->ttb[TTB_FLOOD])
				source.Reply(_("Bot will now kick for \002flood\002 (%d lines in %d seconds\n"
						"and will place a ban after %d kicks for the same user."), kd->floodlines, kd->floodsecs, kd->ttb[TTB_FLOOD]);
			else
				source.Reply(_("Bot will now kick for \002flood\002 (%d lines in %d seconds)."), kd->floodlines, kd->floodsecs);
		}
		else if (params[1].equals_ci("OFF"))
		{
			kd->flood = false;
			source.Reply(_("Bot won't kick for \002flood\002 anymore."));
		}
		else
			this->OnSyntaxError(source, params[1]);

		kd->Check(ci);
	}

	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
	{
		this->SendSyntax(source);
		source.Reply(" ");
		source.Reply(_("Sets the flood kicker on or off. When enabled, this\n"
				"option tells the bot to kick users who are flooding\n"
				"the channel using at least \002ln\002 lines in \002secs\002 seconds\n"
				"(if not given, it defaults to 6 lines in 10 seconds).\n"
				" \n"
				"\037ttb\037 is the number of times a user can be kicked\n"
				"before it gets banned. Don't give ttb to disable\n"
				"the ban system once activated."));
		return true;
	}
};

class CommandBSKickItalics : public CommandBSKickBase
{
 public:
	CommandBSKickItalics(Module *creator) : CommandBSKickBase(creator, "botserv/kick/italics", 2, 3)
	{
		this->SetDesc(_("Configures italics kicker"));
		this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
	}

	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
	{
		ChannelInfo *ci;
		if (CheckArguments(source, params, ci))
		{
			KickerData *kd = ci->Require<KickerData>("kickerdata");
			Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_ITALICS, "italics", kd, kd->italics);
			kd->Check(ci);
		}
	}

	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
	{
		this->SendSyntax(source);
		source.Reply(" ");
		source.Reply(_("Sets the italics kicker on or off. When enabled, this\n"
				"option tells the bot to kick users who use italics.\n"
				" \n"
				"\037ttb\037 is the number of times a user can be kicked\n"
				"before it gets banned. Don't give ttb to disable\n"
				"the ban system once activated."));
		return true;
	}
};

class CommandBSKickRepeat : public CommandBSKickBase
{
 public:
	CommandBSKickRepeat(Module *creator) : CommandBSKickBase(creator, "botserv/kick/repeat", 2, 4)
	{
		this->SetDesc(_("Configures repeat kicker"));
		this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037 [\037num\037]]\002"));
	}

	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
	{
		ChannelInfo *ci;
		if (!CheckArguments(source, params, ci))
			return;

		KickerData *kd = ci->Require<KickerData>("kickerdata");

		if (params[1].equals_ci("ON"))
		{
			const Anope::string &ttb = params.size() > 2 ? params[2] : "",
						&times = params.size() > 3 ? params[3] : "";

			if (!ttb.empty())
			{
				int16_t i;

				try
				{
					i = convertTo<int16_t>(ttb);
					if (i < 0)
						throw ConvertException();
				}
				catch (const ConvertException &)
				{
					source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str());
					return;
				}

				kd->ttb[TTB_REPEAT] = i;
			}
			else
				kd->ttb[TTB_REPEAT] = 0;

			kd->repeattimes = 3;
			try
			{
				kd->repeattimes = convertTo<int16_t>(times);
			}
			catch (const ConvertException &) { }
			if (kd->repeattimes < 2)
				kd->repeattimes = 3;

			kd->repeat = true;
			if (kd->ttb[TTB_REPEAT])
				source.Reply(_("Bot will now kick for \002repeats\002 (users that say the\n"
						"same thing %d times), and will place a ban after %d\n"
						"kicks for the same user."), kd->repeattimes + 1, kd->ttb[TTB_REPEAT]);
			else
				source.Reply(_("Bot will now kick for \002repeats\002 (users that say the\n"
					"same thing %d times)."), kd->repeattimes + 1);
		}
		else if (params[1].equals_ci("OFF"))
		{
			kd->repeat = false;
			source.Reply(_("Bot won't kick for \002repeats\002 anymore."));
		}
		else
			this->OnSyntaxError(source, params[1]);

		kd->Check(ci);
	}

	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
	{
		this->SendSyntax(source);
		source.Reply(" ");
		source.Reply(_("Sets the repeat kicker on or off. When enabled, this\n"
				"option tells the bot to kick users who are repeating\n"
				"themselves \002num\002 times (if num is not given, it\n"
				"defaults to 3).\n"
				" \n"
				"\037ttb\037 is the number of times a user can be kicked\n"
				"before it gets banned. Don't give ttb to disable\n"
				"the ban system once activated."));
		return true;
	}
};

class CommandBSKickReverses : public CommandBSKickBase
{
 public:
 	CommandBSKickReverses(Module *creator) : CommandBSKickBase(creator, "botserv/kick/reverses", 2, 3)
	{
		this->SetDesc(_("Configures reverses kicker"));
		this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
	}

	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
	{
		ChannelInfo *ci;
		if (CheckArguments(source, params, ci))
		{
			KickerData *kd = ci->Require<KickerData>("kickerdata");
			Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_REVERSES, "reverses", kd, kd->reverses);
			kd->Check(ci);
		}
	}

	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
	{
		this->SendSyntax(source);
		source.Reply(" ");
		source.Reply(_("Sets the reverses kicker on or off. When enabled, this\n"
				"option tells the bot to kick users who use reverses.\n"
				" \n"
				"\037ttb\037 is the number of times a user can be kicked\n"
				"before it gets banned. Don't give ttb to disable\n"
				"the ban system once activated."));
		return true;
	}
};

class CommandBSKickUnderlines : public CommandBSKickBase
{
 public:
	CommandBSKickUnderlines(Module *creator) : CommandBSKickBase(creator, "botserv/kick/underlines", 2, 3)
	{
		this->SetDesc(_("Configures underlines kicker"));
		this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
	}

	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
	{
		ChannelInfo *ci;
		if (CheckArguments(source, params, ci))
		{
			KickerData *kd = ci->Require<KickerData>("kickerdata");
			Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_UNDERLINES, "underlines", kd, kd->underlines);
			kd->Check(ci);
		}
	}

	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
	{
		this->SendSyntax(source);
		source.Reply(" ");
		source.Reply(_("Sets the underlines kicker on or off. When enabled, this\n"
			"option tells the bot to kick users who use underlines.\n"
			" \n"
			"\037ttb\037 is the number of times a user can be kicked\n"
			"before it gets banned. Don't give ttb to disable\n"
			"the ban system once activated."));
		return true;
	}
};

class CommandBSSetDontKickOps : public Command
{
 public:
	CommandBSSetDontKickOps(Module *creator, const Anope::string &sname = "botserv/set/dontkickops") : Command(creator, sname, 2, 2)
	{
		this->SetDesc(_("To protect ops against bot kicks"));
		this->SetSyntax(_("\037channel\037 {ON | OFF}"));
	}

	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
	{
		ChannelInfo *ci = ChannelInfo::Find(params[0]);
		if (ci == NULL)
		{
			source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
			return;
		}

		AccessGroup access = source.AccessFor(ci);
		if (!source.HasPriv("botserv/administration") && !access.HasPriv("SET"))
		{
			source.Reply(ACCESS_DENIED);
			return;
		}

		if (Anope::ReadOnly)
		{
			source.Reply(_("Sorry, bot option setting is temporarily disabled."));
			return;
		}

		KickerData *kd = ci->Require<KickerData>("kickerdata");
		if (params[1].equals_ci("ON"))
		{
			bool override = !access.HasPriv("SET");
			Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable dontkickops";

			kd->dontkickops = true;
			source.Reply(_("Bot \002won't kick ops\002 on channel %s."), ci->name.c_str());
		}
		else if (params[1].equals_ci("OFF"))
		{
			bool override = !access.HasPriv("SET");
			Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable dontkickops";

			kd->dontkickops = false;
			source.Reply(_("Bot \002will kick ops\002 on channel %s."), ci->name.c_str());
		}
		else
			this->OnSyntaxError(source, source.command);

		kd->Check(ci);
	}

	bool OnHelp(CommandSource &source, const Anope::string &) anope_override
	{
		this->SendSyntax(source);
		source.Reply(_(" \n"
				"Enables or disables \002ops protection\002 mode on a channel.\n"
				"When it is enabled, ops won't be kicked by the bot\n"
				"even if they don't match the NOKICK level."));
		return true;
	}
};

class CommandBSSetDontKickVoices : public Command
{
 public:
	CommandBSSetDontKickVoices(Module *creator, const Anope::string &sname = "botserv/set/dontkickvoices") : Command(creator, sname, 2, 2)
	{
		this->SetDesc(_("To protect voices against bot kicks"));
		this->SetSyntax(_("\037channel\037 {ON | OFF}"));
	}

	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
	{
		ChannelInfo *ci = ChannelInfo::Find(params[0]);
		if (ci == NULL)
		{
			source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
			return;
		}

		AccessGroup access = source.AccessFor(ci);
		if (!source.HasPriv("botserv/administration") && !access.HasPriv("SET"))
		{
			source.Reply(ACCESS_DENIED);
			return;
		}

		if (Anope::ReadOnly)
		{
			source.Reply(_("Sorry, bot option setting is temporarily disabled."));
			return;
		}

		KickerData *kd = ci->Require<KickerData>("kickerdata");
		if (params[1].equals_ci("ON"))
		{
			bool override = !access.HasPriv("SET");
			Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable dontkickvoices";

			kd->dontkickvoices = true;
			source.Reply(_("Bot \002won't kick voices\002 on channel %s."), ci->name.c_str());
		}
		else if (params[1].equals_ci("OFF"))
		{
			bool override = !access.HasPriv("SET");
			Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable dontkickvoices";

			kd->dontkickvoices = false;
			source.Reply(_("Bot \002will kick voices\002 on channel %s."), ci->name.c_str());
		}
		else
			this->OnSyntaxError(source, source.command);

		kd->Check(ci);
	}

	bool OnHelp(CommandSource &source, const Anope::string &) anope_override
	{
		this->SendSyntax(source);
		source.Reply(_(" \n"
				"Enables or disables \002voices protection\002 mode on a channel.\n"
				"When it is enabled, voices won't be kicked by the bot\n"
				"even if they don't match the NOKICK level."));
		return true;
	}
};

struct BanData
{
	struct Data
	{
		Anope::string mask;
		time_t last_use;
		int16_t ttb[TTB_SIZE];

		Data()
		{
			last_use = 0;
			for (int i = 0; i < TTB_SIZE; ++i)
				this->ttb[i] = 0;
		}
	};

 private:
	typedef Anope::map<Data> data_type;
	data_type data_map;

 public:
 	BanData(Extensible *) { }

	Data &get(const Anope::string &key)
	{
		return this->data_map[key];
	}

	bool empty() const
	{
		return this->data_map.empty();
	}

	void purge()
	{
		time_t keepdata = Config->GetModule(me)->Get<time_t>("keepdata");
		for (data_type::iterator it = data_map.begin(), it_end = data_map.end(); it != it_end;)
		{
			const Anope::string &user = it->first;
			Data &bd = it->second;
			++it;

			if (Anope::CurTime - bd.last_use > keepdata)
				data_map.erase(user);
		}
	}
};

struct UserData
{
	UserData(Extensible *)
	{
		last_use = last_start = Anope::CurTime;
		lines = times = 0;
		lastline.clear();
	}

	/* Data validity */
	time_t last_use;

	/* for flood kicker */
	int16_t lines;
	time_t last_start;

	/* for repeat kicker */
	Anope::string lasttarget;
	int16_t times;

	Anope::string lastline;
};

class BanDataPurger : public Timer
{
 public:
	BanDataPurger(Module *o) : Timer(o, 300, Anope::CurTime, true) { }

	void Tick(time_t) anope_override
	{
		Log(LOG_DEBUG) << "bs_main: Running bandata purger";

		for (channel_map::iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
		{
			Channel *c = it->second;

			BanData *bd = c->GetExt<BanData>("bandata");
			if (bd != NULL)
			{
				bd->purge();
				if (bd->empty())
					c->Shrink<BanData>("bandata");
			}
		}
	}
};

class BSKick : public Module
{
	ExtensibleItem<BanData> bandata;
	ExtensibleItem<UserData> userdata;
	KickerDataImpl::ExtensibleItem kickerdata;

	CommandBSKick commandbskick;
	CommandBSKickAMSG commandbskickamsg;
	CommandBSKickBadwords commandbskickbadwords;
	CommandBSKickBolds commandbskickbolds;
	CommandBSKickCaps commandbskickcaps;
	CommandBSKickColors commandbskickcolors;
	CommandBSKickFlood commandbskickflood;
	CommandBSKickItalics commandbskickitalics;
	CommandBSKickRepeat commandbskickrepeat;
	CommandBSKickReverses commandbskickreverse;
	CommandBSKickUnderlines commandbskickunderlines;

	CommandBSSetDontKickOps commandbssetdontkickops;
	CommandBSSetDontKickVoices commandbssetdontkickvoices;

	BanDataPurger purger;

	BanData::Data &GetBanData(User *u, Channel *c)
	{
		BanData *bd = bandata.Require(c);
		return bd->get(u->GetMask());
	}

	UserData *GetUserData(User *u, Channel *c)
	{
		ChanUserContainer *uc = c->FindUser(u);
		if (uc == NULL)
			return NULL;

		UserData *ud = userdata.Require(uc);
		return ud;
       }

	void check_ban(ChannelInfo *ci, User *u, KickerData *kd, int ttbtype)
	{
		/* Don't ban ulines or protected users */
		if (u->IsProtected())
			return;

		BanData::Data &bd = this->GetBanData(u, ci->c);

		++bd.ttb[ttbtype];
		if (kd->ttb[ttbtype] && bd.ttb[ttbtype] >= kd->ttb[ttbtype])
		{
			/* Should not use == here because bd.ttb[ttbtype] could possibly be > kd->ttb[ttbtype]
			 * if the TTB was changed after it was not set (0) before and the user had already been
			 * kicked a few times. Bug #1056 - Adam */

			bd.ttb[ttbtype] = 0;

			Anope::string mask = ci->GetIdealBan(u);

			ci->c->SetMode(NULL, "BAN", mask);
			FOREACH_MOD(OnBotBan, (u, ci, mask));
		}
	}

	void bot_kick(ChannelInfo *ci, User *u, const char *message, ...)
	{
		va_list args;
		char buf[1024];

		if (!ci || !ci->bi || !ci->c || !u || u->IsProtected() || !ci->c->FindUser(u))
			return;

		Anope::string fmt = Language::Translate(u, message);
		va_start(args, message);
		vsnprintf(buf, sizeof(buf), fmt.c_str(), args);
		va_end(args);

		ci->c->Kick(ci->bi, u, "%s", buf);
	}

 public:
	BSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
		bandata(this, "bandata"),
		userdata(this, "userdata"),
		kickerdata(this, "kickerdata"),

		commandbskick(this),
		commandbskickamsg(this), commandbskickbadwords(this), commandbskickbolds(this), commandbskickcaps(this),
		commandbskickcolors(this), commandbskickflood(this), commandbskickitalics(this), commandbskickrepeat(this),
		commandbskickreverse(this), commandbskickunderlines(this),

		commandbssetdontkickops(this), commandbssetdontkickvoices(this),

		purger(this)
	{
		me = this;

	}

	void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) anope_override
	{
		if (!ci)
			return;

		Anope::string enabled = Language::Translate(source.nc, _("Enabled"));
		Anope::string disabled = Language::Translate(source.nc, _("Disabled"));
		KickerData *kd = kickerdata.Get(ci);

		if (kd && kd->badwords)
		{
			if (kd->ttb[TTB_BADWORDS])
				info[_("Bad words kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BADWORDS]);
			else
				info[_("Bad words kicker")] = enabled;
		}
		else
			info[_("Bad words kicker")] = disabled;

		if (kd && kd->bolds)
		{
			if (kd->ttb[TTB_BOLDS])
				info[_("Bolds kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BOLDS]);
			else
				info[_("Bolds kicker")] = enabled;
		}
		else
			info[_("Bolds kicker")] = disabled;

		if (kd && kd->caps)
		{
			if (kd->ttb[TTB_CAPS])
				info[_("Caps kicker")] = Anope::printf(_("%s (%d kick(s) to ban; minimum %d/%d%%)"), enabled.c_str(), kd->ttb[TTB_CAPS], kd->capsmin, kd->capspercent);
			else
				info[_("Caps kicker")] = Anope::printf(_("%s (minimum %d/%d%%)"), enabled.c_str(), kd->capsmin, kd->capspercent);
		}
		else
			info[_("Caps kicker")] = disabled;

		if (kd && kd->colors)
		{
			if (kd->ttb[TTB_COLORS])
				info[_("Colors kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_COLORS]);
			else
				info[_("Colors kicker")] = enabled;
		}
		else
			info[_("Colors kicker")] = disabled;

		if (kd && kd->flood)
		{
			if (kd->ttb[TTB_FLOOD])
				info[_("Flood kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d lines in %ds)"), enabled.c_str(), kd->ttb[TTB_FLOOD], kd->floodlines, kd->floodsecs);
			else
				info[_("Flood kicker")] = Anope::printf(_("%s (%d lines in %ds)"), enabled.c_str(), kd->floodlines, kd->floodsecs);
		}
		else
			info[_("Flood kicker")] = disabled;

		if (kd && kd->repeat)
		{
			if (kd->ttb[TTB_REPEAT])
				info[_("Repeat kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d times)"), enabled.c_str(), kd->ttb[TTB_REPEAT], kd->repeattimes);
			else
				info[_("Repeat kicker")] = Anope::printf(_("%s (%d times)"), enabled.c_str(), kd->repeattimes);
		}
		else
			info[_("Repeat kicker")] = disabled;

		if (kd && kd->reverses)
		{
			if (kd->ttb[TTB_REVERSES])
				info[_("Reverses kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_REVERSES]);
			else
				info[_("Reverses kicker")] = enabled;
		}
		else
			info[_("Reverses kicker")] = disabled;

		if (kd && kd->underlines)
		{
			if (kd->ttb[TTB_UNDERLINES])
				info[_("Underlines kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_UNDERLINES]);
			else
				info[_("Underlines kicker")] = enabled;
		}
		else
			info[_("Underlines kicker")] = disabled;

		if (kd && kd->italics)
		{
			if (kd->ttb[TTB_ITALICS])
				info[_("Italics kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_ITALICS]);
			else
				info[_("Italics kicker")] = enabled;
		}
		else
			info[_("Italics kicker")] = disabled;

		if (kd && kd->amsgs)
		{
			if (kd->ttb[TTB_AMSGS])
				info[_("AMSG kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_AMSGS]);
			else
				info[_("AMSG kicker")] = enabled;
		}
		else
			info[_("AMSG kicker")] = disabled;

		if (kd && kd->dontkickops)
			info.AddOption(_("Ops protection"));
		if (kd && kd->dontkickvoices)
			info.AddOption(_("Voices protection"));
	}

	void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override
	{
		/* Now we can make kicker stuff. We try to order the checks
		 * from the fastest one to the slowest one, since there's
		 * no need to process other kickers if a user is kicked before
		 * the last kicker check.
		 *
		 * But FIRST we check whether the user is protected in any
		 * way.
		 */
		ChannelInfo *ci = c->ci;
		if (ci == NULL)
			return;
		KickerData *kd = kickerdata.Get(ci);
		if (kd == NULL)
			return;

		if (ci->AccessFor(u).HasPriv("NOKICK"))
			return;
		else if (kd->dontkickops && (c->HasUserStatus(u, "HALFOP") || c->HasUserStatus(u, "OP") || c->HasUserStatus(u, "PROTECT") || c->HasUserStatus(u, "OWNER")))
			return;
		else if (kd->dontkickvoices && c->HasUserStatus(u, "VOICE"))
			return;

		Anope::string realbuf = msg;

		/* If it's a /me, cut the CTCP part because the ACTION will cause
		 * problems with the caps or badwords kicker
		 */
		if (realbuf.substr(0, 8).equals_ci("\1ACTION ") && realbuf[realbuf.length() - 1] == '\1')
		{
			realbuf.erase(0, 8);
			realbuf.erase(realbuf.length() - 1);
		}

		if (realbuf.empty())
			return;

		/* Bolds kicker */
		if (kd->bolds && realbuf.find(2) != Anope::string::npos)
		{
			check_ban(ci, u, kd, TTB_BOLDS);
			bot_kick(ci, u, _("Don't use bolds on this channel!"));
			return;
		}

		/* Color kicker */
		if (kd->colors && realbuf.find(3) != Anope::string::npos)
		{
			check_ban(ci, u, kd, TTB_COLORS);
			bot_kick(ci, u, _("Don't use colors on this channel!"));
			return;
		}

		/* Reverses kicker */
		if (kd->reverses && realbuf.find(22) != Anope::string::npos)
		{
			check_ban(ci, u, kd, TTB_REVERSES);
			bot_kick(ci, u, _("Don't use reverses on this channel!"));
			return;
		}

		/* Italics kicker */
		if (kd->italics && realbuf.find(29) != Anope::string::npos)
		{
			check_ban(ci, u, kd, TTB_ITALICS);
			bot_kick(ci, u, _("Don't use italics on this channel!"));
			return;
		}

		/* Underlines kicker */
		if (kd->underlines && realbuf.find(31) != Anope::string::npos)
		{
			check_ban(ci, u, kd, TTB_UNDERLINES);
			bot_kick(ci, u, _("Don't use underlines on this channel!"));
			return;
		}

		/* Caps kicker */
		if (kd->caps && realbuf.length() >= static_cast<unsigned>(kd->capsmin))
		{
			int i = 0, l = 0;

			for (unsigned j = 0, end = realbuf.length(); j < end; ++j)
			{
				if (isupper(realbuf[j]))
					++i;
				else if (islower(realbuf[j]))
					++l;
			}

			/* i counts uppercase chars, l counts lowercase chars. Only
			 * alphabetic chars (so islower || isupper) qualify for the
			 * percentage of caps to kick for; the rest is ignored. -GD
			 */

			if ((i || l) && i >= kd->capsmin && i * 100 / (i + l) >= kd->capspercent)
			{
				check_ban(ci, u, kd, TTB_CAPS);
				bot_kick(ci, u, _("Turn caps lock OFF!"));
				return;
			}
		}

		/* Bad words kicker */
		if (kd->badwords)
		{
			bool mustkick = false;
			BadWords *badwords = ci->GetExt<BadWords>("badwords");

			/* Normalize the buffer */
			Anope::string nbuf = Anope::NormalizeBuffer(realbuf);
			bool casesensitive = Config->GetModule("botserv")->Get<bool>("casesensitive");

			/* Normalize can return an empty string if this only conains control codes etc */
			if (badwords && !nbuf.empty())
				for (unsigned i = 0; i < badwords->GetBadWordCount(); ++i)
				{
					const BadWord *bw = badwords->GetBadWord(i);

					if (bw->word.empty())
						continue; // Shouldn't happen

					if (bw->word.length() > nbuf.length())
						continue; // This can't ever match

					if (bw->type == BW_ANY && ((casesensitive && nbuf.find(bw->word) != Anope::string::npos) || (!casesensitive && nbuf.find_ci(bw->word) != Anope::string::npos)))
						mustkick = true;
					else if (bw->type == BW_SINGLE)
					{
						size_t len = bw->word.length();

						if ((casesensitive && bw->word.equals_cs(nbuf)) || (!casesensitive && bw->word.equals_ci(nbuf)))
							mustkick = true;
						else if (nbuf.find(' ') == len && ((casesensitive && bw->word.equals_cs(nbuf.substr(0, len))) || (!casesensitive && bw->word.equals_ci(nbuf.substr(0, len)))))
							mustkick = true;
						else
						{
							if (len < nbuf.length() && nbuf.rfind(' ') == nbuf.length() - len - 1 && ((casesensitive && nbuf.find(bw->word) == nbuf.length() - len) || (!casesensitive && nbuf.find_ci(bw->word) == nbuf.length() - len)))
								mustkick = true;
							else
							{
								Anope::string wordbuf = " " + bw->word + " ";

								if ((casesensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!casesensitive && nbuf.find_ci(wordbuf) != Anope::string::npos))
									mustkick = true;
							}
						}
					}
					else if (bw->type == BW_START)
					{
						size_t len = bw->word.length();

						if ((casesensitive && nbuf.substr(0, len).equals_cs(bw->word)) || (!casesensitive && nbuf.substr(0, len).equals_ci(bw->word)))
							mustkick = true;
						else
						{
							Anope::string wordbuf = " " + bw->word;

							if ((casesensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!casesensitive && nbuf.find_ci(wordbuf) != Anope::string::npos))
								mustkick = true;
						}
					}
					else if (bw->type == BW_END)
					{
						size_t len = bw->word.length();

						if ((casesensitive && nbuf.substr(nbuf.length() - len).equals_cs(bw->word)) || (!casesensitive && nbuf.substr(nbuf.length() - len).equals_ci(bw->word)))
							mustkick = true;
						else
						{
							Anope::string wordbuf = bw->word + " ";

							if ((casesensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!casesensitive && nbuf.find_ci(wordbuf) != Anope::string::npos))
								mustkick = true;
						}
					}

					if (mustkick)
					{
						check_ban(ci, u, kd, TTB_BADWORDS);
						if (Config->GetModule(me)->Get<bool>("gentlebadwordreason"))
							bot_kick(ci, u, _("Watch your language!"));
						else
							bot_kick(ci, u, _("Don't use the word \"%s\" on this channel!"), bw->word.c_str());

						return;
					}
				} /* for */
		} /* if badwords */

		UserData *ud = GetUserData(u, c);

		if (ud)
		{
			/* Flood kicker */
			if (kd->flood)
			{
				if (Anope::CurTime - ud->last_start > kd->floodsecs)
				{
					ud->last_start = Anope::CurTime;
					ud->lines = 0;
				}

				++ud->lines;
				if (ud->lines >= kd->floodlines)
				{
					check_ban(ci, u, kd, TTB_FLOOD);
					bot_kick(ci, u, _("Stop flooding!"));
					return;
				}
			}

			/* Repeat kicker */
			if (kd->repeat)
			{
				if (!ud->lastline.equals_ci(realbuf))
					ud->times = 0;
				else
					++ud->times;

				if (ud->times >= kd->repeattimes)
				{
					check_ban(ci, u, kd, TTB_REPEAT);
					bot_kick(ci, u, _("Stop repeating yourself!"));
					return;
				}
			}

			if (ud->lastline.equals_ci(realbuf) && !ud->lasttarget.empty() && !ud->lasttarget.equals_ci(ci->name))
			{
				for (User::ChanUserList::iterator it = u->chans.begin(); it != u->chans.end();)
				{
					Channel *chan = it->second->chan;
					++it;

					if (chan->ci && kd->amsgs && !chan->ci->AccessFor(u).HasPriv("NOKICK"))
					{
						check_ban(chan->ci, u, kd, TTB_AMSGS);
						bot_kick(chan->ci, u, _("Don't use AMSGs!"));
					}
				}
			}

			ud->lasttarget = ci->name;
			ud->lastline = realbuf;
		}
	}
};

MODULE_INIT(BSKick)


text:
package com.davidbracewell.conversion;

public class ConvertTest {

}

redpajama_set_name: RedPajamaGithub


text:
Difficulty: Easy

https://leetcode.com/problems/reverse-vowels-of-a-string/

Write a function that takes a string as input and reverse only the vowels of a string.

**Example 1:**
```
Input: "hello"
Output: "holle"
```

**Example 2:**
```
Input: "leetcode"
Output: "leotcede"
```

**Note:**

The vowels does not include the letter "y".


text:
@interface DVViewController ()

@end

@implementation DVViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.

    [[self navigationController] setNavigationBarHidden:YES];
    [self.view setBackgroundColor:[UIColor whiteColor]];

}
- (IBAction)showDrawVC:(id)sender {
    drawVC = [[DrawVC alloc] initWithNibName:@"DrawVC" bundle:[NSBundle bundleForClass:[DrawVC class]]];
    drawVC.delegate = self;
    [drawVC setShowSaveAlert:YES];
    //[drawVC blockDrawWithMessage:@"BlockView"];
    [self presentViewController:drawVC animated:YES completion:nil];

    //[drawVC setButtonsMode: ThreeButtonsAndABox];
    //drawVC.buttonsTmeHeightConstraint.constant = 100;

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)drawVC:(UIViewController *)pDrawVC imagen:(UIImage *)imagen{
    UIImageView *imageV = [[UIImageView alloc] initWithImage:imagen];
    [self.view addSubview:imageV];
}

-(void)drawVC:(UIViewController *)pDrawVC viewDidAppearFinished:(NSObject *)pData{

}

@end


text:
'use strict';

angular.module('ioAtSpotApp')
    .controller('TimeOffsCtrl',
        function ($scope, $http, socket, authModel, TimeOffs, $moment, $modal, Members, messageCenterService) {

            //var authModel = Auth.getAuthModel();

            $scope.model = new function () {
                var model = this;

                model.timeOffs = [];
                model.totalNumber = null;
                model.page = 1;
                model.maxPaginationSize = 5;
                model.itemsPerPage = 10;

                model.showFilters = true;

                model.day = new Date();

                model.fastPeriodFilter = null;
                model.membersFilter = [authModel.currentUser._id];
                model.membersFilterText = authModel.currentUser.name;
                model.timeOffTypeFilter = 'All';
                model.from = null;
                model.to = null;

                //model.organization = Auth.getCurrentOrganization(organizations);
                model.workingDays = authModel.currentOrganization.settings.workingDays;
                model.timeOffTypes = authModel.currentOrganization.settings.timeOffTypes;

                $scope.$watch('model.fastPeriodFilter', function (newValue, oldValue) {

                    if (newValue === 'lm') {
                        $scope.actions.lastMonth();
                    } else if (newValue === 'tm') {
                        $scope.actions.thisMonth();
                    } else if (newValue === 'lw') {
                        $scope.actions.lastWeek();
                    } else if (newValue === 'tw') {
                        $scope.actions.thisWeek();
                    } else if (newValue === null) {
                        model.from = null;
                        model.to = null;
                        $scope.actions.search();
                    }

                });

                $scope.$watch('model.page', function (newValue, oldValue) {
                    if (newValue != oldValue) {
                        $scope.proxies.search.request();
                    }
                });

                $scope.$watch('model.timeOffTypeFilter', function (newValue, oldValue) {
                    if (newValue != oldValue) {
                        $scope.proxies.search.request();
                    }
                });

                $scope.$on('organization-updated', function (event, data) {
                    var newOrganization = data.newOrganization;
                    var oldOrganization = data.oldOrganization;

                    if (newOrganization !== oldOrganization) {

                        $scope.proxies.loadMembers();
                        $scope.proxies.search.request();
                    }
                });
            };

            $scope.utils = new function () {
                var utils = this;

                utils.userDropdownOpened = false;

                utils.format = 'dd MMMM yyyy';

                utils.disabled = function (date, mode) {
                    return false;
                };

                utils.datepickerOpened = false;
                utils.fromOpened = false;
                utils.toOpened = false;

                utils.isCurrentOrganizationAdmin = function () {

                    return authModel.currentOrganization.userRole === 'admin';
                };

                utils.setPageSize = function (n) {
                    $scope.model.page = 1;
                    $scope.model.itemsPerPage = n;
                    $scope.actions.search();
                };

                utils.getExportData = function () {
                    var data = [];
                    for (var i = 0; i < $scope.model.timeOffs.length; i++) {

                        data.push({
                            name: $scope.model.timeOffs[i]._user.name,
                            date: $moment($scope.model.timeOffs[i].performedAt).format('L'),
                            type: $scope.model.timeOffs[i].timeOffType,
                            amount: $scope.model.timeOffs[i].amount
                        });
                    }

                    return data;
                };

                utils.getExportHeader = function () {
                    return ['Name', 'Date', 'Type', 'Amount'];
                };

                utils.getExportFileName = function () {
                    return 'timeoffs.csv';
                };
            };

            $scope.actions = {

                import: function () {
                    var modalInstance = $modal.open({
                        templateUrl: 'app/timeOffs/timeOffs.import.modal.html',
                        controller: 'TimeOffsImportModalCtrl',
                        size: 'lg',
                        resolve: {
                            currentUser: function () {
                                return authModel.currentUser;
                            },
                            currentOrganization: function () {
                                return authModel.currentOrganization;
                            }
                        }
                    }).result.then(function () {

                        messageCenterService.add('success', 'Import completed successfully.', {
                            timeout: 3000
                        });

                        $scope.actions.search();
                    }, function (err) {
                        messageCenterService.add('danger', err.data.error, {
                            timeout: 3000
                        });
                    });
                },
                memberFilterChange: function (user) {
                    if (user === 'all') {

                        $scope.model.membersFilter = [];
                        angular.forEach($scope.model.members, function (member) {
                            $scope.model.membersFilter.push(member._user._id);
                        });

                        $scope.model.membersFilterText = 'All';

                    } else {
                        $scope.model.membersFilterText = user.name;
                        $scope.model.membersFilter = [user._id];
                    }
                    $scope.utils.userDropdownOpened = false;
                    $scope.actions.search();
                },

                timeOffTypeChange: function (timeOffType) {
                    $scope.model.timeOffTypeFilter = timeOffType;
                    $scope.utils.dropdownOpened = false;
                },

                lastMonth: function () {
                    $scope.model.from = $moment().subtract('month', 1).startOf('month').toDate();
                    $scope.model.to = $moment().subtract('month', 1).endOf('month').toDate();

                    $scope.actions.search();
                },

                lastWeek: function () {
                    $scope.model.from = $moment().subtract('week', 1).startOf('week').toDate();
                    $scope.model.to = $moment().subtract('week', 1).endOf('week').toDate();

                    $scope.actions.search();
                },

                thisMonth: function () {
                    $scope.model.from = $moment().startOf('month').toDate();
                    $scope.model.to = $moment().endOf('month').toDate();

                    $scope.actions.search();
                },

                thisWeek: function () {
                    $scope.model.from = $moment().startOf('week').toDate();
                    $scope.model.to = $moment().endOf('week').toDate();

                    $scope.actions.search();
                },

                dateFromOpen: function ($event) {
                    $event.preventDefault();
                    $event.stopPropagation();

                    $scope.utils.fromOpened = true;
                },

                dateToOpen: function ($event) {
                    $event.preventDefault();
                    $event.stopPropagation();

                    $scope.utils.toOpened = true;
                },

                search: function () {
                    $scope.proxies.search.request();
                },

                edit: function (timeOff) {
                    //opens the modal
                    var modalInstance = $modal.open({
                        templateUrl: 'app/timeOffs/timeOffs.modal.html',
                        controller: 'TimeOffsModalCtrl',
                        resolve: {
                            currentUser: function () {
                                return authModel.currentUser;
                            },
                            timeOff: function () {
                                var to = {};
                                angular.copy(timeOff, to);
                                return to;
                            },
                            organizationSettings: function () {
                                return authModel.currentOrganization.settings
                            }
                        }
                    }).result.then(function (timeOff) {
                        //callback function
                        $scope.proxies.edit.request(timeOff);

                    }, function () {

                    });
                },

                delete: function (timeOff) {
                    $scope.proxies.delete.request(timeOff);
                },

                new: function () {
                    //opens the modal
                    var modalInstance = $modal.open({
                        templateUrl: 'app/timeOffs/timeOffs.modal.html',
                        controller: 'TimeOffsModalCtrl',
                        //size: 'lg',
                        resolve: {
                            currentUser: function () {
                                return authModel.currentUser;
                            },
                            timeOff: function () {
                                return null;
                            },
                            organizationSettings: function () {
                                return authModel.currentOrganization.settings
                            }
                        }
                    }).result.then(function (timeOff) {
                        //callback function
                        $scope.proxies.create.request(timeOff);

                    }, function () {

                    });
                }
            };

            $scope.proxies = new function () {
                var proxies = this;

                proxies.loadMembers = function () {
                    Members.query({
                        organizationId: authModel.currentOrganization._id
                    }).$promise.then(
                        function (members) {

                            $scope.model.members = members;
                        },
                        function (err) {
                            messageCenterService.add('danger', err.data.error, {
                                timeout: 3000
                            });
                        });
                };

                proxies.search = {
                    requestData: function () {

                        return {
                            from: $scope.model.from ? $moment($scope.model.from).startOf('day').toDate() : null,
                            organizationId: authModel.currentOrganization._id,
                            page: $scope.model.page,
                            timeOffType: $scope.model.timeOffTypeFilter === 'All' ? null : $scope.model.timeOffTypeFilter,
                            to: $scope.model.to ? $moment($scope.model.to).endOf('day').toDate() : null,
                            members: JSON.stringify($scope.model.membersFilter),
                            itemsPerPage: $scope.model.itemsPerPage
                        };
                    },
                    request: function () {
                        TimeOffs.query(proxies.search.requestData(), {}).$promise.then(
                            proxies.search.successCallback,
                            proxies.search.errorCallback);
                    },
                    successCallback: function (pagedResult) {
                        $scope.model.totalNumber = pagedResult.total;
                        $scope.model.timeOffs = pagedResult.items;
                        $scope.model.page = pagedResult.currentPage;
                    },
                    errorCallback: function (err) {
                        messageCenterService.add('danger', err.data.error, {
                            timeout: 3000
                        });
                    }
                };

                proxies.create = {
                    requestData: function (timeOff) {
                        return {
                            userId: authModel.currentUser._id,
                            timeOffType: timeOff.timeOffType,
                            amount: timeOff.amount,
                            performedAt: timeOff.performedAt
                        }
                    },
                    request: function (timeOff) {
                        TimeOffs.create({
                                organizationId: authModel.currentOrganization._id
                            },
                            proxies.create.requestData(timeOff)).$promise.then(
                            proxies.create.successCallback,
                            proxies.create.errorCallback);
                    },
                    successCallback: function () {
                        proxies.search.request();
                    },
                    errorCallback: function (err) {
                        messageCenterService.add('danger', err.data.error, {
                            timeout: 3000
                        });
                    }
                };

                proxies.edit = {
                    requestData: function (timeOff) {
                        return {
                            timeOffType: timeOff.timeOffType,
                            amount: timeOff.amount,
                            performedAt: timeOff.performedAt
                        }
                    },
                    request: function (timeOff) {

                        TimeOffs.update({
                                organizationId: authModel.currentOrganization._id,
                                timeOffId: timeOff._id
                            },
                            proxies.edit.requestData(timeOff)).$promise.then(
                            function () {
                                proxies.edit.successCallback(timeOff);
                            },
                            proxies.edit.errorCallback);
                    },
                    successCallback: function (timeOff) {

                        for (var i = 0; i < $scope.model.timeOffs.length; i++) {
                            if ($scope.model.timeOffs[i]._id === timeOff._id) {
                                $scope.model.timeOffs[i].timeOffType = timeOff.timeOffType;
                                $scope.model.timeOffs[i].amount = timeOff.amount;
                                $scope.model.timeOffs[i].performedAt = timeOff.performedAt;
                                break;
                            }
                        }

                    },
                    errorCallback: function (err) {
                        messageCenterService.add('danger', err.data.error, {
                            timeout: 3000
                        });
                    }
                };

                proxies.delete = {
                    requestData: function (timeOff) {

                    },
                    request: function (timeOff) {
                        TimeOffs.delete({
                                organizationId: authModel.currentOrganization._id,
                                timeOffId: timeOff._id
                            },
                            proxies.delete.requestData(timeOff)).$promise.then(
                            function () {
                                proxies.delete.successCallback(timeOff);
                            },
                            proxies.delete.errorCallback);
                    },
                    successCallback: function (timeOff) {
                        if ($scope.model.timeOffs.length === 1 && $scope.model.page > 1) {
                            $scope.model.page -= 1;
                        } else {
                            $scope.actions.search();
                        }
                    },
                    errorCallback: function (err) {
                        messageCenterService.add('danger', err.data.error, {
                            timeout: 3000
                        });
                    }
                };
            };

            $scope.proxies.search.request();
            $scope.proxies.loadMembers();
        });


text:
/* @test
   @summary Test SoftTuning constructor */

import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Patch;
import javax.sound.sampled.*;

import com.sun.media.sound.*;

public class NewSoftTuningByteArray {

	private static void assertEquals(Object a, Object b) throws Exception
	{
		if(!a.equals(b))
			throw new RuntimeException("assertEquals fails!");
	}

	private static void assertTrue(boolean value) throws Exception
	{
		if(!value)
			throw new RuntimeException("assertTrue fails!");
	}

	public static void main(String[] args) throws Exception {
		// RealTime: Scale/Octave tuning in 1-byte format
		int[] msg = {0xf0,0x7f,0x7f,0x08,0x08,0x03,0x7f,0x7f,
				5,10,15,20,25,30,35,40,45,50,51,52,
				0xf7};
		int[] oct = {5,10,15,20,25,30,35,40,45,50,51,52};
		byte[] bmsg = new byte[msg.length];
		for (int i = 0; i < bmsg.length; i++)
			bmsg[i] = (byte)msg[i];
		SoftTuning tuning = new SoftTuning(bmsg);
		double[] tunings = tuning.getTuning();
		for (int i = 0; i < tunings.length; i++)
			assertTrue(Math.abs(tunings[i]-(i*100 + (oct[i%12]-64))) < 0.00001);
	}
}


text:
var assert = require('assert'),
	MockRequest = require('./index');

var tests = [

	function is_writable_and_readable(done) {
		var req = new MockRequest({
			method: 'POST',
		});

		assert(req.readable);
		assert(req.writable);

		done();
	},

	function default_options(done) {
		var req = new MockRequest();

		assert.equal(typeof req.url, 'string');
		assert.equal(req.method, 'GET');
		assert.deepEqual(req.headers, {});
		assert.deepEqual(req.rawHeaders, []);

		done()
	},

	function parses_headers(done) {
		var req = new MockRequest({
			headers: {
				'Content-Type': 'text/plain',
				'Content-Length': 10
			}
		});

		assert.equal(req.headers['content-type'], 'text/plain');
		assert.equal(req.headers['content-length'], '10');
		assert.deepEqual(req.rawHeaders, [
			'Content-Type',
			'text/plain',
			'Content-Length',
			'10'
		]);

		done()
	},

	function undefined_header(done) {
		var req = new MockRequest({
			headers: {
				'foo': undefined
			}
		});

		assert.equal(req.rawHeaders.indexOf('foo'), -1);
		assert.equal(req.headers['foo'], undefined);

		done()
	},

	function automatically_ends_for_bodiless(done) {
		var ends = {
			GET: true,
			HEAD: true,
			DELETE: true,
			POST: false,
			PUT: false,
			WHATEVS: false
		};

		Object.keys(ends).forEach(function(method) {
			var req = new MockRequest({
				method: method
			});

			assert.equal(req._writableState.ended, ends[method], method);
		});

		done();
	},

	function string_body(done) {
		var req = new MockRequest({
			method: 'POST'
		});

		req.write('hello', 'utf8');
		req.end();

		req.setEncoding('utf8');
		req.once('readable', function() {
			var d = this.read();
			assert.equal(d, 'hello');
			done();
		});
	},

	function json_body(done) {
		var req = new MockRequest({
			method: 'POST'
		});

		req.write({
			hello: 3
		});
		req.end();

		req.setEncoding('utf8');
		req.once('readable', function() {
			var d = this.read();
			assert.deepEqual(d, '{"hello":3}');
			done();
		});
	},

	function buffer_body(done) {
		var req = new MockRequest({
			method: 'POST'
		});

		var buf = new Buffer('yo', 'utf8');
		req.write(buf);
		req.end();

		req.once('readable', function() {
			var d = this.read();
			assert.equal(d, buf);
			done();
		});
	},

	function fails(done) {
		var req = new MockRequest({
			method: 'POST'
		});

		var err = new Error('Oops');
		req._fail(err);

		req.on('error', function(err2) {
			assert.equal(err, err2);
			done();
		});

		req.write('yo');
	}

];

var doneCount = 0;
tests.forEach(function(test) {
	test(done.bind(null, test.name));
});

function done(name) {
	console.log(name);
	doneCount++;

	if (doneCount === tests.length) {
		console.log('>> All tests passed');
		return process.exit(0);
	}
}


text:
namespace Community.Owin.Security
{
    using System.Collections.Generic;
    using System.Security.Claims;

    using Microsoft.Owin.Security;
    using Microsoft.Owin.Security.Provider;

    public class OAuth2AuthenticatedContext : BaseContext
    {
        public OAuth2AuthenticatedContext(
            string accessToken,
            string userId,
            string userName,
            IDictionary<string, object> environment)
            : base(environment)
        {
            AccessToken = accessToken;
            UserId = userId;
            UserName = userName;
        }

        public string AccessToken
        {
            get;
            private set;
        }

        public string UserId { get; private set; }

        public string UserName { get; private set; }

        public AuthenticationExtra Extra { get; set; }

        public ClaimsIdentity Identity { get; set; }
    }
}


text:
require 'spec_helper'

describe 'totpcgi::install', :type => :class do
  # set some default good params so we can override with bad ones in
  # test
    let(:facts) {
    {
      :fqdn                   => 'test.example.com',
      :hostname               => 'test',
      :ipaddress              => '192.168.0.1',
      :operatingsystem        => 'CentOS',
      :operatingsystemrelease => '7',
      :osfamily               => 'RedHat'
    }
  }

  # we do not have default values so the class should fail compile
  context 'with defaults for all parameters' do
    let(:params) {{}}

    it do
      expect {
        should compile
      }.to raise_error(RSpec::Expectations::ExpectationNotMetError,
        /Must pass /)
    end
  end

   context 'with basic init defaults' do
         let(:params) {
      {
        'install_totpcgi' => true,
        'install_qrcode'  => true,
      }
    }
    it { should contain_class('totpcgi::install') }
    it { should contain_package('totpcgi') }
    it { should contain_package('totpcgi-selinux') }
    it { should contain_package('totpcgi-provisioning') }
   end
end

# vim: sw=2 ts=2 sts=2 et :


text:
@interface ViewController () <UICollectionViewDelegate, UICollectionViewDataSource>
@property (weak, nonatomic) IBOutlet UICollectionView *collectionView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib

    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc]init];
    layout.itemSize = CGSizeMake(100, 100)
    ;
    layout.minimumLineSpacing = 0;
    layout.minimumInteritemSpacing = 0;
    layout.scrollDirection = UICollectionViewScrollDirectionVertical;
    self.collectionView.collectionViewLayout = layout;
    self.collectionView.delegate = self;
    self.collectionView.dataSource = self;

    [self.collectionView registerNib:[UINib nibWithNibName:@"CollectionImageViewCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:NSStringFromClass([CollectionImageViewCell class])];
}

#pragma mark -
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return 6;
}

// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CollectionImageViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CollectionImageViewCell" forIndexPath:indexPath];
    cell.imageView.image = [UIImage imageNamed:@"game1.png"];
    return cell;
}

@end


text:
package de.micromata.jira.rest.core.domain.meta;

import com.google.gson.annotations.Expose;
import de.micromata.jira.rest.core.domain.IssuetypeBean;

/**
 * Created by cschulc on 16.03.16.
 */
public class IssueTypeMetaBean extends IssuetypeBean {

    @Expose
    private FieldsMetaBean fields;

    public FieldsMetaBean getFields() {
        return fields;
    }

    public void setFields(FieldsMetaBean fields) {
        this.fields = fields;
    }
}


text:
"""Rules for NonnegativeInts."""

__author__ = 'Sean Lip'

from extensions.rules import base

class Equals(base.NonnegativeIntRule):
    description = 'is equal to {{x|NonnegativeInt}}'

    def _evaluate(self, subject):
        return self._fuzzify_truth_value(subject == self.x)


text:
package core

import (
	"context"
	"fmt"
	"reflect"
	"testing"

	"github.com/google/trillian/merkle/compact"
	"github.com/google/trillian/merkle/rfc6962"
	"github.com/google/trillian/merkle/testonly"
	"github.com/google/trillian/skylog/storage"
)

// TODO(pavelkalinnikov): Use GoMock instead.
type mockTreeWriter struct {
	calls [][]storage.Node
}

func (t *mockTreeWriter) Write(ctx context.Context, nodes []storage.Node) error {
	t.calls = append(t.calls, nodes)
	return nil
}

func (t *mockTreeWriter) verify(nodes []storage.Node) error {
	if len(t.calls) == 0 && len(nodes) == 0 {
		return nil
	}
	if got, want := len(t.calls), 1; got != want {
		return fmt.Errorf("wrong number of calls %d, want %d", got, want)
	}
	if got, want := t.calls[0], nodes; !reflect.DeepEqual(got, want) {
		return fmt.Errorf("got nodes: %+v\nwant: %+v", got, want)
	}
	return nil
}

func TestBuildWorker(t *testing.T) {
	hashes := testonly.NodeHashes()
	n := len(hashes[0])
	if got, want := n, 8; got != want {
		t.Fatalf("prerequisite: testonly.NodeHashes() returned %d leaves, want %d", got, want)
	}
	node := func(level uint, index uint64) storage.Node {
		return storage.Node{ID: compact.NewNodeID(level, index), Hash: hashes[level][index]}
	}
	adds := [][]storage.Node{
		{node(0, 0)},
		{node(0, 1), node(1, 0)},
		{node(0, 2)},
		{node(0, 3), node(1, 1), node(2, 0)},
		{node(0, 4)},
		{node(0, 5), node(1, 2)},
		{node(0, 6)},
		{node(0, 7), node(1, 3), node(2, 1), node(3, 0)},
	}

	rf := &compact.RangeFactory{Hash: rfc6962.DefaultHasher.HashChildren}
	var wantAdds []storage.Node
	for end := 0; end <= n; end++ {
		// TODO(pavelkalinnikov): Add tests where RangeStart > 0.
		t.Run(fmt.Sprintf("0:%d", end), func(t *testing.T) {
			var tw mockTreeWriter
			bw := NewBuildWorker(&tw, rf)
			bj := BuildJob{RangeStart: 0, Hashes: hashes[0][0:end]}
			if _, err := bw.Process(context.Background(), bj); err != nil {
				t.Fatalf("Process: %v", err)
			}
			if err := tw.verify(wantAdds); err != nil {
				t.Errorf("verify: %v", err)
			}
		})
		if end < n {
			wantAdds = append(wantAdds, adds[end]...)
		}
	}
}


text:
using MVVM.ViewModel.Events;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using MVVM.ViewModel.Annotations;

namespace MVVM.ViewModel.Cliente
{
    //Aqui ficaria toda a programação da Tela.
    //MODEL são das dados que vão ou vem das tabelas
    //VIEWMODEL são dados que vão ou vem da tela.

    //Tecnicas Específicas:

    //Binding - sincronização de dados
    //Commands - Eventos (click do botão)
    //Notifications - Mandando um sinal (notificação para a tela)

    public sealed class CadastrarViewModel:INotifyPropertyChanged
    {
        #region Constructor
        public CadastrarViewModel()
        {
            Click_Limpar = new DispararClick(Limpar);
            Click_Cadastrar = new DispararClick(Cadastrar);
        }
        #endregion

        #region Properties

        private string _nome;

        public string Nome
        {
            get
            {
                return _nome;
            }

            set
            {
                _nome = value;

                PropertyChanged(this,new PropertyChangedEventArgs("Nome"));
            }
        }

        private string _email;

        public string Email
        {
            get
            {
                return _email;
            }
            set
            {
                _email = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Email"));
            }
        }

        private string _telefone;
        public string Telefone {
            get
            {
                return _telefone;
            }

            set
            {
                _telefone = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Telefone"));
            }
        }

        private DateTime? _dataNascimento;

        public DateTime? DataNascimento
        {
            get
            {
                return _dataNascimento;
            }
            set
            {
                _dataNascimento = value;
                PropertyChanged(this, new PropertyChangedEventArgs("DataNascimento"));
            }
        }

        #endregion Properties

        #region Commands

        public ICommand Click_Limpar { get; set; }

        public ICommand Click_Cadastrar { get; set; }

        public void Limpar()
        {
            Nome = string.Empty;
            Email = string.Empty;
            Telefone = string.Empty;
        }

        public void Cadastrar()
        {
            //lógica para inserir o cliente no BD
            var cliente = new Model.Cliente(Nome, Email,Telefone, DataNascimento);

            Debug.WriteLine(cliente.Nome);
            Debug.WriteLine(cliente.Email);
            Debug.WriteLine(cliente.Telefone);
            Debug.WriteLine(cliente.DataNascimento.Value.ToShortDateString());
        }

        #endregion Commands

        #region NotifyEvent
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion
    }
}


text:
package main

// This file contains a demo of using the Accountstatuses service by
// retrieving the account status for the requested merchant ID and
// printing out any data quality issues (if any), along with which
// products are impacted.

import (
	"fmt"

	"golang.org/x/net/context"
	"google.golang.org/api/content/v2.1"
)

func accountstatusesDemo(ctx context.Context, service *content.APIService, config *merchantInfo) {
	accountstatuses := content.NewAccountstatusesService(service)

	fmt.Printf("Getting account status:\n")
	accountStatus, err := accountstatuses.Get(config.MerchantID, config.MerchantID).Do()
	if err != nil {
		dumpAPIErrorAndStop(err, "Getting account status failed")
	}
	printAccountStatus(accountStatus)

	if !config.IsMCA {
		return
	}

	fmt.Printf("Printing statuses of subaccounts of %d:\n", config.MerchantID)
	if err := accountstatuses.List(config.MerchantID).Pages(ctx, printAccountStatusesPage); err != nil {
		dumpAPIErrorAndStop(err, "Listing subaccount statuses failed")
	}
	fmt.Println("")
}

func printAccountStatusesPage(res *content.AccountstatusesListResponse) error {
	for _, as := range res.Resources {
		printAccountStatus(as)
	}
	return nil
}

func printAccountStatus(accountStatus *content.AccountStatus) {
	fmt.Printf(" - Account %s\n", accountStatus.AccountId)

	issueCount := 0

	for _, accountStatusProduct := range accountStatus.Products {
		for _, itemLevelIssue := range accountStatusProduct.ItemLevelIssues {
			issueCount++
			fmt.Printf("  - Issue: [%s] '%s' affecting %d items\n",
				itemLevelIssue.Code,
				itemLevelIssue.Detail,
				itemLevelIssue.NumItems)
		}
	}

	fmt.Printf("Total number of data quality issues: %d\n", issueCount)
}


text:
require 'spec_helper'

RSpec.describe Numo::Linalg do
  describe 'solve' do
    let(:m) { 5 }
    let(:n) { 3 }
    let(:mat_a) { rand_square_real_mat(m) }
    let(:mat_b) { rand_rect_real_mat(m, n) }
    let(:vec_b) { rand_real_vec(m) }
    let(:mat_c) { rand_square_complex_mat(m) }
    let(:mat_d) { rand_rect_complex_mat(m, n) }
    let(:vec_d) { rand_complex_vec(m) }
    let(:mat_s) { rand_symmetric_mat(m) }
    let(:mat_h) { rand_hermitian_mat(m) }
    let(:mat_p) { mat_s.dot(mat_s.transpose) }
    let(:mat_q) { mat_h.dot(mat_h.transpose.conj) }

    it 'raises ArgumentError given a invalid driver option' do
      expect { described_class.solve(mat_a, vec_b, driver: 'foo') }.to raise_error(ArgumentError)
    end

    it 'raises ShapeError when the number of rows of matrices are different' do
      expect { described_class.solve(mat_a, mat_b.transpose) }.to raise_error(Numo::NArray::ShapeError)
    end

    it 'raises ShapeError given a rectangular matrix as matrix A' do
      expect { described_class.solve(mat_b, mat_a) }.to raise_error(Numo::NArray::ShapeError)
    end

    it 'solves the linear equation A x = b with a square real matrix A' do
      vec_x = described_class.solve(mat_a, vec_b)
      expect((mat_a.dot(vec_x) - vec_b).abs.max).to be < ERR_TOL
      mat_x = described_class.solve(mat_a, mat_b)
      expect((mat_a.dot(mat_x) - mat_b).abs.max).to be < ERR_TOL
      vec_x = described_class.solve(mat_a, vec_d)
      expect((mat_a.dot(vec_x) - vec_d).abs.max).to be < ERR_TOL
      mat_x = described_class.solve(mat_a, mat_d)
      expect((mat_a.dot(mat_x) - mat_d).abs.max).to be < ERR_TOL
    end

    it 'solves the linear equation A x = b with a square complex matrix A' do
      vec_x = described_class.solve(mat_c, vec_b)
      expect((mat_c.dot(vec_x) - vec_b).abs.max).to be < ERR_TOL
      mat_x = described_class.solve(mat_c, mat_b)
      expect((mat_c.dot(mat_x) - mat_b).abs.max).to be < ERR_TOL
      vec_x = described_class.solve(mat_c, vec_d)
      expect((mat_c.dot(vec_x) - vec_d).abs.max).to be < ERR_TOL
      mat_x = described_class.solve(mat_c, mat_d)
      expect((mat_c.dot(mat_x) - mat_d).abs.max).to be < ERR_TOL
    end

    it 'solves the linear equation A x = b with a symmetric matrix A' do
      vec_x = described_class.solve(mat_s, vec_b, driver: 'sym')
      expect((mat_s.dot(vec_x) - vec_b).abs.max).to be < ERR_TOL
      mat_x = described_class.solve(mat_s, mat_b, driver: 'sym')
      expect((mat_s.dot(mat_x) - mat_b).abs.max).to be < ERR_TOL
      vec_x = described_class.solve(mat_s, vec_d, driver: 'sym')
      expect((mat_s.dot(vec_x) - vec_d).abs.max).to be < ERR_TOL
      mat_x = described_class.solve(mat_s, mat_d, driver: 'sym')
      expect((mat_s.dot(mat_x) - mat_d).abs.max).to be < ERR_TOL
    end

    it 'solves the linear equation A x = b with a hermitian matrix A' do
      vec_x = described_class.solve(mat_h, vec_b, driver: 'her')
      expect((mat_h.dot(vec_x) - vec_b).abs.max).to be < ERR_TOL
      mat_x = described_class.solve(mat_h, mat_b, driver: 'her')
      expect((mat_h.dot(mat_x) - mat_b).abs.max).to be < ERR_TOL
      vec_x = described_class.solve(mat_h, vec_d, driver: 'her')
      expect((mat_h.dot(vec_x) - vec_d).abs.max).to be < ERR_TOL
      mat_x = described_class.solve(mat_h, mat_d, driver: 'her')
      expect((mat_h.dot(mat_x) - mat_d).abs.max).to be < ERR_TOL
    end

    it 'solves the linear equation A x = b with a symmetric positive-definite matrix A' do
      vec_x = described_class.solve(mat_p, vec_b, driver: 'pos')
      expect((mat_p.dot(vec_x) - vec_b).abs.max).to be < ERR_TOL
      mat_x = described_class.solve(mat_p, mat_b, driver: 'pos')
      expect((mat_p.dot(mat_x) - mat_b).abs.max).to be < ERR_TOL
      vec_x = described_class.solve(mat_p, vec_d, driver: 'pos')
      expect((mat_p.dot(vec_x) - vec_d).abs.max).to be < ERR_TOL
      mat_x = described_class.solve(mat_p, mat_d, driver: 'pos')
      expect((mat_p.dot(mat_x) - mat_d).abs.max).to be < ERR_TOL
    end

    it 'solves the linear equation A x = b with a hermitian positive-definite matrix A' do
      vec_x = described_class.solve(mat_q, vec_b, driver: 'pos')
      expect((mat_q.dot(vec_x) - vec_b).abs.max).to be < ERR_TOL
      mat_x = described_class.solve(mat_q, mat_b, driver: 'pos')
      expect((mat_q.dot(mat_x) - mat_b).abs.max).to be < ERR_TOL
      vec_x = described_class.solve(mat_q, vec_d, driver: 'pos')
      expect((mat_q.dot(vec_x) - vec_d).abs.max).to be < ERR_TOL
      mat_x = described_class.solve(mat_q, mat_d, driver: 'pos')
      expect((mat_q.dot(mat_x) - mat_d).abs.max).to be < ERR_TOL
    end
  end
end


text:
namespace Google.Cloud.Iot.V1.Snippets
{
    // [START cloudiot_v1_generated_DeviceManager_ModifyCloudToDeviceConfig_async]
    using Google.Cloud.Iot.V1;
    using Google.Protobuf;
    using System.Threading.Tasks;

    public sealed partial class GeneratedDeviceManagerClientSnippets
    {
        /// <summary>Snippet for ModifyCloudToDeviceConfigAsync</summary>
        /// <remarks>
        /// This snippet has been automatically generated and should be regarded as a code template only.
        /// It will require modifications to work:
        /// - It may require correct/in-range values for request initialization.
        /// - It may require specifying regional endpoints when creating the service client as shown in
        ///   https://cloud.google.com/dotnet/docs/reference/help/client-configuration#endpoint.
        /// </remarks>
        public async Task ModifyCloudToDeviceConfigRequestObjectAsync()
        {
            // Create client
            DeviceManagerClient deviceManagerClient = await DeviceManagerClient.CreateAsync();
            // Initialize request argument(s)
            ModifyCloudToDeviceConfigRequest request = new ModifyCloudToDeviceConfigRequest
            {
                DeviceName = DeviceName.FromProjectLocationRegistryDevice("[PROJECT]", "[LOCATION]", "[REGISTRY]", "[DEVICE]"),
                VersionToUpdate = 0L,
                BinaryData = ByteString.Empty,
            };
            // Make the request
            DeviceConfig response = await deviceManagerClient.ModifyCloudToDeviceConfigAsync(request);
        }
    }
    // [END cloudiot_v1_generated_DeviceManager_ModifyCloudToDeviceConfig_async]
}


text:
A parameter type is missing an explicit lifetime bound and may not live long
enough.

Erroneous code example:

```compile_fail,E0309
// This won't compile because the applicable impl of
// `SomeTrait` (below) requires that `T: 'a`, but the struct does
// not have a matching where-clause.
struct Foo<'a, T> {
    foo: <T as SomeTrait<'a>>::Output,
}

trait SomeTrait<'a> {
    type Output;
}

impl<'a, T> SomeTrait<'a> for T
where
    T: 'a,
{
    type Output = u32;
}
```

The type definition contains some field whose type requires an outlives
annotation. Outlives annotations (e.g., `T: 'a`) are used to guarantee that all
the data in `T` is valid for at least the lifetime `'a`. This scenario most
commonly arises when the type contains an associated type reference like
`<T as SomeTrait<'a>>::Output`, as shown in the previous code.

There, the where clause `T: 'a` that appears on the impl is not known to be
satisfied on the struct. To make this example compile, you have to add a
where-clause like `T: 'a` to the struct definition:

```
struct Foo<'a, T>
where
    T: 'a,
{
    foo: <T as SomeTrait<'a>>::Output
}

trait SomeTrait<'a> {
    type Output;
}

impl<'a, T> SomeTrait<'a> for T
where
    T: 'a,
{
    type Output = u32;
}
```


text:
from setupext import find_namespace_packages, setup

setup.register_pth_hook("setup_mplcursors_pth.py", "mplcursors.pth")

setup(
    name="mplcursors",
    description="Interactive data selection cursors for Matplotlib.",
    long_description=open("README.rst", encoding="utf-8").read(),
    long_description_content_type="text/x-rst",
    author="Antony Lee",
    url="https://github.com/anntzer/mplcursors",
    license="MIT",
    classifiers=[
        "Development Status :: 4 - Beta",
        "Framework :: Matplotlib",
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python :: 3",
    ],
    packages=find_namespace_packages("lib"),
    package_dir={"": "lib"},
    python_requires=">=3.6",
    setup_requires=["setuptools_scm"],
    use_scm_version=lambda: {  # xref __init__.py
        "version_scheme": "post-release",
        "local_scheme": "node-and-date",
        "write_to": "lib/mplcursors/_version.py",
    },
    install_requires=[
        "matplotlib>=3.1",
    ],
    extras_require={
        "docs": [
            "pandas",
            "pydata_sphinx_theme!=0.10.1",
            "sphinx",
            "sphinx-gallery",
        ],
    },
)


text:
/**
 * Call: app.add
 *
 * @author Zongmin Lei <leizongmin@gmail.com>
 */

module.exports = function (ns, debug) {
  return function (params, callback) {

    debug('add: [%s] %s', params.email, params.display_name);
    var app_list = ns('model.app_list');

    app_list.getByName(params.name, function (err, user) {
      if (err) return callback(err);
      if (user) return callback(new Error('App name "' + params.name + '" already exist'));

      app_list.add(params, callback);
    });

  };
};


text:
'use strict';

angular.module('issueTracker.services.notifier', [])
    .factory('notificationService', [
        function () {
            return {
                showSuccess: function (msg) {
                    noty({
                            theme: 'relax',
                            text: msg,
                            type: 'information',
                            layout: 'topCenter',
                            timeout: 3000,
                            closeWith: ['click']
                        }
                    );
                },
                showError: function (msg, serverError) {
                    var errors = [];
                    if (serverError && serverError.data.error_description) {
                        errors.push(serverError.data.error_description);
                    }
                    if (serverError && serverError.data.Message) {
                        errors.push(serverError.data.Message);
                    }
                    if (serverError && serverError.data.ModelState) {
                        var modelStateErrors = serverError.data.ModelState;
                        for (var propertyName in modelStateErrors) {
                            var errorMessages = modelStateErrors[propertyName];
                            var trimmedName =
                                propertyName.substr(propertyName.indexOf('.') + 1);
                            for (var i = 0; i < errorMessages.length; i++) {
                                var currentError = errorMessages[i];
                                errors.push(trimmedName + ' - ' + currentError);
                            }
                        }
                    }
                    if (errors.length > 0) {
                        msg = msg + ":
" + errors.join("
");
                    }
                    noty({
                            theme: 'relax',
                            text: msg,
                            type: 'error',
                            layout: 'topCenter',
                            timeout: 5000,
                            closeWith: ['click']
                        }
                    );
                }
            }
        }
    ]);


text:
package com.lin.web.dto;

import java.io.Serializable;

@SuppressWarnings("serial")
public class ProductDTO implements Serializable{

	private long id;
	private String name;
	private double offeredRate;
	private long availableImpressions;
	private long matchedImpressions;
	private long allocatedImpressions;
	private double allocatedBudget;
	private double revenueSharePercent;
	private double payout;
	private double netRate;
	private String placementId;
	private String partnerName;
	private String partnerAdserverId;
	private String partnerId;
	private String partnerLogo;

	public ProductDTO(){

	}

	public ProductDTO(long id, String name, double offeredRate,
			long availableImpressions, long allocatedImpressions,
			double allocatedBudget, double revenueSharePercent, double payout,
			double netRate, String placementId, String partnerName,
			String partnerAdserverId, String partnerId){
		this(id, name, offeredRate, availableImpressions, 0, allocatedImpressions,  allocatedBudget, revenueSharePercent, payout, netRate, placementId, partnerName, partnerAdserverId, partnerId);

	}
	public ProductDTO(long id, String name, double offeredRate,
			long availableImpressions, long matchedImpressions, long allocatedImpressions,
			double allocatedBudget, double revenueSharePercent, double payout,
			double netRate, String placementId, String partnerName,
			String partnerAdserverId, String partnerId) {
		this.id = id;
		this.name = name;
		this.offeredRate = offeredRate;
		this.availableImpressions = availableImpressions;
		this.matchedImpressions = matchedImpressions;
		this.allocatedImpressions = allocatedImpressions;
		this.allocatedBudget = allocatedBudget;
		this.revenueSharePercent = revenueSharePercent;
		this.payout = payout;
		this.netRate = netRate;
		this.placementId = placementId;
		this.partnerName = partnerName;
		this.partnerAdserverId = partnerAdserverId;
		this.partnerId = partnerId;
	}

	@Override
	public String toString() {
		return "ProductDTO [id=" + id + ", name=" + name + ", offeredRate="
				+ offeredRate + ", availableImpressions="
				+ availableImpressions + ", allocatedImpressions="
				+ allocatedImpressions + ", allocatedBudget=" + allocatedBudget
				+ ", revenueSharePercent=" + revenueSharePercent + ", payout="
				+ payout + ", netRate=" + netRate + ", placementId="
				+ placementId + ", partnerName=" + partnerName
				+ ", partnerAdserverId=" + partnerAdserverId + ", partnerId="
				+ partnerId + ", partnerId="+partnerLogo+"]";
	}

	public long getId() {
		return id;
	}
	public void setId(long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getOfferedRate() {
		return offeredRate;
	}
	public void setOfferedRate(double offeredRate) {
		this.offeredRate = offeredRate;
	}
	public long getAvailableImpressions() {
		return availableImpressions;
	}
	public void setAvailableImpressions(long availableImpressions) {
		this.availableImpressions = availableImpressions;
	}
	public long getAllocatedImpressions() {
		return allocatedImpressions;
	}
	public void setAllocatedImpressions(long allocatedImpressions) {
		this.allocatedImpressions = allocatedImpressions;
	}
	public double getAllocatedBudget() {
		return allocatedBudget;
	}
	public void setAllocatedBudget(double allocatedBudget) {
		this.allocatedBudget = allocatedBudget;
	}
	public double getRevenueSharePercent() {
		return revenueSharePercent;
	}
	public void setRevenueSharePercent(double revenueSharePercent) {
		this.revenueSharePercent = revenueSharePercent;
	}
	public double getPayout() {
		return payout;
	}
	public void setPayout(double payout) {
		this.payout = payout;
	}
	public double getNetRate() {
		return netRate;
	}
	public void setNetRate(double netRate) {
		this.netRate = netRate;
	}
	public String getPlacementId() {
		return placementId;
	}
	public void setPlacementId(String placementId) {
		this.placementId = placementId;
	}
	public String getPartnerName() {
		return partnerName;
	}
	public void setPartnerName(String partnerName) {
		this.partnerName = partnerName;
	}
	public String getPartnerAdserverId() {
		return partnerAdserverId;
	}
	public void setPartnerAdserverId(String partnerAdserverId) {
		this.partnerAdserverId = partnerAdserverId;
	}

	public String getPartnerId() {
		return partnerId;
	}

	public void setPartnerId(String partnerId) {
		this.partnerId = partnerId;
	}

	public String getPartnerLogo() {
		return partnerLogo;
	}

	public void setPartnerLogo(String partnerLogo) {
		this.partnerLogo = partnerLogo;
	}

	public long getMatchedImpressions() {
		return matchedImpressions;
	}

	public void setMatchedImpressions(long matchedImpressions) {
		this.matchedImpressions = matchedImpressions;
	}

}


text:
users Cookbook CHANGELOG
========================
This file is used to list changes made in each version of the users cookbook.

v1.7.0 (2014-02-14)
-------------------
[COOK-4139] - users_manage resource always notifies
[COOK-4078] - users cookbook fails in why-run mode for .ssh directory
[COOK-3959] - Add support for Mac OS X to users cookbook

v1.6.0
------
### Bug
- **[COOK-3744](https://tickets.opscode.com/browse/COOK-3744)** - Allow passing an action option via the `data_bag` to the user resource

v1.5.2
------
### Bug
- **[COOK-3215](https://tickets.opscode.com/browse/COOK-3215)** - Make `group_id` optional

v1.5.0
------
- [COOK-2427] - Mistakenly released instead of sudo :-).

v1.4.0
------
- [COOK-2479] - Permit users cookbook to work with chef-solo if edelight/chef-solo-search is installed
- [COOK-2486] - specify precedence when setting node attribute

v1.3.0
------
- [COOK-1842] - allow specifying private SSH keys
- [COOK-2021] - Empty default recipe for including users LWRPs

v1.2.0
------
- [COOK-1398] - Provider manage.rb ignores username attribute
- [COOK-1582] - ssh_keys should take an array in addition to a string separated by new lines

v1.1.4
------
- [COOK-1396] - removed users get recreated
- [COOK-1433] - resolve foodcritic warnings
- [COOK-1583] - set passwords for users

v1.1.2
------
- [COOK-1076] - authorized_keys template not found in another cookbook

v1.1.0
------
- [COOK-623] - LWRP conversion


text:
using Microsoft.Extensions.Configuration;

namespace Sif.Framework.Settings
{
    /// <summary>
    /// This class represents Consumer application settings that are stored in a database.
    /// </summary>
    public class ConsumerSettings : FrameworkSettings
    {
        /// <summary>
        /// Prefix used to indicate Consumer specific application settings.
        /// </summary>
        protected override string SettingsPrefix => "consumer.";

        /// <summary>
        /// Create an instance of this class based upon the configuration provided.
        /// </summary>
        /// <param name="configuration">Application configuration properties.</param>
        public ConsumerSettings(IConfiguration configuration) : base(configuration)
        {
        }
    }
}


text:
class CreateBuilds < ActiveRecord::Migration
  def change
    create_table :builds do |t|
      t.integer :build_number
      t.integer :total_test
      t.integer :skipped_test

      t.timestamps
    end
  end
end


text:
package alluxio.master.journal;

import alluxio.exception.ExceptionMessage;
import alluxio.proto.journal.File.AddMountPointEntry;
import alluxio.proto.journal.Journal.JournalEntry;

import com.google.protobuf.Message;
import com.google.protobuf.UnknownFieldSet;
import com.google.protobuf.UnknownFieldSet.Field;
import org.junit.Assert;
import org.junit.Test;
/**
 * Unit tests for {@link JournalProtoUtils}.
 */
public final class JournalProtoUtilsTest {

  /**
   * Tests that format returns the sub-message contained in a JournalEntry.
   */
  @Test
  public void getMessage() {
    AddMountPointEntry addMountEntry = AddMountPointEntry.newBuilder().build();
    JournalEntry entry = JournalEntry.newBuilder()
        .setAddMountPoint(addMountEntry)
        .build();
    Message message = JournalProtoUtils.unwrap(entry);
    Assert.assertTrue(message instanceof AddMountPointEntry);
    Assert.assertEquals(message, addMountEntry);
  }

  /**
   * Tests that the right exception is thrown when no sub-message is set for a JournalEntry.
   */
  @Test
  public void getUnknownMessage() {
    JournalEntry unknownEntry = JournalEntry.newBuilder().build();
    unknownEntry = unknownEntry.toBuilder()
        .setUnknownFields(
            UnknownFieldSet.newBuilder().addField(46264, Field.newBuilder().build()).build())
        .build();
    try {
      JournalProtoUtils.unwrap(unknownEntry);
      Assert.fail("format() should fail when no messages is set");
    } catch (RuntimeException e) {
      Assert.assertEquals(ExceptionMessage.NO_ENTRY_TYPE.getMessage("[46264]"), e.getMessage());
    }
  }
}


text:
package com.sind.projectx.repository.place;

import com.sind.projectx.domain.place.PlaceNetwork;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

/**
 * @author Dmytro Bekuzarov
 */
@Repository
public interface PlaceNetworkRepository extends MongoRepository<PlaceNetwork, String> {

    PlaceNetwork findByIdAndOrganizationId(String id, String organizationId);
}


text:
Difficulty: Easy

https://leetcode.com/problems/construct-the-rectangle/

For a web developer, it is very important to know how to design a web page's size. So, given a specific rectangular web page's area, your job by now is to design a rectangular web page, whose length L and width W satisfy the following requirements:

1. The area of the rectangular web page you designed must equal to the given target area.

2. The width W should not be larger than the length L, which means L >= W.

3. The difference between length L and width W should be as small as possible.

You need to output the length L and the width W of the web page you designed in sequence.

Example:
```
Input: 4
Output: [2, 2]
Explanation: The target area is 4, and all the possible ways to construct it are [1,4], [2,2], [4,1].
But according to requirement 2, [1,4] is illegal; according to requirement 3,  [4,1] is not optimal compared to [2,2]. So the length L is 2, and the width W is 2.
```

Note:
1. The given area won't exceed 10,000,000 and is a positive integer
2. The web page's width and length you designed must be positive integers.