<commit_before>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef __STOUT_OS_POSIX_HPP__
#define __STOUT_OS_POSIX_HPP__

// This file contains Linux-only OS utilities.
#ifndef __linux__
#error "stout/os/linux.hpp is only available on Linux systems."
#endif

#include <sys/types.h> // For pid_t.

#include <list>
#include <queue>
#include <set>
#include <string>

#include <stout/error.hpp>
#include <stout/foreach.hpp>
#include <stout/lambda.hpp>
#include <stout/option.hpp>
#include <stout/proc.hpp>
#include <stout/result.hpp>
#include <stout/try.hpp>

#include <stout/os/pagesize.hpp>
#include <stout/os/process.hpp>

namespace os {

// Helper for clone() which expects an int(void*).
static int childMain(void* _func)
{
  const lambda::function<int()>* func =
    static_cast<const lambda::function<int()>*> (_func);

  return (*func)();
}

inline pid_t clone(const lambda::function<int()>& func, int flags)
{
  // Stack for the child.
  // - unsigned long long used for best alignment.
  // - 8 MiB appears to be the default for "ulimit -s" on OSX and Linux.
  //
  // NOTE: We need to allocate the stack dynamically. This is because
  // glibc's 'clone' will modify the stack passed to it, therefore the
  // stack must NOT be shared as multiple 'clone's can be invoked
  // simultaneously.
  int stackSize = 8 * 1024 * 1024;
  unsigned long long *stack =
    new unsigned long long[stackSize/sizeof(unsigned long long)];

  pid_t pid = ::clone(
      childMain,
      &stack[stackSize/sizeof(stack[0]) - 1],  // stack grows down.
      flags,
      (void*) &func);

  // If CLONE_VM is not set, ::clone would create a process which runs in a
  // separate copy of the memory space of the calling process. So we destroy the
  // stack here to avoid memory leak. If CLONE_VM is set, ::clone would create a
  // thread which runs in the same memory space with the calling process.
  if (!(flags & CLONE_VM)) {
    delete[] stack;
  }

  return pid;
}

inline Result<Process> process(pid_t pid)
{
  // Page size, used for memory accounting.
  static const size_t pageSize = os::pagesize();

  // Number of clock ticks per second, used for cpu accounting.
  static const long ticks = sysconf(_SC_CLK_TCK);
  if (ticks <= 0) {
    return Error("Failed to get sysconf(_SC_CLK_TCK)");
  }

  const Result<proc::ProcessStatus> status = proc::status(pid);

  if (status.isError()) {
    return Error(status.error());
  }

  if (status.isNone()) {
    return None();
  }

  // There are known bugs with invalid utime / stime values coming
  // from /proc/<pid>/stat on some Linux systems.
  // See the following thread for details:
  // http://mail-archives.apache.org/mod_mbox/incubator-mesos-dev/
  // 201307.mbox/%3CCA+2n2er-Nemh0CsKLbHRkaHd=YCrNt17NLUPM2=TtEfsKOw4
  // Rg@mail.gmail.com%3E
  // These are similar reports:
  // http://lkml.indiana.edu/hypermail/linux/kernel/1207.1/01388.html
  // https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1023214
  Try<Duration> utime = Duration::create(status.get().utime / (double) ticks);
  Try<Duration> stime = Duration::create(status.get().stime / (double) ticks);

  // The command line from 'status.get().comm' is only "arg0" from
  // "argv" (i.e., the canonical executable name). To get the entire
  // command line we grab '/proc/[pid]/cmdline'.
  Result<std::string> cmdline = proc::cmdline(pid);

  return Process(status.get().pid,
                 status.get().ppid,
                 status.get().pgrp,
                 status.get().session,
                 Bytes(status.get().rss * pageSize),
                 utime.isSome() ? utime.get() : Option<Duration>::none(),
                 stime.isSome() ? stime.get() : Option<Duration>::none(),
                 cmdline.isSome() ? cmdline.get() : status.get().comm,
                 status.get().state == 'Z');
}

inline Try<std::set<pid_t>> pids()
{
  return proc::pids();
}

// Returns the total size of main and free memory.
inline Try<Memory> memory()
{
  Memory memory;

  struct sysinfo info;
  if (sysinfo(&info) != 0) {
    return ErrnoError();
  }

# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 23)
  memory.total = Bytes(info.totalram * info.mem_unit);
  memory.free = Bytes(info.freeram * info.mem_unit);
  memory.totalSwap = Bytes(info.totalswap * info.mem_unit);
  memory.freeSwap = Bytes(info.freeswap * info.mem_unit);
# else
  memory.total = Bytes(info.totalram);
  memory.free = Bytes(info.freeram);
  memory.totalSwap = Bytes(info.totalswap);
  memory.freeSwap = Bytes(info.freeswap);
# endif

  return memory;
}

} // namespace os {

#endif // __STOUT_OS_POSIX_HPP__
<commit_msg>Refactored 'os::clone()' to take an optional stack.<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef __STOUT_OS_POSIX_HPP__
#define __STOUT_OS_POSIX_HPP__

// This file contains Linux-only OS utilities.
#ifndef __linux__
#error "stout/os/linux.hpp is only available on Linux systems."
#endif

#include <sys/types.h> // For pid_t.

#include <list>
#include <queue>
#include <set>
#include <string>

#include <stout/error.hpp>
#include <stout/foreach.hpp>
#include <stout/lambda.hpp>
#include <stout/option.hpp>
#include <stout/proc.hpp>
#include <stout/result.hpp>
#include <stout/try.hpp>

#include <stout/os/pagesize.hpp>
#include <stout/os/process.hpp>

namespace os {

// Helper for clone() which expects an int(void*).
static int childMain(void* _func)
{
  const lambda::function<int()>* func =
    static_cast<const lambda::function<int()>*> (_func);

  return (*func)();
}

// Helper that captures information about a stack to be used when
// invoking clone.
struct Stack
{
  size_t size;
  unsigned long long* address;
};

inline pid_t clone(
    const lambda::function<int()>& func,
    int flags,
    Option<Stack> stack = None())
{
  // Stack for the child.
  // - unsigned long long used for best alignment.
  // - 8 MiB appears to be the default for "ulimit -s" on OSX and Linux.
  //
  // NOTE: We need to allocate the stack dynamically. This is because
  // glibc's 'clone' will modify the stack passed to it, therefore the
  // stack must NOT be shared as multiple 'clone's can be invoked
  // simultaneously.
  bool cleanup = false;
  if (stack.isNone()) {
    stack = Stack();
    stack->size = 8 * 1024 * 1024;
    stack->address =
      new unsigned long long[stack->size/sizeof(unsigned long long)];
    cleanup = true;
  }

  // Compute the address of the stack given that it grows down.
  void* address = &stack->address[stack->size / sizeof(stack->address[0]) - 1];

  pid_t pid = ::clone(childMain, address, flags, (void*) &func);

  // Given we allocated the stack ourselves, there are two
  // circumstances where we need to delete the allocated stack to
  // avoid a memory leak:
  //
  // (1) Failed to clone.
  //
  // (2) CLONE_VM is not set implying ::clone will create a process
  //     which runs in it's own copy of the memory space of the
  //     calling process. If CLONE_VM is set ::clone will create a
  //     thread which runs in the same memory space with the calling
  //     process, in which case we don't want to call delete!
  if (cleanup && (pid < 0 || !(flags & CLONE_VM))) {
    delete[] stack->address;
  }

  return pid;
}

inline Result<Process> process(pid_t pid)
{
  // Page size, used for memory accounting.
  static const size_t pageSize = os::pagesize();

  // Number of clock ticks per second, used for cpu accounting.
  static const long ticks = sysconf(_SC_CLK_TCK);
  if (ticks <= 0) {
    return Error("Failed to get sysconf(_SC_CLK_TCK)");
  }

  const Result<proc::ProcessStatus> status = proc::status(pid);

  if (status.isError()) {
    return Error(status.error());
  }

  if (status.isNone()) {
    return None();
  }

  // There are known bugs with invalid utime / stime values coming
  // from /proc/<pid>/stat on some Linux systems.
  // See the following thread for details:
  // http://mail-archives.apache.org/mod_mbox/incubator-mesos-dev/
  // 201307.mbox/%3CCA+2n2er-Nemh0CsKLbHRkaHd=YCrNt17NLUPM2=TtEfsKOw4
  // Rg@mail.gmail.com%3E
  // These are similar reports:
  // http://lkml.indiana.edu/hypermail/linux/kernel/1207.1/01388.html
  // https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1023214
  Try<Duration> utime = Duration::create(status.get().utime / (double) ticks);
  Try<Duration> stime = Duration::create(status.get().stime / (double) ticks);

  // The command line from 'status.get().comm' is only "arg0" from
  // "argv" (i.e., the canonical executable name). To get the entire
  // command line we grab '/proc/[pid]/cmdline'.
  Result<std::string> cmdline = proc::cmdline(pid);

  return Process(status.get().pid,
                 status.get().ppid,
                 status.get().pgrp,
                 status.get().session,
                 Bytes(status.get().rss * pageSize),
                 utime.isSome() ? utime.get() : Option<Duration>::none(),
                 stime.isSome() ? stime.get() : Option<Duration>::none(),
                 cmdline.isSome() ? cmdline.get() : status.get().comm,
                 status.get().state == 'Z');
}

inline Try<std::set<pid_t>> pids()
{
  return proc::pids();
}

// Returns the total size of main and free memory.
inline Try<Memory> memory()
{
  Memory memory;

  struct sysinfo info;
  if (sysinfo(&info) != 0) {
    return ErrnoError();
  }

# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 23)
  memory.total = Bytes(info.totalram * info.mem_unit);
  memory.free = Bytes(info.freeram * info.mem_unit);
  memory.totalSwap = Bytes(info.totalswap * info.mem_unit);
  memory.freeSwap = Bytes(info.freeswap * info.mem_unit);
# else
  memory.total = Bytes(info.totalram);
  memory.free = Bytes(info.freeram);
  memory.totalSwap = Bytes(info.totalswap);
  memory.freeSwap = Bytes(info.freeswap);
# endif

  return memory;
}

} // namespace os {

#endif // __STOUT_OS_POSIX_HPP__
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/utils/c_str.C $                 */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file c_str.C
/// @brief Storage for the C-string name of a thing
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: HB:FSP

#include <fapi2.H>
#include <generic/memory/lib/utils/c_str.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;
using fapi2::TARGET_TYPE_DIMM;

using fapi2::FAPI2_RC_SUCCESS;

namespace mss
{

// Thread local storage for the string we're going to create.
//TODO RTC:153924 Remove the else case when issue is resolved
#ifndef PLAT_NO_THREAD_LOCAL_STORAGE
    thread_local char c_str_storage[fapi2::MAX_ECMD_STRING_LEN];
#else
    char c_str_storage[fapi2::MAX_ECMD_STRING_LEN];
#endif

}
<commit_msg>L3 work for mss xmls<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/utils/c_str.C $                 */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file c_str.C
/// @brief Storage for the C-string name of a thing
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: HB:FSP

#include <fapi2.H>
#include <generic/memory/lib/utils/c_str.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;
using fapi2::TARGET_TYPE_DIMM;

using fapi2::FAPI2_RC_SUCCESS;

namespace mss
{

// Thread local storage for the string we're going to create.
//TODO RTC:153924 Remove the else case when issue is resolved
#ifndef PLAT_NO_THREAD_LOCAL_STORAGE
    thread_local char c_str_storage[fapi2::MAX_ECMD_STRING_LEN];
#else
    char c_str_storage[fapi2::MAX_ECMD_STRING_LEN];
#endif

}
<|endoftext|>


<commit_before>#include "tansa/jocsPlayer.h"

#include <unistd.h>

namespace tansa {

	std::vector<Point> JocsPlayer::getHomes() {
		return homes;
	}

	std::vector<std::vector<Action*>> JocsPlayer::getActions() {
		return actions;
	}

	JocsPlayer::JocsPlayer(const std::vector<Vehicle *> &vehicles, const std::vector<unsigned> &jocsActiveIds) {
		this->vehicles = vehicles;
		this->jocsActiveIds = jocsActiveIds;

		int n = vehicles.size();

		hovers.resize(n);
		for(int i = 0; i < n; i++) {
			hovers[i] = new HoverController(vehicles[i]);
		}

		posctls.resize(n);
		for(int i = 0; i < n; i++) {
			posctls[i] = new PositionController(vehicles[i]);
		}

		lightctls.resize(n);
		for(int i = 0; i < n; i++) {
			lightctls[i] = new LightController(vehicles[i]);
		}

		states.resize(n);
		for(auto& state : states){
			state = StateInit;
		}

		plans.resize(n);
		for(auto &p : plans) {
			p = 0;
		}

		lightCounters.resize(n);
		for(auto &lc : lightCounters) {
			lc = 0;
		}

		pauseIndices.resize(n);
		for(auto &pi : pauseIndices){
			pi = 0;
		}

		transitionStarts.resize(n, Time(0,0));
	}

	/**
	 * Load JOCS data from a specified path
	 */
	void JocsPlayer::loadJocs(Jocs *j) {
		currentJocs = j;
		homes = currentJocs->GetHomes();
		actions = currentJocs->GetActions();
		lightActions = currentJocs->GetLightActions();
		breakpoints = currentJocs->GetBreakpoints();
	}

	/**
	 * Play one 'step' in the choreography
	 */
	void JocsPlayer::step() {

		int n = jocsActiveIds.size();

		// Check for state transitions
		if (states[0] == StateInit) {
			// No implicit transitions
		} else if (states[0] == StateArming) {
			// Once all are armed, take them all off to the current position

			bool allGood = true;
			for(int i = 0; i < n; i++) {
				if (vehicles[i]->mode != "offboard" || !vehicles[i]->armed) {
					allGood = false;
					break;
				}
			}

			if (allGood) {
				start = Time::now();
				for(auto& state : states) {
					state = StateReady; // TODO: Shouldn't this be StateReady?
				}

				transitions.resize(n);
				for(int i = 0; i < n; i++) {

					states[i] = StateTakeoff;
					transitionStarts[i] = Time::now();
					transitions[i] = new LinearTrajectory(vehicles[i]->state.position, 0, homes[jocsActiveIds[i]], 10.0);
				}
				// TODO: Only grab the ones for the active drones
				holdpoints = homes;

				return;
			}
		}

		// Do the control loops
		for(int i = 0; i < n; i++) {
			Vehicle &v = *vehicles[i];
			auto &s = states[i];

			int chorI = jocsActiveIds[i];

			if (s == StateArming) {
				// Lower frequency state management
				if(stepTick % 50 == 0) {
					if (v.mode != "offboard") {
						v.set_mode("offboard");
						printf("Setting mode\n");
					} else if (!v.armed) {
						v.arm(true);
						printf("Arming mode\n");
					}
				}

				// Do nothing
				v.setpoint_accel(Vector3d(0,0,0));
			} else if (s == StateTakeoff) {
				double t = Time::now().since(transitionStarts[i]).seconds();

				// If the drones started on the ground and overshot the target, switch to hover
				bool overshot = v.state.position.z() > holdpoints[i].z();

				if(transitions[i] == NULL || t >= transitions[i]->endTime() || overshot) {
					s = StateHolding;
				}

				posctls[i]->track(transitions[i]);
				posctls[i]->control(t);
			} else if (s == StateReady) {
				// Do nothing
				v.setpoint_accel(Vector3d(0,0,0));
			} else if (s == StateHolding) {
				double t = Time::now().seconds();

				if (pauseRequested) {
					cout << "Transitioning to paused, t = " << Time::now().since(start).seconds() - timeOffset << endl;
					paused = true;
					pauseRequested = false;
					pauseOffset = Time::now();
				}

				if (paused && (stopRequested || Time::now().since(pauseOffset).seconds() > 20.0)) {
					cout << (stopRequested ? "Stop requested" : "Paused for more than 20 seconds")
						 << ", attempting to land." << endl;
					land();
					return;
				}
				// Do a hover
				hovers[i]->setPoint(holdpoints[i]); // TODO: Only do this on transitions (when holdpoints changes)
				hovers[i]->control(t);
			} else if (s == StateFlying) {
				double t = Time::now().since(start).seconds() - timeOffset;

				Trajectory *motion = static_cast<MotionAction*>(actions[chorI][plans[i]])->GetPath();

				if (t >= actions[chorI][plans[i]]->GetEndTime()) {
					if (plans[i] == actions[chorI].size()-1) {
						states[i] = StateLanding;

						Point lastPoint = motion->evaluate(t).position;
						Point groundPoint = lastPoint; groundPoint.z() = 0;
						transitions[i] = new LinearTrajectory(lastPoint, 0, groundPoint, 10.0);
						transitionStarts[i] = Time::now();
						continue;
					}
					plans[i]++;
				} else if (pauseRequested) {
					double nextBreakpoint = getNextBreakpointTime(t);
					if ((int)t + 1 == nextBreakpoint) {
						states[i] = StateHolding;
						pauseIndices[i] = plans[i];
						holdpoints[i] = motion->evaluate(t).position;
						continue;
					}
				}

				posctls[i]->track(motion);
				posctls[i]->control(t);

				if (lightCounters[i] < lightActions[jocsActiveIds[i]].size()) {
					LightTrajectory *light = static_cast<LightAction *>(lightActions[jocsActiveIds[i]][lightCounters[i]])->GetPath();

					if (t >= lightActions[jocsActiveIds[i]][lightCounters[i]]->GetStartTime()) {
						//printf("Getting light action for drone %d at time %f\n", jocsActiveIds[vi], light->getStartTime());
						lightctls[i]->track(light, light); //TODO: not just copy same light trajectory for both lights
						//printf("Drone %d \n" + jocsActiveIds[i]);
						lightctls[i]->control(t);
						if (t >= lightActions[jocsActiveIds[i]][lightCounters[i]]->GetEndTime()) {
							lightCounters[i]++;
						}
					}
				}
			} else if (s == StateLanding) {
				double t = Time::now().since(transitionStarts[i]).seconds();

				// Descend to ground
				if(t < transitions[i]->endTime()) {
					posctls[i]->track(transitions[i]);
					posctls[i]->control(t);
				}
				// Disarm
				else if(v.armed){
					v.setpoint_accel(Vector3d(0,0,0));
					v.arm(false);
				}
				// Reset state machine
				else {
					s = StateInit;
				}

			}
		}

		stepTick++;
	}

	void JocsPlayer::prepare() {

		for(auto s : states) {
			if(s != StateInit) {
				printf("Cannot prepare: Some drones not in initial state\n");
				return;
			}
		}

		for(auto &s : states) {
			s = StateArming;
		}
	}

	void JocsPlayer::play() {

		for(auto s : states) {
			if(s != StateHolding) {
				printf("Cannot play: Some drones not ready\n");
				return;
			}
		}

		if (paused) {
			paused = false;
			pauseRequested = false;
			stopRequested = false;
			timeOffset += Time::now().since(pauseOffset).seconds();
			int n = jocsActiveIds.size();
			for (int i = 0; i < n; i++) {
				plans[i] = pauseIndices[i];
			}
		} else {
			start = Time::now();
		}

		for(auto &s : states) {
			s = StateFlying;
		}
	}

	/**
	 * Pause the choreography
	 */
	void JocsPlayer::pause() {
		pauseRequested = true;
		// TODO: Determine a pause-at index (and maybe also a stop-at index)
	}

	void JocsPlayer::stop() {
		if (!paused) {
			printf("Must already be paused.");
			return;
		}
		stopRequested = true;
	}

	void JocsPlayer::land() {
		for(auto s : states) {
			if(s != StateHolding) {
				printf("Cannot land: Some drones not holding position\n");
				return;
			}
		}

		for(int i = 0; i < states.size(); i++) {
			states[i] = StateLanding;

			Point lastPoint = holdpoints[i];
			Point groundPoint = lastPoint; groundPoint.z() = 0;
			transitions[i] = new LinearTrajectory(lastPoint, 0, groundPoint, 10.0);
			transitionStarts[i] = Time::now();
		}
	}

	/**
	 * Rewind the chreography by a number of 'steps'
	 * @param steps How far back in the choreography to rewind
	 */
	void JocsPlayer::rewind(int steps) {

	}

	double JocsPlayer::currentTime() {
		if(!this->isPlaying()) {
			return -1;
		}

		return Time::now().since(start).seconds();
	}

	/**
	 * Reset the choreography back to the initial position (ie: plans[0])
	 */
	void JocsPlayer::reset() {
		resetMode = true;
	}

	void JocsPlayer::cleanup() {
		for (int i = 0; i < posctls.size(); i++) {
			delete posctls[i];
		}

		for (int i = 0; i < lightctls.size(); i++) {
			delete lightctls[i];
		}

		for (int i = 0; i < hovers.size(); i++) {
			delete hovers[i];
		}

		// TODO: They will memory leak
		for (int i = 0; i < transitions.size(); i++) {
			delete transitions[i];
		}
	}

	/**
     * Helper methods
     * TODO: write test cases (especially since the code doesn't use them yet)
     */

	double JocsPlayer::getNextBreakpointTime(double lastTime) {
		unsigned breakpointsLength = breakpoints.size();

		// Cycles all breakpoints
		// Assumes list of breakpoints is in time-ascending order
		for (unsigned i = 0; i < breakpointsLength - 1; i++) {
			double ret = breakpoints[i].GetStartTime();
			if (ret >= lastTime) {
				// Return the first breakpoint whose starttime hasn't passed yet
				// or is currently happening
				return ret;
			}
		}

		return -1;
	}
	double JocsPlayer::getBreakpointTime(unsigned breakpointNumber) {
		unsigned breakpointsLength = breakpoints.size();

		// Cycles all breakpoints
		for (unsigned i = 1; i < breakpointsLength - 1; i++) {
			unsigned ret = breakpoints[i].GetNumber();
			if (ret == breakpointNumber) {
				return breakpoints[i].GetStartTime();
			}
		}

		return -1;
	}
	double JocsPlayer::getBreakpointTime(std::string breakpointName) {
		unsigned breakpointsLength = breakpoints.size();

		// Cycles all breakpoints
		for (unsigned i = 1; i < breakpointsLength - 1; i++) {
			std::string name = breakpoints[i].GetName();
			if (name.compare(breakpointName) == 0) {
				return breakpoints[i].GetStartTime();
			}
		}

		return -1;
	}
	unsigned JocsPlayer::getBreakpointNumber(double startTime) {
		unsigned breakpointsLength = breakpoints.size();

		// Cycles all breakpoints
		for (unsigned i = 1; i < breakpointsLength - 1; i++) {
			double ret = breakpoints[i].GetStartTime();
			if (ret > startTime) {
				// Return the breakpoint that the given time is a part of
				// Also works for given times that are within a breakpoint
				// not just the start time of a breakpoint
				return breakpoints[i-1].GetNumber();
			}
		}

		return -1;
	}
	Point JocsPlayer::getDroneLocationAtTime(double startTime, unsigned droneId) {
		// This one only works if the startTime is a startTime of an action
		// Returns negative value if startTime is either between actions or out of scope

		unsigned actionsLength = actions[droneId].size();

		// Assume droneId is valid and use it to choose which list of actions we need to parse
		for (unsigned j = 0; j < actionsLength; j++) {
			double actionStartTime = actions[droneId][j]->GetStartTime();
			if (actionStartTime == startTime && isMotionAction(actions[droneId][j])) {
				return ((MotionAction*)actions[droneId][j])->GetStartPoint(); // TODO: check if this cast works...
			}
		}

		return Point(0,0,-1); // TODO: figure out better "invalid" answer
	}
	bool JocsPlayer::isMotionAction(Action* a) {
		MotionAction* ma = dynamic_cast<MotionAction*>(a);
		return ma;
	}
/*
	void JocsPlayer::createBreakpointSection(const std::vector<vector> actions, int startPoint, int endPoint = -1) {
		double startTime, endTime = -1;
		int bpStartIndex, bpEndIndex = -1;
		if(startPoint >= 0) {
			startTime = getBreakpointTime(startPoint);
		} else {
			bpStartIndex = 0;
		}
		if(startPoint >= 0) {
			endTime = getBreakpointTime(endPoint);
		} else {
			bpEndIndex = actions.size() - 1;
		}
		for(int i = 0; i < actions.size(); i++) {
			if(actions[i][1].start_time.seconds == startTime) {
				bpStartIndex = i;
			}
			if(actions[i][1].start_time.seconds == endTime) {
				bpEndIndex = i;
			}
			if(bpStartIndex != -1 && bpEndIndex != -1) {
				break;
			}
		}
		startIndex = bpStartIndex;
		endIndex = bpEndIndex;
	}

	*/
}
<commit_msg>Fix bug where drones are sent to wrong index's home position<commit_after>#include "tansa/jocsPlayer.h"

#include <unistd.h>

namespace tansa {

	std::vector<Point> JocsPlayer::getHomes() {
		return homes;
	}

	std::vector<std::vector<Action*>> JocsPlayer::getActions() {
		return actions;
	}

	JocsPlayer::JocsPlayer(const std::vector<Vehicle *> &vehicles, const std::vector<unsigned> &jocsActiveIds) {
		this->vehicles = vehicles;
		this->jocsActiveIds = jocsActiveIds;

		int n = vehicles.size();

		hovers.resize(n);
		for(int i = 0; i < n; i++) {
			hovers[i] = new HoverController(vehicles[i]);
		}

		posctls.resize(n);
		for(int i = 0; i < n; i++) {
			posctls[i] = new PositionController(vehicles[i]);
		}

		lightctls.resize(n);
		for(int i = 0; i < n; i++) {
			lightctls[i] = new LightController(vehicles[i]);
		}

		states.resize(n);
		for(auto& state : states){
			state = StateInit;
		}

		plans.resize(n);
		for(auto &p : plans) {
			p = 0;
		}

		lightCounters.resize(n);
		for(auto &lc : lightCounters) {
			lc = 0;
		}

		pauseIndices.resize(n);
		for(auto &pi : pauseIndices){
			pi = 0;
		}

		transitionStarts.resize(n, Time(0,0));
	}

	/**
	 * Load JOCS data from a specified path
	 */
	void JocsPlayer::loadJocs(Jocs *j) {
		currentJocs = j;
		homes = currentJocs->GetHomes();
		actions = currentJocs->GetActions();
		lightActions = currentJocs->GetLightActions();
		breakpoints = currentJocs->GetBreakpoints();
	}

	/**
	 * Play one 'step' in the choreography
	 */
	void JocsPlayer::step() {

		int n = jocsActiveIds.size();

		// Check for state transitions
		if (states[0] == StateInit) {
			// No implicit transitions
		} else if (states[0] == StateArming) {
			// Once all are armed, take them all off to the current position

			bool allGood = true;
			for(int i = 0; i < n; i++) {
				if (vehicles[i]->mode != "offboard" || !vehicles[i]->armed) {
					allGood = false;
					break;
				}
			}

			if (allGood) {
				start = Time::now();
				for(auto& state : states) {
					state = StateReady; // TODO: Shouldn't this be StateReady?
				}

				transitions.resize(n);
				for(int i = 0; i < n; i++) {

					states[i] = StateTakeoff;
					transitionStarts[i] = Time::now();
					transitions[i] = new LinearTrajectory(vehicles[i]->state.position, 0, homes[jocsActiveIds[i]], 10.0);
				}
				// TODO: Only grab the ones for the active drones
				holdpoints = homes;

				return;
			}
		}

		// Do the control loops
		for(int i = 0; i < n; i++) {
			Vehicle &v = *vehicles[i];
			auto &s = states[i];

			int chorI = jocsActiveIds[i];

			if (s == StateArming) {
				// Lower frequency state management
				if(stepTick % 50 == 0) {
					if (v.mode != "offboard") {
						v.set_mode("offboard");
						printf("Setting mode\n");
					} else if (!v.armed) {
						v.arm(true);
						printf("Arming mode\n");
					}
				}

				// Do nothing
				v.setpoint_accel(Vector3d(0,0,0));
			} else if (s == StateTakeoff) {
				double t = Time::now().since(transitionStarts[i]).seconds();

				// If the drones started on the ground and overshot the target, switch to hover
				bool overshot = v.state.position.z() > holdpoints[jocsActiveIds[i]].z();

				if(transitions[i] == NULL || t >= transitions[i]->endTime() || overshot) {
					s = StateHolding;
				}

				posctls[i]->track(transitions[i]);
				posctls[i]->control(t);
			} else if (s == StateReady) {
				// Do nothing
				v.setpoint_accel(Vector3d(0,0,0));
			} else if (s == StateHolding) {
				double t = Time::now().seconds();

				if (pauseRequested) {
					cout << "Transitioning to paused, t = " << Time::now().since(start).seconds() - timeOffset << endl;
					paused = true;
					pauseRequested = false;
					pauseOffset = Time::now();
				}

				if (paused && (stopRequested || Time::now().since(pauseOffset).seconds() > 20.0)) {
					cout << (stopRequested ? "Stop requested" : "Paused for more than 20 seconds")
						 << ", attempting to land." << endl;
					land();
					return;
				}
				// Do a hover
				hovers[i]->setPoint(holdpoints[jocsActiveIds[i]]); // TODO: Only do this on transitions (when holdpoints changes)
				hovers[i]->control(t);
			} else if (s == StateFlying) {
				double t = Time::now().since(start).seconds() - timeOffset;

				Trajectory *motion = static_cast<MotionAction*>(actions[chorI][plans[i]])->GetPath();

				if (t >= actions[chorI][plans[i]]->GetEndTime()) {
					if (plans[i] == actions[chorI].size()-1) {
						states[i] = StateLanding;

						Point lastPoint = motion->evaluate(t).position;
						Point groundPoint = lastPoint; groundPoint.z() = 0;
						transitions[i] = new LinearTrajectory(lastPoint, 0, groundPoint, 10.0);
						transitionStarts[i] = Time::now();
						continue;
					}
					plans[i]++;
				} else if (pauseRequested) {
					double nextBreakpoint = getNextBreakpointTime(t);
					if ((int)t + 1 == nextBreakpoint) {
						states[i] = StateHolding;
						pauseIndices[i] = plans[i];
						holdpoints[jocsActiveIds[i]] = motion->evaluate(t).position;
						continue;
					}
				}

				posctls[i]->track(motion);
				posctls[i]->control(t);

				if (lightCounters[i] < lightActions[jocsActiveIds[i]].size()) {
					LightTrajectory *light = static_cast<LightAction *>(lightActions[jocsActiveIds[i]][lightCounters[i]])->GetPath();

					if (t >= lightActions[jocsActiveIds[i]][lightCounters[i]]->GetStartTime()) {
						//printf("Getting light action for drone %d at time %f\n", jocsActiveIds[vi], light->getStartTime());
						lightctls[i]->track(light, light); //TODO: not just copy same light trajectory for both lights
						//printf("Drone %d \n" + jocsActiveIds[i]);
						lightctls[i]->control(t);
						if (t >= lightActions[jocsActiveIds[i]][lightCounters[i]]->GetEndTime()) {
							lightCounters[i]++;
						}
					}
				}
			} else if (s == StateLanding) {
				double t = Time::now().since(transitionStarts[i]).seconds();

				// Descend to ground
				if(t < transitions[i]->endTime()) {
					posctls[i]->track(transitions[i]);
					posctls[i]->control(t);
				}
				// Disarm
				else if(v.armed){
					v.setpoint_accel(Vector3d(0,0,0));
					v.arm(false);
				}
				// Reset state machine
				else {
					s = StateInit;
				}

			}
		}

		stepTick++;
	}

	void JocsPlayer::prepare() {

		for(auto s : states) {
			if(s != StateInit) {
				printf("Cannot prepare: Some drones not in initial state\n");
				return;
			}
		}

		for(auto &s : states) {
			s = StateArming;
		}
	}

	void JocsPlayer::play() {

		for(auto s : states) {
			if(s != StateHolding) {
				printf("Cannot play: Some drones not ready\n");
				return;
			}
		}

		if (paused) {
			paused = false;
			pauseRequested = false;
			stopRequested = false;
			timeOffset += Time::now().since(pauseOffset).seconds();
			int n = jocsActiveIds.size();
			for (int i = 0; i < n; i++) {
				plans[i] = pauseIndices[i];
			}
		} else {
			start = Time::now();
		}

		for(auto &s : states) {
			s = StateFlying;
		}
	}

	/**
	 * Pause the choreography
	 */
	void JocsPlayer::pause() {
		pauseRequested = true;
		// TODO: Determine a pause-at index (and maybe also a stop-at index)
	}

	void JocsPlayer::stop() {
		if (!paused) {
			printf("Must already be paused.");
			return;
		}
		stopRequested = true;
	}

	void JocsPlayer::land() {
		for(auto s : states) {
			if(s != StateHolding) {
				printf("Cannot land: Some drones not holding position\n");
				return;
			}
		}

		for(int i = 0; i < states.size(); i++) {
			states[i] = StateLanding;

			Point lastPoint = holdpoints[jocsActiveIds[i]];
			Point groundPoint = lastPoint; groundPoint.z() = 0;
			transitions[i] = new LinearTrajectory(lastPoint, 0, groundPoint, 10.0);
			transitionStarts[i] = Time::now();
		}
	}

	/**
	 * Rewind the chreography by a number of 'steps'
	 * @param steps How far back in the choreography to rewind
	 */
	void JocsPlayer::rewind(int steps) {

	}

	double JocsPlayer::currentTime() {
		if(!this->isPlaying()) {
			return -1;
		}

		return Time::now().since(start).seconds();
	}

	/**
	 * Reset the choreography back to the initial position (ie: plans[0])
	 */
	void JocsPlayer::reset() {
		resetMode = true;
	}

	void JocsPlayer::cleanup() {
		for (int i = 0; i < posctls.size(); i++) {
			delete posctls[i];
		}

		for (int i = 0; i < lightctls.size(); i++) {
			delete lightctls[i];
		}

		for (int i = 0; i < hovers.size(); i++) {
			delete hovers[i];
		}

		// TODO: They will memory leak
		for (int i = 0; i < transitions.size(); i++) {
			delete transitions[i];
		}
	}

	/**
     * Helper methods
     * TODO: write test cases (especially since the code doesn't use them yet)
     */

	double JocsPlayer::getNextBreakpointTime(double lastTime) {
		unsigned breakpointsLength = breakpoints.size();

		// Cycles all breakpoints
		// Assumes list of breakpoints is in time-ascending order
		for (unsigned i = 0; i < breakpointsLength - 1; i++) {
			double ret = breakpoints[i].GetStartTime();
			if (ret >= lastTime) {
				// Return the first breakpoint whose starttime hasn't passed yet
				// or is currently happening
				return ret;
			}
		}

		return -1;
	}
	double JocsPlayer::getBreakpointTime(unsigned breakpointNumber) {
		unsigned breakpointsLength = breakpoints.size();

		// Cycles all breakpoints
		for (unsigned i = 1; i < breakpointsLength - 1; i++) {
			unsigned ret = breakpoints[i].GetNumber();
			if (ret == breakpointNumber) {
				return breakpoints[i].GetStartTime();
			}
		}

		return -1;
	}
	double JocsPlayer::getBreakpointTime(std::string breakpointName) {
		unsigned breakpointsLength = breakpoints.size();

		// Cycles all breakpoints
		for (unsigned i = 1; i < breakpointsLength - 1; i++) {
			std::string name = breakpoints[i].GetName();
			if (name.compare(breakpointName) == 0) {
				return breakpoints[i].GetStartTime();
			}
		}

		return -1;
	}
	unsigned JocsPlayer::getBreakpointNumber(double startTime) {
		unsigned breakpointsLength = breakpoints.size();

		// Cycles all breakpoints
		for (unsigned i = 1; i < breakpointsLength - 1; i++) {
			double ret = breakpoints[i].GetStartTime();
			if (ret > startTime) {
				// Return the breakpoint that the given time is a part of
				// Also works for given times that are within a breakpoint
				// not just the start time of a breakpoint
				return breakpoints[i-1].GetNumber();
			}
		}

		return -1;
	}
	Point JocsPlayer::getDroneLocationAtTime(double startTime, unsigned droneId) {
		// This one only works if the startTime is a startTime of an action
		// Returns negative value if startTime is either between actions or out of scope

		unsigned actionsLength = actions[droneId].size();

		// Assume droneId is valid and use it to choose which list of actions we need to parse
		for (unsigned j = 0; j < actionsLength; j++) {
			double actionStartTime = actions[droneId][j]->GetStartTime();
			if (actionStartTime == startTime && isMotionAction(actions[droneId][j])) {
				return ((MotionAction*)actions[droneId][j])->GetStartPoint(); // TODO: check if this cast works...
			}
		}

		return Point(0,0,-1); // TODO: figure out better "invalid" answer
	}
	bool JocsPlayer::isMotionAction(Action* a) {
		MotionAction* ma = dynamic_cast<MotionAction*>(a);
		return ma;
	}
/*
	void JocsPlayer::createBreakpointSection(const std::vector<vector> actions, int startPoint, int endPoint = -1) {
		double startTime, endTime = -1;
		int bpStartIndex, bpEndIndex = -1;
		if(startPoint >= 0) {
			startTime = getBreakpointTime(startPoint);
		} else {
			bpStartIndex = 0;
		}
		if(startPoint >= 0) {
			endTime = getBreakpointTime(endPoint);
		} else {
			bpEndIndex = actions.size() - 1;
		}
		for(int i = 0; i < actions.size(); i++) {
			if(actions[i][1].start_time.seconds == startTime) {
				bpStartIndex = i;
			}
			if(actions[i][1].start_time.seconds == endTime) {
				bpEndIndex = i;
			}
			if(bpStartIndex != -1 && bpEndIndex != -1) {
				break;
			}
		}
		startIndex = bpStartIndex;
		endIndex = bpEndIndex;
	}

	*/
}
<|endoftext|>


<commit_before>// Time:  addNum: O(n), getIntervals: O(n), n is the number of disjoint intervals.
// Space: O(n)

/**
 * Definition for an interval.
 * struct Interval {
 *     int start;
 *     int end;
 *     Interval() : start(0), end(0) {}
 *     Interval(int s, int e) : start(s), end(e) {}
 * };
 */
class SummaryRanges {
public:
    /** Initialize your data structure here. */
    SummaryRanges() {

    }

    void addNum(int val) {
        auto ub_cmp =  [](int d, const Interval& x) { return d < x.start; };
        if (intervals_.empty()) {
            intervals_.emplace_back(val, val);
        } else {
            auto it = upper_bound(intervals_.begin(), intervals_.end(), val, ub_cmp);
            if (it == intervals_.end()) {
                if (prev(it)->end + 1 == val) {
                    prev(it)->end = val;
                } else if (prev(it)->end + 1 < val) {
                    intervals_.insert(it, Interval(val, val));
                }
            } else {
                if (it != intervals_.begin() && prev(it)->end + 1 == val) {
                    prev(it)->end = val;
                } else if (it == intervals_.begin() || prev(it)->end + 1 < val) {
                    intervals_.insert(it, Interval(val, val));
                }
                it = upper_bound(intervals_.begin(), intervals_.end(), val, ub_cmp);
                if (prev(it)->end + 1 == it->start) {
                    prev(it)->end = it->end;
                    intervals_.erase(it);
                }
            }
        }
    }

    vector<Interval> getIntervals() {
        return intervals_;
    }

private:
    vector<Interval> intervals_;
};

// Time:  addNum: O(logs), getIntervals: O(s), s is the data stream's size.
// Space: O(s)
class SummaryRanges2 {
public:
    /** Initialize your data structure here. */
    SummaryRanges() {

    }

    void addNum(int val) {
        nums_.emplace(val);
    }

    vector<Interval> getIntervals() {
        vector<Interval> result;
        if (nums_.empty()) {
            return result;
        }
        auto start = *nums_.begin(), end = *nums_.begin();
        for (auto it = next(nums_.begin()); it != nums_.end(); ++it) {
            if (it != nums_.end() && *it == end + 1) {
                end = *it;
            } else  {
                result.emplace_back(start, end);
                if (it != nums_.end()) {
                    start = end = *it;
                }
            }
        }
        result.emplace_back(start, end);
        return result;
    }

private:
    set<int> nums_;
};

/**
 * Your SummaryRanges object will be instantiated and called as such:
 * SummaryRanges obj = new SummaryRanges();
 * obj.addNum(val);
 * vector<Interval> param_2 = obj.getIntervals();
 */

<commit_msg>Update data-stream-as-disjoint-intervals.cpp<commit_after>// Time:  addNum: O(n), getIntervals: O(n), n is the number of disjoint intervals.
// Space: O(n)

/**
 * Definition for an interval.
 * struct Interval {
 *     int start;
 *     int end;
 *     Interval() : start(0), end(0) {}
 *     Interval(int s, int e) : start(s), end(e) {}
 * };
 */
class SummaryRanges {
public:
    /** Initialize your data structure here. */
    SummaryRanges() {

    }

    void addNum(int val) {
        if (intervals_.empty()) {
            intervals_.emplace_back(val, val);
        } else {
            auto it = upper_bound(intervals_.begin(), intervals_.end(), val,
                                  [](int d, const Interval& x) { return d < x.start; });
            if (it == intervals_.end()) {
                if (prev(it)->end + 1 == val) {
                    prev(it)->end = val;
                } else if (prev(it)->end + 1 < val) {
                    intervals_.insert(it, Interval(val, val));
                }
            } else {
                if (it != intervals_.begin() && prev(it)->end + 1 == val) {
                    prev(it)->end = val;
                } else if (it == intervals_.begin() || prev(it)->end + 1 < val) {
                    intervals_.insert(it, Interval(val, val));
                }
                it = upper_bound(intervals_.begin(), intervals_.end(), val, ub_cmp);
                if (prev(it)->end + 1 == it->start) {
                    prev(it)->end = it->end;
                    intervals_.erase(it);
                }
            }
        }
    }

    vector<Interval> getIntervals() {
        return intervals_;
    }

private:
    vector<Interval> intervals_;
};

// Time:  addNum: O(logs), getIntervals: O(s), s is the data stream's size.
// Space: O(s)
class SummaryRanges2 {
public:
    /** Initialize your data structure here. */
    SummaryRanges() {

    }

    void addNum(int val) {
        nums_.emplace(val);
    }

    vector<Interval> getIntervals() {
        vector<Interval> result;
        if (nums_.empty()) {
            return result;
        }
        auto start = *nums_.begin(), end = *nums_.begin();
        for (auto it = next(nums_.begin()); it != nums_.end(); ++it) {
            if (it != nums_.end() && *it == end + 1) {
                end = *it;
            } else  {
                result.emplace_back(start, end);
                if (it != nums_.end()) {
                    start = end = *it;
                }
            }
        }
        result.emplace_back(start, end);
        return result;
    }

private:
    set<int> nums_;
};

/**
 * Your SummaryRanges object will be instantiated and called as such:
 * SummaryRanges obj = new SummaryRanges();
 * obj.addNum(val);
 * vector<Interval> param_2 = obj.getIntervals();
 */

<|endoftext|>


<commit_before>
/**
 * This file is part of the boostcache package.
 *
 * (c) Azat Khuzhin <a3at.mail@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#include "commands.h"
#include "util/compiler.h"

#include <boost/format.hpp>

namespace PlaceHolders = std::placeholders;

#define ADD_COMMAND(callback, objectPtr, argsNum) \
    CallbackInfo(std::bind(callback, objectPtr, PlaceHolders::_1), argsNum);

Commands::Callback Commands::find(const std::string& commandName,
                                  int numberOfArguments) const
{
    HashTable::const_iterator command = m_commands.find(commandName);

    if (command == m_commands.end()) {
        return std::bind(&Commands::notImplementedYetCallback,
                         PlaceHolders::_1);
    }

    const int expectedArguments = command->second.numberOfArguments;
    if ((expectedArguments >= 0) && (expectedArguments != numberOfArguments)) {
        return std::bind(malformedArgumentsCallback,
                         PlaceHolders::_1, numberOfArguments, expectedArguments);
    }

    return command->second.callback;
}

Commands::Commands()
{
    addGenericCommands();
    addDbCommands();
}

void Commands::addGenericCommands()
{
    m_commands["COMMANDS"] = ADD_COMMAND(&Commands::commandsList, this, 0);
    m_commands["PING"]     = ADD_COMMAND(&Commands::pingPong, this, 0);
}

void Commands::addDbCommands()
{
    /* hashtable */
    m_commands["HGET"] =   ADD_COMMAND(&Db::HashTable::get, &m_dbHashTable, 1);
    m_commands["HSET"] =   ADD_COMMAND(&Db::HashTable::set, &m_dbHashTable, 2);
    m_commands["HDEL"] =   ADD_COMMAND(&Db::HashTable::del, &m_dbHashTable, 1);
    /* avltree */
    m_commands["ATGET"] =  ADD_COMMAND(&Db::AvlTree::get, &m_dbAvlTree, 1);
    m_commands["ATSET"] =  ADD_COMMAND(&Db::AvlTree::set, &m_dbAvlTree, 2);
    m_commands["ATDEL"] =  ADD_COMMAND(&Db::AvlTree::del, &m_dbAvlTree, 1);
}

std::string Commands::notImplementedYetCallback(const Command::Arguments& arguments)
{
    boost::format format = boost::format("%s is not implemented") % arguments[0];
    return Command::toErrorReplyString(boost::str(format));
}

std::string Commands::malformedArgumentsCallback(const Command::Arguments& arguments,
                                                 int inputArguments, int expectedArguments)
{
    boost::format format = boost::format("%s malformed number of arguments (%i vs %i)")
                                         % arguments[0]
                                         % inputArguments
                                         % expectedArguments;
    return Command::toErrorReplyString(boost::str(format));
}

std::string Commands::commandsList(const Command::Arguments& UNUSED(arguments))
{
    std::string asString;
    for (const HashTablePair &pair : m_commands) {
        asString += pair.first;
        asString += "\n";
    }
    return Command::toReplyString(asString);
}

std::string Commands::pingPong(const Command::Arguments& UNUSED(arguments))
{
    return "PONG";
}<commit_msg>[kernel] fix PONG reply (add CRLF at the end)<commit_after>
/**
 * This file is part of the boostcache package.
 *
 * (c) Azat Khuzhin <a3at.mail@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#include "commands.h"
#include "util/compiler.h"

#include <boost/format.hpp>

namespace PlaceHolders = std::placeholders;

#define ADD_COMMAND(callback, objectPtr, argsNum) \
    CallbackInfo(std::bind(callback, objectPtr, PlaceHolders::_1), argsNum);

Commands::Callback Commands::find(const std::string& commandName,
                                  int numberOfArguments) const
{
    HashTable::const_iterator command = m_commands.find(commandName);

    if (command == m_commands.end()) {
        return std::bind(&Commands::notImplementedYetCallback,
                         PlaceHolders::_1);
    }

    const int expectedArguments = command->second.numberOfArguments;
    if ((expectedArguments >= 0) && (expectedArguments != numberOfArguments)) {
        return std::bind(malformedArgumentsCallback,
                         PlaceHolders::_1, numberOfArguments, expectedArguments);
    }

    return command->second.callback;
}

Commands::Commands()
{
    addGenericCommands();
    addDbCommands();
}

void Commands::addGenericCommands()
{
    m_commands["COMMANDS"] = ADD_COMMAND(&Commands::commandsList, this, 0);
    m_commands["PING"]     = ADD_COMMAND(&Commands::pingPong, this, 0);
}

void Commands::addDbCommands()
{
    /* hashtable */
    m_commands["HGET"] =   ADD_COMMAND(&Db::HashTable::get, &m_dbHashTable, 1);
    m_commands["HSET"] =   ADD_COMMAND(&Db::HashTable::set, &m_dbHashTable, 2);
    m_commands["HDEL"] =   ADD_COMMAND(&Db::HashTable::del, &m_dbHashTable, 1);
    /* avltree */
    m_commands["ATGET"] =  ADD_COMMAND(&Db::AvlTree::get, &m_dbAvlTree, 1);
    m_commands["ATSET"] =  ADD_COMMAND(&Db::AvlTree::set, &m_dbAvlTree, 2);
    m_commands["ATDEL"] =  ADD_COMMAND(&Db::AvlTree::del, &m_dbAvlTree, 1);
}

std::string Commands::notImplementedYetCallback(const Command::Arguments& arguments)
{
    boost::format format = boost::format("%s is not implemented") % arguments[0];
    return Command::toErrorReplyString(boost::str(format));
}

std::string Commands::malformedArgumentsCallback(const Command::Arguments& arguments,
                                                 int inputArguments, int expectedArguments)
{
    boost::format format = boost::format("%s malformed number of arguments (%i vs %i)")
                                         % arguments[0]
                                         % inputArguments
                                         % expectedArguments;
    return Command::toErrorReplyString(boost::str(format));
}

std::string Commands::commandsList(const Command::Arguments& UNUSED(arguments))
{
    std::string asString;
    for (const HashTablePair &pair : m_commands) {
        asString += pair.first;
        asString += "\n";
    }
    return Command::toReplyString(asString);
}

std::string Commands::pingPong(const Command::Arguments& UNUSED(arguments))
{
    return "+PONG\r\n";
}<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 Torsten Rahn <tackat@kde.org>"
// Copyright 2007      Inge Wallin  <ingwa@kde.org>"
// Copyright 2008      Jens-Michael Hoffmann <jensmh@gmx.de>
//

#include "TextureTile.h"

#include <QtCore/QDateTime>
#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
#include <QtGui/QImage>

#include <cmath>

#include "global.h"
#include "GeoSceneTexture.h"
#include "MarbleDirs.h"
#include "TileLoaderHelper.h"

namespace Marble {

class TextureTilePrivate {
 public:
    uchar   **jumpTable8;
    uint    **jumpTable32;

    TileId    m_id;

    QImage    m_rawtile;

    int       m_depth;
    bool      m_isGrayscale;
    bool      m_used;

    TextureTile::TileState m_state;

    QDateTime m_created;

    TextureTilePrivate(const TileId& id) :
      jumpTable8(0),
      jumpTable32(0),
      m_id(id),
      m_rawtile(),
      m_depth(0),
      m_isGrayscale(false),
      m_used(false),
      m_state(TextureTile::TileEmpty),
      m_created(QDateTime::currentDateTime()) { }

    ~TextureTilePrivate() {
      delete [] jumpTable32;
      delete [] jumpTable8;
    }
};

};

using namespace Marble;

static uint **jumpTableFromQImage32( QImage &img )
{
    const int  height = img.height();
    const int  bpl    = img.bytesPerLine() / 4;
    uint      *data = (QRgb*)(img.scanLine(0));
    uint     **jumpTable = new uint*[height];

    for ( int y = 0; y < height; ++y ) {
        jumpTable[ y ] = data;
        data += bpl;
    }

    return jumpTable;
}

static uchar **jumpTableFromQImage8( QImage &img )
{
    const int  height = img.height();
    const int  bpl    = img.bytesPerLine();
    uchar     *data = img.bits();
    uchar    **jumpTable = new uchar*[height];

    for ( int y = 0; y < height; ++y ) {
        jumpTable[ y ] = data;
        data += bpl;
    }

    return jumpTable;
}

TextureTile::TextureTile( TileId const& id )
    : QObject(),
      d(new TextureTilePrivate(id))
{
}

TextureTile::~TextureTile()
{
    delete d;
}

void TextureTile::loadDataset( GeoSceneTexture *textureLayer, int level, int x, int y, QCache<TileId, TextureTile> *tileCache )
{
    // qDebug() << "TextureTile::loadDataset" << level << x << y;
    QImage temptile;

    d->m_used = true; // Needed to avoid frequent deletion of tiles

    QString  absfilename;

    // If the tile level offers the requested tile then load it.
    // Otherwise cycle from the requested tilelevel down to one where
    // the requested area is covered.  Then scale the area to create a
    // replacement for the tile that has been requested.

    const int levelZeroColumns = textureLayer->levelZeroColumns();
    const int levelZeroRows = textureLayer->levelZeroRows();
    const int rowsRequestedLevel = TileLoaderHelper::levelToRow( levelZeroRows, level );
    const int columnsRequestedLevel = TileLoaderHelper::levelToColumn( levelZeroColumns, level );
    bool tileFound = false;
    for ( int currentLevel = level; !tileFound && currentLevel > -1; --currentLevel ) {

        const int rowsCurrentLevel =
            TileLoaderHelper::levelToRow( levelZeroRows, currentLevel );
        const int columnsCurrentLevel =
            TileLoaderHelper::levelToColumn( levelZeroColumns, currentLevel );

        qreal normalizedX = (qreal)(x) / (qreal)( rowsRequestedLevel );
        qreal normalizedY = (qreal)(y) / (qreal)( columnsRequestedLevel );
        qreal currentX    = normalizedX * (qreal)( rowsCurrentLevel );
        qreal currentY    = normalizedY * (qreal)( columnsCurrentLevel );

        const QDateTime now = QDateTime::currentDateTime();
        QDateTime lastModified;

        bool download = false;
        bool currentTileAvailable = false;

        TextureTile *currentTile = 0;
        TileId currentTileId( currentLevel, (int)(currentX), (int)(currentY) );

        // Check whether the current tile id is available in the CACHE:
        if ( tileCache ) {
            currentTile = tileCache->take( currentTileId );

            if ( currentTile ) {
                // the tile was in the cache, but is it up to date?
                lastModified = currentTile->created();
                if ( lastModified.secsTo( now ) < textureLayer->expire()) {
                    temptile = currentTile->rawtile();
                    currentTileAvailable = true;
                } else {
                    delete currentTile;
                    currentTile = 0;
                }
            }
        }
        // If the current tile id is not in the cache or if it was
        // in the cache but has expired load from DISK:

        if ( !currentTile ) {
            QString relfilename = TileLoaderHelper::relativeTileFileName( textureLayer,
                                                                        currentLevel, (int)(currentX), (int)(currentY) );
            absfilename = MarbleDirs::path( relfilename );
            const QFileInfo fileInfo( absfilename );
            lastModified = fileInfo.lastModified();

            // - if the file does not exist, we want to download it and search an
            //   existing tile of a lower zoom level for imediate display
            // - if the file exists and is expired according to the value of the
            //   expire element we want to download it again and display the old
            //   tile until the new one is there. Once the updated tile is
            //   available, it should get displayed.

            if ( !fileInfo.exists() ) {
//                qDebug() << "File does not exist:" << fileInfo.filePath();
                download = true;
            }
            else if ( lastModified.secsTo( now ) > textureLayer->expire() ) {
//                qDebug() << "File does exist, but is expired:" << fileInfo.filePath()
//                        << "age (seconds):" << lastModified.secsTo( now )
//                        << "allowed age:" << textureLayer->expire();
                download = true;
            }

            if ( fileInfo.exists() ) {

                temptile.load( absfilename );
                // qDebug() << "TextureTile::loadDataset "
                //          << "depth:" << temptile.depth()
                //          << "format:" << temptile.format()
                //          << "bytesPerLine:" << temptile.bytesPerLine()
                //          << "numBytes:" << temptile.numBytes() ;
                currentTileAvailable = true;
            }
        }

        if ( currentTileAvailable ) {
            if ( !temptile.isNull() ) {

                // Don't scale if the current tile isn't a fallback
                if ( level != currentLevel ) {
                    scaleTileFrom( textureLayer, temptile, currentX, currentY, currentLevel, x, y, level );
                }
                else {
                    d->m_state = TileComplete;
                }

                d->m_rawtile = temptile;
                d->m_created = lastModified;
                tileFound = true;
            }
        }

        if ( download ) {
            QUrl sourceUrl = TileLoaderHelper::downloadUrl( textureLayer, level, x, y );
            QString destFileName = TileLoaderHelper::relativeTileFileName( textureLayer,
                                                                           level, x, y );
//            qDebug() << "emit downloadTile(" << sourceUrl << destFileName << ");";
            emit downloadTile( sourceUrl, destFileName, d->m_id.toString() );
        }
    }

//    qDebug() << "TextureTile::loadDataset end";

    d->m_depth = d->m_rawtile.depth();

//    qDebug() << "m_depth =" << m_depth;
}

void TextureTile::loadTile( bool requestTileUpdate )
{
    //    qDebug() << "Entered loadTile( int, int, int) of Tile" << m_id;

    if ( d->m_rawtile.isNull() ) {
        qDebug() << "An essential tile is missing. Please rerun the application.";
        exit(-1);
    }

    switch ( d->m_depth ) {
        case 48:
        case 32:
            if ( d->jumpTable32 )
                delete [] d->jumpTable32;
            d->jumpTable32 = jumpTableFromQImage32( d->m_rawtile );
            break;
        case 8:
        case 1:
            if ( d->jumpTable8 )
                delete [] d->jumpTable8;
            d->jumpTable8 = jumpTableFromQImage8( d->m_rawtile );
            break;
        default:
            qDebug() << QString("Color m_depth %1 of tile could not be retrieved. Exiting.").arg(d->m_depth);
            exit( -1 );
    }

    d->m_isGrayscale = d->m_rawtile.isGrayscale();

    if ( requestTileUpdate ) {
        // qDebug() << "TileUpdate available";
        emit tileUpdateDone();
    }
}

void TextureTile::scaleTileFrom( GeoSceneTexture *textureLayer, QImage &tile, qreal sourceX, qreal sourceY, int sourceLevel, int targetX, int targetY, int targetLevel )
{
    const int levelZeroColumns = textureLayer->levelZeroColumns();
    const int levelZeroRows = textureLayer->levelZeroRows();
    const int rowsRequestedLevel = TileLoaderHelper::levelToRow( levelZeroRows, targetLevel );
    const int columnsRequestedLevel = TileLoaderHelper::levelToColumn( levelZeroColumns, targetLevel );
    const int rowsCurrentLevel = TileLoaderHelper::levelToRow( levelZeroRows, sourceLevel );
    const int columnsCurrentLevel = TileLoaderHelper::levelToColumn( levelZeroColumns, sourceLevel );

    // qDebug() << "About to start cropping an existing image.";

    QSize tilesize = tile.size();
    qreal normalizedX2 = (qreal)(targetX + 1) / (qreal)( rowsRequestedLevel );
    qreal normalizedY2 = (qreal)(targetY + 1) / (qreal)( columnsRequestedLevel );
    qreal currentX2    = normalizedX2 * (qreal)( rowsCurrentLevel );
    qreal currentY2    = normalizedY2 * (qreal)( columnsCurrentLevel );

    // Determine the rectangular section of the previous tile data
    // which we intend to copy from:
    int left   = (int)( ( sourceX    - (int)( sourceX ) ) * tile.width() );
    int top    = (int)( ( sourceY    - (int)( sourceY ) ) * tile.height() );
    int right  = (int)( ( currentX2  - (int)( sourceX ) ) * tile.width() ) - 1;
    int bottom = (int)( ( currentY2  - (int)( sourceY ) ) * tile.height() ) - 1;

    // Important: Scaling a null image during the next step would be fatal
    // So we make sure the width and height is at least 1.
    int rectWidth  = ( right - left > 1 ) ? right  - left : 1;
    int rectHeight = ( bottom - top > 1 ) ? bottom - top  : 1;

    // This should not create any memory leaks as
    // 'copy' and 'scaled' return a value (on the
    // stack) which gets deep copied always into the
    // same place for m_rawtile on the heap:
    tile = tile.copy( left, top, rectWidth, rectHeight );
    tile = tile.scaled( tilesize ); // TODO: use correct size
    d->m_state = TilePartial;
    // qDebug() << "Finished scaling up the Temporary Tile.";

}

const QDateTime & TextureTile::created() const
{
    return d->m_created;
}

uint TextureTile::pixel( int x, int y ) const
{
    if ( d->m_depth == 1 || d->m_depth == 8 ) {
        if ( !d->m_isGrayscale )
            return d->m_rawtile.pixel( x, y );
        else
            return (d->jumpTable8)[y][x];
    }
    return (d->jumpTable32)[y][x];
}

TileId const& TextureTile::id() const { return d->m_id; }

int TextureTile::depth() const { return d->m_depth; }

bool TextureTile::used() const { return d->m_used; }
void TextureTile::setUsed( bool used ) { d->m_used = used; }

int TextureTile::numBytes() const { return d->m_rawtile.numBytes(); }

TextureTile::TileState TextureTile::state() const { return d->m_state; }
void TextureTile::setState( TileState state ) { d->m_state = state; }

const QImage& TextureTile::rawtile() { return d->m_rawtile; }

QImage * TextureTile::tile() { return &(d->m_rawtile); }

#include "TextureTile.moc"
<commit_msg>extra ';'<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 Torsten Rahn <tackat@kde.org>"
// Copyright 2007      Inge Wallin  <ingwa@kde.org>"
// Copyright 2008      Jens-Michael Hoffmann <jensmh@gmx.de>
//

#include "TextureTile.h"

#include <QtCore/QDateTime>
#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
#include <QtGui/QImage>

#include <cmath>

#include "global.h"
#include "GeoSceneTexture.h"
#include "MarbleDirs.h"
#include "TileLoaderHelper.h"

namespace Marble {

class TextureTilePrivate {
 public:
    uchar   **jumpTable8;
    uint    **jumpTable32;

    TileId    m_id;

    QImage    m_rawtile;

    int       m_depth;
    bool      m_isGrayscale;
    bool      m_used;

    TextureTile::TileState m_state;

    QDateTime m_created;

    TextureTilePrivate(const TileId& id) :
      jumpTable8(0),
      jumpTable32(0),
      m_id(id),
      m_rawtile(),
      m_depth(0),
      m_isGrayscale(false),
      m_used(false),
      m_state(TextureTile::TileEmpty),
      m_created(QDateTime::currentDateTime()) { }

    ~TextureTilePrivate() {
      delete [] jumpTable32;
      delete [] jumpTable8;
    }
};

}

using namespace Marble;

static uint **jumpTableFromQImage32( QImage &img )
{
    const int  height = img.height();
    const int  bpl    = img.bytesPerLine() / 4;
    uint      *data = (QRgb*)(img.scanLine(0));
    uint     **jumpTable = new uint*[height];

    for ( int y = 0; y < height; ++y ) {
        jumpTable[ y ] = data;
        data += bpl;
    }

    return jumpTable;
}

static uchar **jumpTableFromQImage8( QImage &img )
{
    const int  height = img.height();
    const int  bpl    = img.bytesPerLine();
    uchar     *data = img.bits();
    uchar    **jumpTable = new uchar*[height];

    for ( int y = 0; y < height; ++y ) {
        jumpTable[ y ] = data;
        data += bpl;
    }

    return jumpTable;
}

TextureTile::TextureTile( TileId const& id )
    : QObject(),
      d(new TextureTilePrivate(id))
{
}

TextureTile::~TextureTile()
{
    delete d;
}

void TextureTile::loadDataset( GeoSceneTexture *textureLayer, int level, int x, int y, QCache<TileId, TextureTile> *tileCache )
{
    // qDebug() << "TextureTile::loadDataset" << level << x << y;
    QImage temptile;

    d->m_used = true; // Needed to avoid frequent deletion of tiles

    QString  absfilename;

    // If the tile level offers the requested tile then load it.
    // Otherwise cycle from the requested tilelevel down to one where
    // the requested area is covered.  Then scale the area to create a
    // replacement for the tile that has been requested.

    const int levelZeroColumns = textureLayer->levelZeroColumns();
    const int levelZeroRows = textureLayer->levelZeroRows();
    const int rowsRequestedLevel = TileLoaderHelper::levelToRow( levelZeroRows, level );
    const int columnsRequestedLevel = TileLoaderHelper::levelToColumn( levelZeroColumns, level );
    bool tileFound = false;
    for ( int currentLevel = level; !tileFound && currentLevel > -1; --currentLevel ) {

        const int rowsCurrentLevel =
            TileLoaderHelper::levelToRow( levelZeroRows, currentLevel );
        const int columnsCurrentLevel =
            TileLoaderHelper::levelToColumn( levelZeroColumns, currentLevel );

        qreal normalizedX = (qreal)(x) / (qreal)( rowsRequestedLevel );
        qreal normalizedY = (qreal)(y) / (qreal)( columnsRequestedLevel );
        qreal currentX    = normalizedX * (qreal)( rowsCurrentLevel );
        qreal currentY    = normalizedY * (qreal)( columnsCurrentLevel );

        const QDateTime now = QDateTime::currentDateTime();
        QDateTime lastModified;

        bool download = false;
        bool currentTileAvailable = false;

        TextureTile *currentTile = 0;
        TileId currentTileId( currentLevel, (int)(currentX), (int)(currentY) );

        // Check whether the current tile id is available in the CACHE:
        if ( tileCache ) {
            currentTile = tileCache->take( currentTileId );

            if ( currentTile ) {
                // the tile was in the cache, but is it up to date?
                lastModified = currentTile->created();
                if ( lastModified.secsTo( now ) < textureLayer->expire()) {
                    temptile = currentTile->rawtile();
                    currentTileAvailable = true;
                } else {
                    delete currentTile;
                    currentTile = 0;
                }
            }
        }
        // If the current tile id is not in the cache or if it was
        // in the cache but has expired load from DISK:

        if ( !currentTile ) {
            QString relfilename = TileLoaderHelper::relativeTileFileName( textureLayer,
                                                                        currentLevel, (int)(currentX), (int)(currentY) );
            absfilename = MarbleDirs::path( relfilename );
            const QFileInfo fileInfo( absfilename );
            lastModified = fileInfo.lastModified();

            // - if the file does not exist, we want to download it and search an
            //   existing tile of a lower zoom level for imediate display
            // - if the file exists and is expired according to the value of the
            //   expire element we want to download it again and display the old
            //   tile until the new one is there. Once the updated tile is
            //   available, it should get displayed.

            if ( !fileInfo.exists() ) {
//                qDebug() << "File does not exist:" << fileInfo.filePath();
                download = true;
            }
            else if ( lastModified.secsTo( now ) > textureLayer->expire() ) {
//                qDebug() << "File does exist, but is expired:" << fileInfo.filePath()
//                        << "age (seconds):" << lastModified.secsTo( now )
//                        << "allowed age:" << textureLayer->expire();
                download = true;
            }

            if ( fileInfo.exists() ) {

                temptile.load( absfilename );
                // qDebug() << "TextureTile::loadDataset "
                //          << "depth:" << temptile.depth()
                //          << "format:" << temptile.format()
                //          << "bytesPerLine:" << temptile.bytesPerLine()
                //          << "numBytes:" << temptile.numBytes() ;
                currentTileAvailable = true;
            }
        }

        if ( currentTileAvailable ) {
            if ( !temptile.isNull() ) {

                // Don't scale if the current tile isn't a fallback
                if ( level != currentLevel ) {
                    scaleTileFrom( textureLayer, temptile, currentX, currentY, currentLevel, x, y, level );
                }
                else {
                    d->m_state = TileComplete;
                }

                d->m_rawtile = temptile;
                d->m_created = lastModified;
                tileFound = true;
            }
        }

        if ( download ) {
            QUrl sourceUrl = TileLoaderHelper::downloadUrl( textureLayer, level, x, y );
            QString destFileName = TileLoaderHelper::relativeTileFileName( textureLayer,
                                                                           level, x, y );
//            qDebug() << "emit downloadTile(" << sourceUrl << destFileName << ");";
            emit downloadTile( sourceUrl, destFileName, d->m_id.toString() );
        }
    }

//    qDebug() << "TextureTile::loadDataset end";

    d->m_depth = d->m_rawtile.depth();

//    qDebug() << "m_depth =" << m_depth;
}

void TextureTile::loadTile( bool requestTileUpdate )
{
    //    qDebug() << "Entered loadTile( int, int, int) of Tile" << m_id;

    if ( d->m_rawtile.isNull() ) {
        qDebug() << "An essential tile is missing. Please rerun the application.";
        exit(-1);
    }

    switch ( d->m_depth ) {
        case 48:
        case 32:
            if ( d->jumpTable32 )
                delete [] d->jumpTable32;
            d->jumpTable32 = jumpTableFromQImage32( d->m_rawtile );
            break;
        case 8:
        case 1:
            if ( d->jumpTable8 )
                delete [] d->jumpTable8;
            d->jumpTable8 = jumpTableFromQImage8( d->m_rawtile );
            break;
        default:
            qDebug() << QString("Color m_depth %1 of tile could not be retrieved. Exiting.").arg(d->m_depth);
            exit( -1 );
    }

    d->m_isGrayscale = d->m_rawtile.isGrayscale();

    if ( requestTileUpdate ) {
        // qDebug() << "TileUpdate available";
        emit tileUpdateDone();
    }
}

void TextureTile::scaleTileFrom( GeoSceneTexture *textureLayer, QImage &tile, qreal sourceX, qreal sourceY, int sourceLevel, int targetX, int targetY, int targetLevel )
{
    const int levelZeroColumns = textureLayer->levelZeroColumns();
    const int levelZeroRows = textureLayer->levelZeroRows();
    const int rowsRequestedLevel = TileLoaderHelper::levelToRow( levelZeroRows, targetLevel );
    const int columnsRequestedLevel = TileLoaderHelper::levelToColumn( levelZeroColumns, targetLevel );
    const int rowsCurrentLevel = TileLoaderHelper::levelToRow( levelZeroRows, sourceLevel );
    const int columnsCurrentLevel = TileLoaderHelper::levelToColumn( levelZeroColumns, sourceLevel );

    // qDebug() << "About to start cropping an existing image.";

    QSize tilesize = tile.size();
    qreal normalizedX2 = (qreal)(targetX + 1) / (qreal)( rowsRequestedLevel );
    qreal normalizedY2 = (qreal)(targetY + 1) / (qreal)( columnsRequestedLevel );
    qreal currentX2    = normalizedX2 * (qreal)( rowsCurrentLevel );
    qreal currentY2    = normalizedY2 * (qreal)( columnsCurrentLevel );

    // Determine the rectangular section of the previous tile data
    // which we intend to copy from:
    int left   = (int)( ( sourceX    - (int)( sourceX ) ) * tile.width() );
    int top    = (int)( ( sourceY    - (int)( sourceY ) ) * tile.height() );
    int right  = (int)( ( currentX2  - (int)( sourceX ) ) * tile.width() ) - 1;
    int bottom = (int)( ( currentY2  - (int)( sourceY ) ) * tile.height() ) - 1;

    // Important: Scaling a null image during the next step would be fatal
    // So we make sure the width and height is at least 1.
    int rectWidth  = ( right - left > 1 ) ? right  - left : 1;
    int rectHeight = ( bottom - top > 1 ) ? bottom - top  : 1;

    // This should not create any memory leaks as
    // 'copy' and 'scaled' return a value (on the
    // stack) which gets deep copied always into the
    // same place for m_rawtile on the heap:
    tile = tile.copy( left, top, rectWidth, rectHeight );
    tile = tile.scaled( tilesize ); // TODO: use correct size
    d->m_state = TilePartial;
    // qDebug() << "Finished scaling up the Temporary Tile.";

}

const QDateTime & TextureTile::created() const
{
    return d->m_created;
}

uint TextureTile::pixel( int x, int y ) const
{
    if ( d->m_depth == 1 || d->m_depth == 8 ) {
        if ( !d->m_isGrayscale )
            return d->m_rawtile.pixel( x, y );
        else
            return (d->jumpTable8)[y][x];
    }
    return (d->jumpTable32)[y][x];
}

TileId const& TextureTile::id() const { return d->m_id; }

int TextureTile::depth() const { return d->m_depth; }

bool TextureTile::used() const { return d->m_used; }
void TextureTile::setUsed( bool used ) { d->m_used = used; }

int TextureTile::numBytes() const { return d->m_rawtile.numBytes(); }

TextureTile::TileState TextureTile::state() const { return d->m_state; }
void TextureTile::setState( TileState state ) { d->m_state = state; }

const QImage& TextureTile::rawtile() { return d->m_rawtile; }

QImage * TextureTile::tile() { return &(d->m_rawtile); }

#include "TextureTile.moc"
<|endoftext|>


<commit_before>
// (c) COPYRIGHT URI/MIT 1997
// Please read the full copyright statement in the file COPYRIGH.
//
// Authors:
//      jhrg,jimg       James Gallagher (jgallagher@gso.uri.edu)

// Implementation of the DODSFilter class. This class is used to build dods
// filter programs which, along with a CGI program, comprise DODS servers.
// jhrg 8/26/97

// $Log: DODSFilter.cc,v $
// Revision 1.6  1998/12/16 19:10:53  jimg
// Added support for XDODS-Server MIME header. This fixes a problem where our use of Server clashed with Java
//
// Revision 1.5  1998/11/10 01:04:42  jimg
// Added `ends' to strings made with ostrstream (fixes a bug found with
// purify).
// Added catch for throws from within the CE evaluation functions.
//
// Revision 1.4  1998/08/06 16:12:30  jimg
// Added cache dir methods and stuff to ctor (from jeh)
//
// Revision 1.3  1998/03/19 23:34:21  jimg
// Fixed calls to set_mime_*().
// Removed the compression code (it is now in DDS::send().
// Removed old code (that was surrounded by #if 0 ... #endif).
//
// Revision 1.2  1998/02/11 22:00:46  jimg
// Added call to util.cc:deflate_exists() to send_data(). This means that
// send_data() will only try to start the compressor if an executable copy of
// deflate can be found. If, for any reason a copy of deflate cannot be found
// data is sent without trying to compress it.
//
// Revision 1.1  1997/08/28 20:39:02  jimg
// Created
//

#ifdef __GNUG__
#pragma "implemenation"
#endif

#include "config_dap.h"

static char rcsid[] __unused__ = {"$Id: DODSFilter.cc,v 1.6 1998/12/16 19:10:53 jimg Exp $"};

#include <iostream.h>
#include <strstream.h>
#include <String.h>
#include <GetOpt.h>

#include "DAS.h"
#include "DDS.h"
#include "debug.h"
#include "cgi_util.h"
#include "DODSFilter.h"

DODSFilter::DODSFilter(int argc,char *argv[]) : comp(false), ver(false),
    bad_options(false), dataset(""), ce(""), cgi_ver(""),
    anc_dir(""), anc_file(""), cache_dir("")
{
    program_name = argv[0];

    int option_char;
    GetOpt getopt (argc, argv, "ce:v:d:f:r:");

    while ((option_char = getopt()) != EOF)
	switch (option_char) {
	  case 'c': comp = true; break;
	  case 'e': ce = getopt.optarg; break;
	  case 'v': ver = true; cgi_ver = getopt.optarg; break;
	  case 'd': anc_dir = getopt.optarg; break;
	  case 'f': anc_file = getopt.optarg; break;
	  case 'r': cache_dir = getopt.optarg; break;
	  default: bad_options = true; break;
	}

    int next_arg = getopt.optind;
    if(next_arg < argc)
	dataset = argv[next_arg];
    else
	bad_options = true;
}

DODSFilter::~DODSFilter()
{
}

bool
DODSFilter::OK()
{

    return !bad_options;
}

bool
DODSFilter::version()
{
    return ver;
}

String
DODSFilter::get_ce()
{
    return ce;
}

String
DODSFilter::get_dataset_name()
{
    return dataset;
}

String
DODSFilter::get_dataset_version()
{
    return "";
}

String
DODSFilter::get_cache_dir()
{
  return cache_dir;
}

bool
DODSFilter::read_ancillary_das(DAS &das)
{
    String name = find_ancillary_file(dataset, "das", anc_dir, anc_file);
    FILE *in = fopen((const char *)name, "r");

    if (in) {
	int status = das.parse(in);
	fclose(in);

	if(!status) {
	    String msg = "Parse error in external file " + dataset + ".das";

	    // server error message
	    ErrMsgT(msg);

	    // client error message
	    set_mime_text(cout, dods_error);
	    Error e(malformed_expr, msg);
	    e.print(cout);

	    return false;
	}
    }

    return true;
}

bool
DODSFilter::read_ancillary_dds(DDS &dds)
{
    String name = find_ancillary_file(dataset, "dds", anc_dir, anc_file);
    FILE *in = fopen((const char *)name, "r");

    if (in) {
	int status = dds.parse(in);
	fclose(in);

	if(!status) {
	    String msg = "Parse error in external file " + dataset + ".dds";

	    // server error message
	    ErrMsgT(msg);

	    // client error message
	    set_mime_text(cout, dods_error);
	    Error e(malformed_expr, msg);
	    e.print(cout);

	    return false;
	}
    }

    return true;
}

static const char *emessage = \
"DODS internal server error. Please report this to the dataset maintainer, \
or to support@dods.gso.uri.edu.";

void
DODSFilter::print_usage()
{
    // Write a message to the WWW server error log file.
    ostrstream oss;
    oss << "Usage: " << program_name
	<< " [-c] [-v <cgi version>] [-e <ce>]"
	<< " [-d <ancillary file directory>] [-f <ancillary file name>]"
	<< " <dataset>" << ends;
    ErrMsgT(oss.str());
    oss.freeze(0);

    // Build an error object to return to the user.
    Error e(unknown_error, emessage);
    set_mime_text(cout, dods_error);
    e.print(cout);
}

void
DODSFilter::send_version_info()
{
    cout << "HTTP/1.0 200 OK" << endl
	 << "XDODS-Server: " << DVR << endl
	 << "Content-Type: text/plain" << endl
	 << endl;

    cout << "Core software version: " << DVR << endl;

    if (cgi_ver != "")
	cout << "Server Script Revision: " << cgi_ver << endl;

    String v = get_dataset_version();
    if (v != "")
	cout << "Dataset version: " << v << endl;
}

bool
DODSFilter::send_das(DAS &das)
{
    set_mime_text(cout, dods_das);
    das.print(cout);

    return true;
}

bool
DODSFilter::send_dds(DDS &dds, bool constrained)
{
    if (constrained) {
	if (!dds.parse_constraint(ce, cout, true)) {
	    String m = program_name + ": parse error in constraint: "
		+  ce;
	    ErrMsgT(m);

	    set_mime_text(cout, dods_error);
	    Error e(unknown_error, m);
	    e.print(cout);

	    return false;
	}
	set_mime_text(cout, dods_dds);
	dds.print_constrained(cout);  // send constrained DDS
    }
    else {
	set_mime_text(cout, dods_dds);
	dds.print(cout);
    }

    return true;
}

bool
DODSFilter::send_data(DDS &dds, FILE *data_stream)
{
    bool compress = comp && deflate_exists();

    // This catch is a quick & dirty hack for exceptions thrown by the new
    // (11/6/98) projection functions in CEs. I might add exceptions to other
    // parts of the CE parser and evaluator. Eventually, the C++ classes
    // should switch to exceptions. 11/6/98 jhrg
    try {
	if (!dds.send(dataset, ce, data_stream, compress)) {
	    ErrMsgT((compress) ? "Could not send compressed data" :
		    "Could not send data");
	    return false;
	}
    }
    catch (Error &e) {
	set_mime_text(cout, dods_error);
	e.print(cout);

	return false;
    }

    return true;
}

<commit_msg>Added the get_accept_types() accessor. Changed the ctor so that the -t option is recognized.<commit_after>
// (c) COPYRIGHT URI/MIT 1997
// Please read the full copyright statement in the file COPYRIGH.
//
// Authors:
//      jhrg,jimg       James Gallagher (jgallagher@gso.uri.edu)

// Implementation of the DODSFilter class. This class is used to build dods
// filter programs which, along with a CGI program, comprise DODS servers.
// jhrg 8/26/97

// $Log: DODSFilter.cc,v $
// Revision 1.7  1999/02/22 22:59:07  jimg
// Added the get_accept_types() accessor.
// Changed the ctor so that the -t option is recognized.
//
// Revision 1.6  1998/12/16 19:10:53  jimg
// Added support for XDODS-Server MIME header. This fixes a problem where our
// use of Server clashed with Java.
//
// Revision 1.5  1998/11/10 01:04:42  jimg
// Added `ends' to strings made with ostrstream (fixes a bug found with
// purify).
// Added catch for throws from within the CE evaluation functions.
//
// Revision 1.4  1998/08/06 16:12:30  jimg
// Added cache dir methods and stuff to ctor (from jeh)
//
// Revision 1.3  1998/03/19 23:34:21  jimg
// Fixed calls to set_mime_*().
// Removed the compression code (it is now in DDS::send().
// Removed old code (that was surrounded by #if 0 ... #endif).
//
// Revision 1.2  1998/02/11 22:00:46  jimg
// Added call to util.cc:deflate_exists() to send_data(). This means that
// send_data() will only try to start the compressor if an executable copy of
// deflate can be found. If, for any reason a copy of deflate cannot be found
// data is sent without trying to compress it.
//
// Revision 1.1  1997/08/28 20:39:02  jimg
// Created
//

#ifdef __GNUG__
#pragma "implemenation"
#endif

#include "config_dap.h"

static char rcsid[] __unused__ = {"$Id: DODSFilter.cc,v 1.7 1999/02/22 22:59:07 jimg Exp $"};

#include <iostream.h>
#include <strstream.h>
#include <String.h>
#include <GetOpt.h>

#include "DAS.h"
#include "DDS.h"
#include "debug.h"
#include "cgi_util.h"
#include "DODSFilter.h"

DODSFilter::DODSFilter(int argc,char *argv[]) : comp(false), ver(false),
    bad_options(false), dataset(""), ce(""), cgi_ver(""),
    anc_dir(""), anc_file(""), cache_dir(""), accept_types("All")
{
    program_name = argv[0];

    int option_char;
    GetOpt getopt (argc, argv, "ce:v:d:f:r:t:");

    while ((option_char = getopt()) != EOF)
	switch (option_char) {
	  case 'c': comp = true; break;
	  case 'e': ce = getopt.optarg; break;
	  case 'v': ver = true; cgi_ver = getopt.optarg; break;
	  case 'd': anc_dir = getopt.optarg; break;
	  case 'f': anc_file = getopt.optarg; break;
	  case 'r': cache_dir = getopt.optarg; break;
	  case 't': accept_types = getopt.optarg; break;
	  default: bad_options = true; break;
	}

    int next_arg = getopt.optind;
    if(next_arg < argc)
	dataset = argv[next_arg];
    else
	bad_options = true;
}

DODSFilter::~DODSFilter()
{
}

bool
DODSFilter::OK()
{

    return !bad_options;
}

bool
DODSFilter::version()
{
    return ver;
}

String
DODSFilter::get_ce()
{
    return ce;
}

String
DODSFilter::get_dataset_name()
{
    return dataset;
}

String
DODSFilter::get_dataset_version()
{
    return "";
}

String
DODSFilter::get_cache_dir()
{
  return cache_dir;
}

String
DODSFilter::get_accept_types()
{
    return accept_types;
}

bool
DODSFilter::read_ancillary_das(DAS &das)
{
    String name = find_ancillary_file(dataset, "das", anc_dir, anc_file);
    FILE *in = fopen((const char *)name, "r");

    if (in) {
	int status = das.parse(in);
	fclose(in);

	if(!status) {
	    String msg = "Parse error in external file " + dataset + ".das";

	    // server error message
	    ErrMsgT(msg);

	    // client error message
	    set_mime_text(cout, dods_error);
	    Error e(malformed_expr, msg);
	    e.print(cout);

	    return false;
	}
    }

    return true;
}

bool
DODSFilter::read_ancillary_dds(DDS &dds)
{
    String name = find_ancillary_file(dataset, "dds", anc_dir, anc_file);
    FILE *in = fopen((const char *)name, "r");

    if (in) {
	int status = dds.parse(in);
	fclose(in);

	if(!status) {
	    String msg = "Parse error in external file " + dataset + ".dds";

	    // server error message
	    ErrMsgT(msg);

	    // client error message
	    set_mime_text(cout, dods_error);
	    Error e(malformed_expr, msg);
	    e.print(cout);

	    return false;
	}
    }

    return true;
}

static const char *emessage = \
"DODS internal server error. Please report this to the dataset maintainer, \
or to support@dods.gso.uri.edu.";

void
DODSFilter::print_usage()
{
    // Write a message to the WWW server error log file.
    ostrstream oss;
    oss << "Usage: " << program_name
	<< " [-c] [-v <cgi version>] [-e <ce>]"
	<< " [-d <ancillary file directory>] [-f <ancillary file name>]"
	<< " <dataset>" << ends;
    ErrMsgT(oss.str());
    oss.freeze(0);

    // Build an error object to return to the user.
    Error e(unknown_error, emessage);
    set_mime_text(cout, dods_error);
    e.print(cout);
}

void
DODSFilter::send_version_info()
{
    cout << "HTTP/1.0 200 OK" << endl
	 << "XDODS-Server: " << DVR << endl
	 << "Content-Type: text/plain" << endl
	 << endl;

    cout << "Core software version: " << DVR << endl;

    if (cgi_ver != "")
	cout << "Server Script Revision: " << cgi_ver << endl;

    String v = get_dataset_version();
    if (v != "")
	cout << "Dataset version: " << v << endl;
}

bool
DODSFilter::send_das(DAS &das)
{
    set_mime_text(cout, dods_das);
    das.print(cout);

    return true;
}

bool
DODSFilter::send_dds(DDS &dds, bool constrained)
{
    if (constrained) {
	if (!dds.parse_constraint(ce, cout, true)) {
	    String m = program_name + ": parse error in constraint: "
		+  ce;
	    ErrMsgT(m);

	    set_mime_text(cout, dods_error);
	    Error e(unknown_error, m);
	    e.print(cout);

	    return false;
	}
	set_mime_text(cout, dods_dds);
	dds.print_constrained(cout);  // send constrained DDS
    }
    else {
	set_mime_text(cout, dods_dds);
	dds.print(cout);
    }

    return true;
}

bool
DODSFilter::send_data(DDS &dds, FILE *data_stream)
{
    bool compress = comp && deflate_exists();

    // This catch is a quick & dirty hack for exceptions thrown by the new
    // (11/6/98) projection functions in CEs. I might add exceptions to other
    // parts of the CE parser and evaluator. Eventually, the C++ classes
    // should switch to exceptions. 11/6/98 jhrg
    try {
	if (!dds.send(dataset, ce, data_stream, compress)) {
	    ErrMsgT((compress) ? "Could not send compressed data" :
		    "Could not send data");
	    return false;
	}
    }
    catch (Error &e) {
	set_mime_text(cout, dods_error);
	e.print(cout);

	return false;
    }

    return true;
}

<|endoftext|>


<commit_before>#include <iostream>
#include <string>

void run_part_one() {
}
void run_part_two() {
}

int main(int argc, char* argv[]) {
    if (argc > 1) {
        if (std::string(argv[1]) == "--part_two") {
            run_part_two();
        } else {
            std::cout << "Usage: day3 [--part_two]" << std::endl;
            return -1;
        }
    } else {
        run_part_one();
    }
}
<commit_msg>added runtime logic for day3<commit_after>#include <iostream>
#include <string>

#include "SantaMap.hpp"

void run_part_one() {
    SantaMap map;
    char movement;
    while (std::cin>>movement) {
        map.move(movement);
    }
    std::cout << map.get_visited_houses() << std::endl;
}
void run_part_two() {
}

int main(int argc, char* argv[]) {
    if (argc > 1) {
        if (std::string(argv[1]) == "--part_two") {
            run_part_two();
        } else {
            std::cout << "Usage: day3 [--part_two]" << std::endl;
            return -1;
        }
    } else {
        run_part_one();
    }
}
<|endoftext|>