<commit_before>#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>

using namespace cv;
using namespace std;

struct PointWithGradient {
	Point pos;
	int gradient;
};

class ComparePWG {
    public:

	// Returns true if t1 has a higher gradient than t2
    bool operator()(PointWithGradient& t1, PointWithGradient& t2) {
       if (t1.gradient > t2.gradient) return true;
       return false;
    }
};

priority_queue<PointWithGradient, vector<PointWithGradient>, ComparePWG> pq, backupQueue;
Mat usedPixels;
Mat mask;
int edgeThresh = 1;
Mat original;

// define a trackbar callback
static void onTrackbar(int, void*)
{
	Mat im = original.clone();
	Mat up = usedPixels.clone();

  mask = Scalar::all(0);
  int i=0;
  while (!pq.empty()) {

       PointWithGradient t2 = pq.top();

	  if(mask.at<uchar>(t2.pos.x-1, t2.pos.y-1) == 0) {
		  i++;
		  Vec3b c1 = im.at<Vec3b>(t2.pos);
		Scalar newVal = Scalar(c1[0], c1[1], c1[2]);
		   int lo = edgeThresh/2;
		   int up = edgeThresh/2;
		   int flags = 4 + (255 << 8); // + FLOODFILL_MASK_ONLY;
		   //Rect ccomp;

		   floodFill(im, mask, t2.pos, newVal, 0, Scalar(lo, lo, lo), Scalar(up, up, up), flags);

	  }

	   /*
	   // if the pixel at position t2 has not been used before
	   if(up.at<uchar>(t2.pos) == 255) {

		   // store the current pixel's color
		   Vec3b c1 = im.at<Vec3b>(t2.pos);

		   // create a region for the current pixel
			vector<Point> region;
			region.push_back(t2.pos);

		   // mark pixel as used
		   up.at<uchar>(t2.pos) = 0;

		   // iterate over all 4-connected pixels
		   for(int i=-1; i<=1; i+=2) {
			for(int j=-1; j<=1; j+=2) {

				// Existiert der Punkt berhaupt? Pixel am Rand haben ja nur 3 bzw. an den Ecken 2 4-connected Nachbarn
				if(t2.pos.x + i >= 0 && t2.pos.x + i < im.cols && t2.pos.y + j >= 0 && t2.pos.y + j < im.rows) {
					Point p = Point(t2.pos.x + i, t2.pos.y + j);
					if(up.at<uchar>(p) == 255) {
						// pixel not yet used
						// color distance zwischen dem Punkt aus der Priority Queue (t2) und dem aktuellen Nachbarn (p) berechnen
						Vec3b c2 = im.at<Vec3b>(p);
						double colorDistance = sqrt((c1[0]-c2[0])*(c1[0]-c2[0]) + (c1[1]-c2[1])*(c1[1]-c2[1]) + (c1[2]-c2[2])*(c1[2]-c2[2]));
						if(colorDistance < edgeThresh) {
							region.push_back(p);
							// TODO: diese 2 Zeilen entfernen
							im.at<Vec3b>(p) = im.at<Vec3b>(t2.pos);
							up.at<uchar>(p) = 0;
						}
					}
				}
			}
		   }

		   // TODO: ber region iterieren, Durchschnittsfarbe berechnen, und jeden Pixel mit dieser Farbe einfrben!

	   }*/

	   backupQueue.push(t2);
       pq.pop();
    }

	  cout << i << endl;

	pq.swap(backupQueue);
    cv::imshow("Edge map", im);
	cv::imshow("Mask", mask);
}

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

  Mat src, src_gray;
  Mat grad;
  int scale = 1;
  int delta = 0;
  int ddepth = CV_16S;

  int c;

  /// Load an image
  src = imread( "C:/Users/Timo/Desktop/test.jpg", 1 );
  original = src.clone();

  if( !src.data )
  { return -1; }

  GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );

  /// Convert it to gray
  cvtColor( src, src_gray, CV_RGB2GRAY );

  /// Generate grad_x and grad_y
  Mat grad_x, grad_y;
  Mat abs_grad_x, abs_grad_y;

  /// Gradient X
  Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );
  convertScaleAbs( grad_x, abs_grad_x );

  /// Gradient Y
  Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );
  convertScaleAbs( grad_y, abs_grad_y );

  /// Total Gradient (approximate)
  addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );

  usedPixels = grad.clone();

  mask.create(src.rows+2, src.cols+2, CV_8UC1);

  // ber alle Pixel iterieren, um sie in die PriorityQueue einzusortieren
  for(int y=0;y<grad.rows;y++)
	{
		for(int x=0;x<grad.cols;x++)
		{
			// Gradient fr jeden Pixel auslesen
			int gradient = grad.at<uchar>(Point(x,y));

			// usedPixels wird als weies Bild initialisiert, hier wird spter gespeichert, welche Pixel beim Auslesen der Priority Queue schon verwendet wurden
			usedPixels.at<uchar>(Point(x,y)) = 255;

			PointWithGradient pwg = PointWithGradient();
			pwg.gradient = gradient;
			pwg.pos = Point(x,y);

			// Store PWG in PriorityQueue
			pq.push(pwg);

		}
	}

    // create a toolbar

  namedWindow("Edge map", 1);
  createTrackbar("threshold", "Edge map", &edgeThresh, 20, onTrackbar);
  onTrackbar(0, 0);

  cv::imshow("original", original);
  waitKey(0);

  return 0;
  }

/*
Mat image0, image, gray, mask;
int ffillMode = 1;
int loDiff = 20, upDiff = 20;
int connectivity = 4;
int isColor = true;
bool useMask = false;
int newMaskVal = 255;

static void onMouse( int event, int x, int y, int, void* )
{
    if( event != EVENT_LBUTTONDOWN )
        return;

    Point seed = Point(x,y);
    int lo = ffillMode == 0 ? 0 : loDiff;
    int up = ffillMode == 0 ? 0 : upDiff;
    int flags = connectivity + (newMaskVal << 8) +
                (ffillMode == 1 ? FLOODFILL_FIXED_RANGE : 0);
    int b = (unsigned)theRNG() & 255;
    int g = (unsigned)theRNG() & 255;
    int r = (unsigned)theRNG() & 255;
    Rect ccomp;

    Scalar newVal = isColor ? Scalar(b, g, r) : Scalar(r*0.299 + g*0.587 + b*0.114);
    Mat dst = isColor ? image : gray;
    int area;

    if( useMask )
    {
        threshold(mask, mask, 1, 128, THRESH_BINARY);
        area = floodFill(dst, mask, seed, newVal, &ccomp, Scalar(lo, lo, lo),
                  Scalar(up, up, up), flags);
        imshow( "mask", mask );
    }
    else
    {
        area = floodFill(dst, seed, newVal, &ccomp, Scalar(lo, lo, lo),
                  Scalar(up, up, up), flags);
    }

    imshow("image", dst);
    cout << area << " pixels were repainted\n";
}
*/<commit_msg>Reindent file<commit_after>#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>

using namespace cv;
using namespace std;

struct PointWithGradient {
    Point pos;
    int gradient;
};

class ComparePWG {
public:

    // Returns true if t1 has a higher gradient than t2
    bool operator()(PointWithGradient& t1, PointWithGradient& t2) {
        if (t1.gradient > t2.gradient) return true;
        return false;
    }
};

priority_queue<PointWithGradient, vector<PointWithGradient>, ComparePWG> pq, backupQueue;
Mat usedPixels;
Mat mask;
int edgeThresh = 1;
Mat original;

// define a trackbar callback
static void onTrackbar(int, void*)
{
    Mat im = original.clone();
    Mat up = usedPixels.clone();

    mask = Scalar::all(0);
    int i=0;
    while (!pq.empty()) {

        PointWithGradient t2 = pq.top();

        if(mask.at<uchar>(t2.pos.x-1, t2.pos.y-1) == 0) {
            i++;
            Vec3b c1 = im.at<Vec3b>(t2.pos);
            Scalar newVal = Scalar(c1[0], c1[1], c1[2]);
            int lo = edgeThresh/2;
            int up = edgeThresh/2;
            int flags = 4 + (255 << 8); // + FLOODFILL_MASK_ONLY;
            //Rect ccomp;

            floodFill(im, mask, t2.pos, newVal, 0, Scalar(lo, lo, lo), Scalar(up, up, up), flags);

        }

        /*
        // if the pixel at position t2 has not been used before
        if(up.at<uchar>(t2.pos) == 255) {

            // store the current pixel's color
            Vec3b c1 = im.at<Vec3b>(t2.pos);

            // create a region for the current pixel
             vector<Point> region;
             region.push_back(t2.pos);

            // mark pixel as used
            up.at<uchar>(t2.pos) = 0;

            // iterate over all 4-connected pixels
            for(int i=-1; i<=1; i+=2) {
             for(int j=-1; j<=1; j+=2) {

                 // Existiert der Punkt �berhaupt? Pixel am Rand haben ja nur 3 bzw. an den Ecken 2 4-connected Nachbarn
                 if(t2.pos.x + i >= 0 && t2.pos.x + i < im.cols && t2.pos.y + j >= 0 && t2.pos.y + j < im.rows) {
                     Point p = Point(t2.pos.x + i, t2.pos.y + j);
                     if(up.at<uchar>(p) == 255) {
                         // pixel not yet used
                         // color distance zwischen dem Punkt aus der Priority Queue (t2) und dem aktuellen Nachbarn (p) berechnen
                         Vec3b c2 = im.at<Vec3b>(p);
                         double colorDistance = sqrt((c1[0]-c2[0])*(c1[0]-c2[0]) + (c1[1]-c2[1])*(c1[1]-c2[1]) + (c1[2]-c2[2])*(c1[2]-c2[2]));
                         if(colorDistance < edgeThresh) {
                             region.push_back(p);
                             // TODO: diese 2 Zeilen entfernen
                             im.at<Vec3b>(p) = im.at<Vec3b>(t2.pos);
                             up.at<uchar>(p) = 0;
                         }
                     }
                 }
             }
            }

            // TODO: �ber region iterieren, Durchschnittsfarbe berechnen, und jeden Pixel mit dieser Farbe einf�rben!

        }*/

        backupQueue.push(t2);
        pq.pop();
    }

    cout << i << endl;

    pq.swap(backupQueue);
    cv::imshow("Edge map", im);
    cv::imshow("Mask", mask);
}

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

    Mat src, src_gray;
    Mat grad;
    int scale = 1;
    int delta = 0;
    int ddepth = CV_16S;

    int c;

    /// Load an image
    src = imread( "C:/Users/Timo/Desktop/test.jpg", 1 );
    original = src.clone();

    if( !src.data )
    { return -1; }

    GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );

    /// Convert it to gray
    cvtColor( src, src_gray, CV_RGB2GRAY );

    /// Generate grad_x and grad_y
    Mat grad_x, grad_y;
    Mat abs_grad_x, abs_grad_y;

    /// Gradient X
    Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );
    convertScaleAbs( grad_x, abs_grad_x );

    /// Gradient Y
    Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );
    convertScaleAbs( grad_y, abs_grad_y );

    /// Total Gradient (approximate)
    addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );

    usedPixels = grad.clone();

    mask.create(src.rows+2, src.cols+2, CV_8UC1);

    // �ber alle Pixel iterieren, um sie in die PriorityQueue einzusortieren
    for(int y=0;y<grad.rows;y++)
    {
        for(int x=0;x<grad.cols;x++)
        {
            // Gradient f�r jeden Pixel auslesen
            int gradient = grad.at<uchar>(Point(x,y));

            // usedPixels wird als wei�es Bild initialisiert, hier wird sp�ter gespeichert, welche Pixel beim Auslesen der Priority Queue schon verwendet wurden
            usedPixels.at<uchar>(Point(x,y)) = 255;

            PointWithGradient pwg = PointWithGradient();
            pwg.gradient = gradient;
            pwg.pos = Point(x,y);

            // Store PWG in PriorityQueue
            pq.push(pwg);

        }
    }

    // create a toolbar

    namedWindow("Edge map", 1);
    createTrackbar("threshold", "Edge map", &edgeThresh, 20, onTrackbar);
    onTrackbar(0, 0);

    cv::imshow("original", original);
    waitKey(0);

    return 0;
}

/*
Mat image0, image, gray, mask;
int ffillMode = 1;
int loDiff = 20, upDiff = 20;
int connectivity = 4;
int isColor = true;
bool useMask = false;
int newMaskVal = 255;

static void onMouse( int event, int x, int y, int, void* )
{
    if( event != EVENT_LBUTTONDOWN )
        return;

    Point seed = Point(x,y);
    int lo = ffillMode == 0 ? 0 : loDiff;
    int up = ffillMode == 0 ? 0 : upDiff;
    int flags = connectivity + (newMaskVal << 8) +
                (ffillMode == 1 ? FLOODFILL_FIXED_RANGE : 0);
    int b = (unsigned)theRNG() & 255;
    int g = (unsigned)theRNG() & 255;
    int r = (unsigned)theRNG() & 255;
    Rect ccomp;

    Scalar newVal = isColor ? Scalar(b, g, r) : Scalar(r*0.299 + g*0.587 + b*0.114);
    Mat dst = isColor ? image : gray;
    int area;

    if( useMask )
    {
        threshold(mask, mask, 1, 128, THRESH_BINARY);
        area = floodFill(dst, mask, seed, newVal, &ccomp, Scalar(lo, lo, lo),
                  Scalar(up, up, up), flags);
        imshow( "mask", mask );
    }
    else
    {
        area = floodFill(dst, seed, newVal, &ccomp, Scalar(lo, lo, lo),
                  Scalar(up, up, up), flags);
    }

    imshow("image", dst);
    cout << area << " pixels were repainted\n";
}
*/<|endoftext|>


<commit_before>
/** \file main.cpp
 *
 * \brief Contains main.cpp function, and possibly some small amount
 * of other code, relating to Phatbooks application.
 *
 * \author Matthew Harvey
 * \date 04 July 2012.
 *
 * Copyright (c) 2012, Matthew Harvey. All rights reserved.
 */

#include "phatbooks_text_session.hpp"
#include <iostream>
#include <string>

using phatbooks::PhatbooksTextSession;
using std::cout;
using std::endl;

int main(int argc, char** argv)
{
	if (argc != 2)
	{
		cout << "Usage: " << argv[0] << " FILENAME" << endl;
		return 1;
	}

	// The following assumes a text based session.
	PhatbooksTextSession session;
	int const ret = session.run(argv[1]);
	return ret;
}
<commit_msg>Empty filename string now caught in main.<commit_after>
/** \file main.cpp
 *
 * \brief Contains main.cpp function, and possibly some small amount
 * of other code, relating to Phatbooks application.
 *
 * \author Matthew Harvey
 * \date 04 July 2012.
 *
 * Copyright (c) 2012, Matthew Harvey. All rights reserved.
 */

#include "phatbooks_text_session.hpp"
#include <iostream>
#include <string>

using phatbooks::PhatbooksTextSession;
using std::cout;
using std::endl;
using std::string;

int main(int argc, char** argv)
{
	if (argc != 2)
	{
		cout << "Usage: " << argv[0] << " FILENAME" << endl;
		return 1;
	}
	string filename(argv[1]);
	if (filename.empty())
	{
		cout << "FILENAME cannot be empty string." << endl;
		return 1;
	}

	// The following assumes a text based session.
	assert (argc == 2 && !filename.empty());
	PhatbooksTextSession session;
	int const ret = session.run(filename);
	return ret;
}
<|endoftext|>


<commit_before>
#include "simpleNW.hpp"
#include <memory>

class Echoing_Handler : public Handler {

	void OnConnectionOpen(std::shared_ptr<Connection> connection) override {
		//std::cout << "Connection openened: " << connection.get() << std::endl;
	}
	void OnConnectionClose(std::shared_ptr<Connection> connection) override {
		//std::cout << "Connection closed: " << connection.get() << std::endl;
	}
	void OnReceive(std::shared_ptr<Connection> connection, char data[], size_t bytes_received) override {
		connection->send_nonblocking(data, bytes_received);

	}
	void OnSend(std::shared_ptr<Connection> connection, char data[], size_t data_size, size_t bytes_sent) override {

	}

};

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

	{
		ServiceOptions options;
		options.server_port_ = 5000;
		options.threads_ = 8;
		options.transport_protocol_ = IPV4::TCP();

		NetworkService ok(options);

		Echoing_Handler hand;

		ok.addHandler(&hand);

		ok.start();

		while (true) {
			std::this_thread::yield();
		}

		std::cin.get();

	}

	std::cin.get();
}
<commit_msg>Fixed small compilation error.<commit_after>
#include "simpleNW.hpp"
#include <iostream>
#include <memory>

class Echoing_Handler : public Handler {

	void OnConnectionOpen(std::shared_ptr<Connection> connection) override {
		//std::cout << "Connection openened: " << connection.get() << std::endl;
	}
	void OnConnectionClose(std::shared_ptr<Connection> connection) override {
		//std::cout << "Connection closed: " << connection.get() << std::endl;
	}
	void OnReceive(std::shared_ptr<Connection> connection, char data[], size_t bytes_received) override {
		connection->send_nonblocking(data, bytes_received);

	}
	void OnSend(std::shared_ptr<Connection> connection, char data[], size_t data_size, size_t bytes_sent) override {

	}

};

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

	{
		ServiceOptions options;
		options.server_port_ = 5000;
		options.threads_ = 8;
		options.transport_protocol_ = IPV4::TCP();

		NetworkService ok(options);

		Echoing_Handler hand;

		ok.addHandler(&hand);

		ok.start();

		while (true) {
			std::this_thread::yield();
		}

		std::cin.get();

	}

	std::cin.get();
}
<|endoftext|>


<commit_before>/******************************************************************************

******************************************************************************/

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <errno.h>
#include <wiringPiSPI.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>

using namespace std;

bool debug_flag = false;

// SPI Speed as per the datasheet of the accelerometer : 1,2 MHz
#define SPI_SPEED 1200000

// Minimum square value for triggering an output
#define MIN_TRIGGER 1 // in G

// Coefficient for 10bit ADC --> G
#define G_COEF (3300/1024)/800
#define G_COEF_2 G_COEF*G_COEF

// Offsets are calculated here for faaaaastness (heuristics)
#define X_OFFSET -512 + 25
#define Y_OFFSET -512 + 64
#define Z_OFFSET -512 - 248 + 3 // Account for gravity (1G = 800mV at 1.5 precision)  // 800mV/(3,3V/1023)

// Time
#define ONE_OVER_CPS (1000000/CLOCKS_PER_SEC)

// Sampling rate for the ADC
unsigned int sampling_rate_in_us = 1000000; // 1 second

// We declare globals for faster reads
unsigned int channel_select;
unsigned char buffer[2];

// channel = 0, 1, 2
unsigned int readADC(int channel) {

   if (channel == 0) {
      buffer[0] = 0x60;
      buffer[1] = 0x00;
      channel_select = 0;
   } else if (channel == 1) {
      buffer[0] = 0x70;
      buffer[1] = 0x00;
      channel_select = 0;
   } else {
      buffer[0] = 0x60;
      buffer[1] = 0x00;
      channel_select = 1;
   }

   // We write two bits
   /*
      Note that the SPI protocol "returns" the same number of bits as sent,
      and in this case the 10-bit ADC data is encoded in the last two bits
      of the first byte and the eight bits of the second byte. I chose to
      retrieve the data in MSB-first order, so the result is the sum of
      (the bottom two bits of the first byte shifted up by eight bits) + the second byte.
   */
   wiringPiSPIDataRW(channel_select, buffer, 2);

   // Used just for testing :
   // unsigned int msb = buffer[1] + ((buffer[0] & 0x03) << 8);
   // unsigned int lsb = buffer[0] + ((buffer[1] & 0x03) << 8);

   return buffer[1] + ((buffer[0] & 0x03) << 8);
}

int main(int argc, char *argv[])
{
   // File descriptors for SPI
   int fd_mpc3002_1, fd_mpc3002_2;

   // Data values
   int x, y, z;
   double xg, yg, zg;

   // Running an average on the whole sim
   long x_avg, y_avg, z_avg, count_avg;
   x_avg = 0; y_avg = 0; z_avg = 0; count_avg = 0;

   // For clocking and precision
   clock_t tic, toc;
   unsigned int elapsed_time_in_us;

   if (argc == 1) {
      printf("Caribe Wave Sensor Pusher — pushes sensor data to stdout for next stage.\n");
      printf("Usage :\n");
      printf("  ./main [sampling rate] [debug]\n");
      printf("\n");
      printf("Arguments :\n");
      printf("  - debug: 1 or 0.\n");
      printf("  - sampling rate: in milliseconds, between 0 and 1000.\n");
      printf("\n");
      exit(0);
   } else if (argc == 2) {
      sampling_rate_in_us = max(0, min(1000, atoi(argv[1]))) * 1000;
   } else if (argc == 3) {
      sampling_rate_in_us = max(0, min(1000, atoi(argv[1]))) * 1000;
      debug_flag = argv[2][0] == '1' ? true : false;
      if (debug_flag) printf("Debug flag is TRUE.\n");
   } else {
      if (debug_flag) printf("Too many arguments supplied. Default sampling rate used.\n");
   }

   if (debug_flag) printf("Starting up.\n");
   if (debug_flag) printf("Sampling rate will be %d µs.\n", sampling_rate_in_us);
   if (debug_flag) printf("Initializing sensor pusher ...\n");

   // Configure the interface.
   fd_mpc3002_1 = wiringPiSPISetup(0, SPI_SPEED);
   fd_mpc3002_2 = wiringPiSPISetup(1, SPI_SPEED);

   if (debug_flag) printf("SPI setup : OK.\n");

   if (debug_flag) printf("Initing first MPC3002  : %d.\n", fd_mpc3002_1);
   if (debug_flag) printf("Initing second MPC3002 : %d.\n", fd_mpc3002_2);

   if (debug_flag) printf("\n");

   do {

      tic = clock();

      x = 0; y = 0; z = 0;
      for (int i = 0; i < 10; ++i)
      {
         x += readADC(0);
         y += readADC(1);
         z += readADC(2);
         usleep(10);
      }

      // Average on 1ms approx.
      x = x/10;
      y = y/10;
      z = z/10;

      // Offset for X/Y (due to MMA7260Q analogic)
      x += X_OFFSET;
      y += Y_OFFSET;
      z += Z_OFFSET;

      xg = (double) x*G_COEF;
      yg = (double) y*G_COEF;
      zg = (double) z*G_COEF;

      // 1G on at least one axis triggers the output
      if (G_COEF_2*(x*x + y*y + z*z) > MIN_TRIGGER || debug_flag) {
         // Format : X_10bit X_G Y_10bit Y_G Z_1Obit Z_G
         printf("%d %f %d %f %d %f\n", x, xg, y, yg, z, zg);

         if (debug_flag) {
            x_avg += x; y_avg += y; z_avg += z;
            count_avg++;
            printf(" [Average since launch %d %d %d]\n", x_avg/count_avg, y_avg/count_avg, z_avg/count_avg);
         }
      }

      toc = clock();
      elapsed_time_in_us = (toc - tic) * ONE_OVER_CPS; // in microsecs
      if (debug_flag) printf(" [Sampling took %d us]\n", elapsed_time_in_us);

      usleep(sampling_rate_in_us - max(0, static_cast<int>(min(elapsed_time_in_us, sampling_rate_in_us))));

   } while(true);

   if (debug_flag) printf("Exiting");

}
<commit_msg>Add type of accel Fixups<commit_after>/******************************************************************************

******************************************************************************/

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <errno.h>
#include <wiringPiSPI.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>

using namespace std;

bool debug_flag = false;

// SPI Speed as per the datasheet of the accelerometer : 1,2 MHz
#define SPI_SPEED 1200000

// Minimum square value for triggering an output
#define MIN_TRIGGER 1 // in G

// Coefficient for 10bit ADC --> G
#define G_COEF (3300/1024)/800
#define G_COEF_2 G_COEF*G_COEF

// Offsets are calculated here for faaaaastness (heuristics)
#define X_OFFSET -512 + 25
#define Y_OFFSET -512 + 64
#define Z_OFFSET -512 - 248 + 3 // Account for gravity (1G = 800mV at 1.5 precision)  // 800mV/(3,3V/1023)

// Time
#define ONE_OVER_CPS (1000000/CLOCKS_PER_SEC)

// Sampling rate for the ADC
unsigned int sampling_rate_in_us = 1000000; // 1 second
// Type of accelerometer
unsigned char type[10];

// We declare globals for faster reads
unsigned int channel_select;
unsigned char buffer[2];

// channel = 0, 1, 2
unsigned int readADC(int channel) {

   if (channel == 0) {
      buffer[0] = 0x60;
      buffer[1] = 0x00;
      channel_select = 0;
   } else if (channel == 1) {
      buffer[0] = 0x70;
      buffer[1] = 0x00;
      channel_select = 0;
   } else {
      buffer[0] = 0x60;
      buffer[1] = 0x00;
      channel_select = 1;
   }

   // We write two bits
   /*
      Note that the SPI protocol "returns" the same number of bits as sent,
      and in this case the 10-bit ADC data is encoded in the last two bits
      of the first byte and the eight bits of the second byte. I chose to
      retrieve the data in MSB-first order, so the result is the sum of
      (the bottom two bits of the first byte shifted up by eight bits) + the second byte.
   */
   wiringPiSPIDataRW(channel_select, buffer, 2);

   // Used just for testing :
   // unsigned int msb = buffer[1] + ((buffer[0] & 0x03) << 8);
   // unsigned int lsb = buffer[0] + ((buffer[1] & 0x03) << 8);

   return buffer[1] + ((buffer[0] & 0x03) << 8);
}

int main(int argc, char *argv[])
{
   // File descriptors for SPI
   int fd_mpc3002_1, fd_mpc3002_2;

   // Data values
   int x, y, z;
   double xg, yg, zg;

   // Running an average on the whole sim
   long x_avg, y_avg, z_avg, count_avg;
   x_avg = 0; y_avg = 0; z_avg = 0; count_avg = 0;

   // For clocking and precision
   clock_t tic, toc;
   unsigned int elapsed_time_in_us;

   if (argc == 1) {
      printf("Caribe Wave Sensor Pusher — pushes sensor data to stdout for next stage.\n");
      printf("Usage :\n");
      printf("  ./main [sampling rate] [debug]\n");
      printf("\n");
      printf("Arguments :\n");
      printf("  - type: type of accelerometer : ADXL, LIS or MMA (string).\n");
      printf("  - sampling rate: in milliseconds, between 0 and 1000.\n");
      printf("  - debug: 1 or 0.\n");
      printf("\n");
      exit(0);
   } else if (argc == 2) {
      type = argv[1];
   } else if (argc == 3) {
      type = argv[1];
      sampling_rate_in_us = max(0, min(1000, atoi(argv[2]))) * 1000;
   } else if (argc == 4) {
      type = argv[1];
      sampling_rate_in_us = max(0, min(1000, atoi(argv[2]))) * 1000;
      debug_flag = argv[3][0] == '1' ? true : false;
      if (debug_flag) printf("Debug flag is TRUE.\n");
   } else {
      if (debug_flag) printf("Too many arguments supplied. Default sampling rate used.\n");
   }

   if (debug_flag) printf("Starting up.\n");
   if (debug_flag) printf("Sampling rate will be %d µs.\n", sampling_rate_in_us);
   if (debug_flag) printf("Accel. type is : %s.\n", type);
   if (debug_flag) printf("Initializing sensor pusher ...\n");

   // Configure the interface.
   fd_mpc3002_1 = wiringPiSPISetup(0, SPI_SPEED);
   fd_mpc3002_2 = wiringPiSPISetup(1, SPI_SPEED);

   if (debug_flag) printf("SPI setup : OK.\n");

   if (debug_flag) printf("Initing first MPC3002  : %d.\n", fd_mpc3002_1);
   if (debug_flag) printf("Initing second MPC3002 : %d.\n", fd_mpc3002_2);

   if (debug_flag) printf("\n");

   do {

      tic = clock();

      x = 0; y = 0; z = 0;
      for (int i = 0; i < 10; ++i)
      {
         x += readADC(0);
         y += readADC(1);
         z += readADC(2);
      }

      // Average on 1ms approx.
      x = x/10;
      y = y/10;
      z = z/10;

      // Offset for X/Y (due to MMA7260Q analogic)
      x += X_OFFSET;
      y += Y_OFFSET;
      z += Z_OFFSET;

      xg = (double) x*G_COEF;
      yg = (double) y*G_COEF;
      zg = (double) z*G_COEF;

      // 1G on at least one axis triggers the output
      if (G_COEF_2*(x*x + y*y + z*z) > MIN_TRIGGER || debug_flag) {
         // Format : X_10bit X_G Y_10bit Y_G Z_1Obit Z_G
         printf("%d %f %d %f %d %f\n", x, xg, y, yg, z, zg);

         if (debug_flag) {
            x_avg += x; y_avg += y; z_avg += z;
            count_avg++;
            printf(" [Average since launch %ld %ld %ld]\n", x_avg/count_avg, y_avg/count_avg, z_avg/count_avg);
         }
      }

      toc = clock();
      elapsed_time_in_us = (toc - tic) * ONE_OVER_CPS; // in microsecs
      if (debug_flag) printf(" [Sampling took %d us]\n", elapsed_time_in_us);

      usleep(sampling_rate_in_us - max(0, static_cast<int>(min(elapsed_time_in_us, sampling_rate_in_us))));

   } while(true);

   if (debug_flag) printf("Exiting");

}
<|endoftext|>


<commit_before>#pragma warning(disable:4996)
#include "MainWindowProxy.h"
#include "common/RhodesApp.h"
#include "common/RhoConf.h"
#include "common/RhoFilePath.h"
#include "NativeToolbarQt.h"
#include "rho/rubyext/NativeToolbarExt.h"
#undef null
#include <QString>
#include <QApplication>
#include <QtGui/QAction>
#include "QtMainWindow.h"

IMPLEMENT_LOGCLASS(CMainWindowProxy,"MainWindowProxy");

extern "C" int rho_wmsys_has_touchscreen();

using namespace rho;
using namespace rho::common;

CMainWindowProxy::CMainWindowProxy(void):
    qtApplication(NULL),
    qtMainWindow(NULL)
{
}

CMainWindowProxy::~CMainWindowProxy(void)
{
    if (qtMainWindow) delete (QtMainWindow*)qtMainWindow;
    if (qtApplication) delete (QApplication*)qtApplication;
}

void CMainWindowProxy::navigate(const wchar_t* url)
{
    LOG(INFO) + "navigate: '"+url+"'";
    ((QtMainWindow*)qtMainWindow)->navigate(QString::fromWCharArray(url));
}

void CMainWindowProxy::setCallback(IMainWindowCallback* callback)
{
    ((QtMainWindow*)qtMainWindow)->setCallback(callback);
}

void* CMainWindowProxy::init(IMainWindowCallback* callback, const wchar_t* title)
{
    int argc = 0;
    qtApplication = (void*)new QApplication(argc, 0);
    qtMainWindow = (void*)new QtMainWindow();
    ((QtMainWindow*)qtMainWindow)->setWindowTitle(QString::fromWCharArray(title));
    ((QtMainWindow*)qtMainWindow)->setCallback(callback);
    ((QtMainWindow*)qtMainWindow)->show();

    return (void*)((QtMainWindow*)qtMainWindow)->winId();
}

void CMainWindowProxy::messageLoop(void)
{
    qApp->exec();
}

void CMainWindowProxy::GoBack(void)
{
    LOG(INFO) + "back";
    ((QtMainWindow*)qtMainWindow)->GoBack();
}

void CMainWindowProxy::GoForward(void)
{
    LOG(INFO) + "forward";
    ((QtMainWindow*)qtMainWindow)->GoForward();
}

void CMainWindowProxy::Refresh(void)
{
    LOG(INFO) + "refresh";
    ((QtMainWindow*)qtMainWindow)->Refresh();
}

bool CMainWindowProxy::isStarted()
{
    return true;
}

int CMainWindowProxy::getHeight()
{
    return ((QtMainWindow*)qtMainWindow)->toolbarGetHeight();
}

void CMainWindowProxy::removeToolbar()
{
    ((QtMainWindow*)qtMainWindow)->toolbarHide();
}

void CMainWindowProxy::removeAllButtons()
{
    ((QtMainWindow*)qtMainWindow)->toolbarRemoveAllButtons();
}

static QColor getColorFromString(const char* szColor)
{
    if ( !szColor || !*szColor )
        return QColor(0, 0, 0);

    int c = atoi(szColor);

    int cR = (c & 0xFF0000) >> 16;
    int cG = (c & 0xFF00) >> 8;
    int cB = (c & 0xFF);

    return QColor(cR, cG, cB);
}

void CMainWindowProxy::createToolbar(rho_param *p)
{
    if (!rho_rhodesapp_check_mode() || !rho_wmsys_has_touchscreen() )
        return;

    int bar_type = TOOLBAR_TYPE;
	std::auto_ptr<QColor> m_rgbBackColor (NULL);
    std::auto_ptr<QColor> m_rgbMaskColor (NULL);
    int m_nHeight = CNativeToolbar::MIN_TOOLBAR_HEIGHT;

    rho_param *params = NULL;
    switch (p->type)
    {
        case RHO_PARAM_ARRAY:
            params = p;
            break;
        case RHO_PARAM_HASH:
            {
                for (int i = 0, lim = p->v.hash->size; i < lim; ++i)
                {
                    const char *name = p->v.hash->name[i];
                    rho_param *value = p->v.hash->value[i];

                    if (strcasecmp(name, "background_color") == 0)
                        m_rgbBackColor.reset(new QColor(getColorFromString(value->v.string)));
                    else if (strcasecmp(name, "mask_color") == 0)
                        m_rgbMaskColor.reset(new QColor(getColorFromString(value->v.string)));
                    else if (strcasecmp(name, "view_height") == 0)
                        m_nHeight = atoi(value->v.string);
                    else if (strcasecmp(name, "buttons") == 0 || strcasecmp(name, "tabs") == 0)
                        params = value;
                }
            }
            break;
        default: {
            LOG(ERROR) + "Unexpected parameter type for create_nativebar, should be Array or Hash";
            return;
        }
    }

    if (!params) {
        LOG(ERROR) + "Wrong parameters for create_nativebar";
        return;
    }

    int size = params->v.array->size;
    if ( size == 0 )
    {
        removeToolbar();
        return;
    }

    removeAllButtons();

    int nSeparators = 0;
    bool wasSeparator = false;
    for (int ipass=0; ipass < 2; ++ipass) {
        for (int i = 0; i < size; ++i)
        {
            rho_param *hash = params->v.array->value[i];
            if (hash->type != RHO_PARAM_HASH) {
                LOG(ERROR) + "Unexpected type of array item for create_nativebar, should be Hash";
                return;
            }

            const char *label = NULL;
            const char *action = NULL;
            const char *icon = NULL;
            const char *colored_icon = NULL;
            int  nItemWidth = 0;

            for (int j = 0, lim = hash->v.hash->size; j < lim; ++j)
            {
                const char *name = hash->v.hash->name[j];
                rho_param *value = hash->v.hash->value[j];
                if (value->type != RHO_PARAM_STRING) {
                    LOG(ERROR) + "Unexpected '" + name + "' type, should be String";
                    return;
                }

                if (strcasecmp(name, "label") == 0)
                    label = value->v.string;
                else if (strcasecmp(name, "action") == 0)
                    action = value->v.string;
                else if (strcasecmp(name, "icon") == 0)
                    icon = value->v.string;
                else if (strcasecmp(name, "colored_icon") == 0)
                    colored_icon = value->v.string;
                else if (strcasecmp(name, "width") == 0)
                    nItemWidth = atoi(value->v.string);
            }

            if (label == NULL && bar_type == TOOLBAR_TYPE)
                label = "";

            if ( label == NULL || action == NULL) {
                LOG(ERROR) + "Illegal argument for create_nativebar";
                return;
            }
            if ( strcasecmp(action, "forward") == 0 && rho_conf_getBool("jqtouch_mode") )
                continue;

            if (!action) action = "";

            if (ipass==0) {
                if (strcasecmp(action, "separator")==0)
                    ++nSeparators;
            } else {
                LOG(INFO) + "addToolbarButton: Label: '"+label+"';Action: '"+action+"'";
                if (strcasecmp(action, "separator")==0) {
                    if (nSeparators!=1)
                        ((QtMainWindow*)qtMainWindow)->toolbarAddSeparator();
                    else
                        wasSeparator = true;
                } else {
                    String strImagePath;
                    if ( icon && *icon )
                        strImagePath = rho::common::CFilePath::join( RHODESAPP().getRhoRootPath(), icon );
                    else {
                        if ( strcasecmp(action, "options")==0 )
                            strImagePath = "res/options_btn.wm.png";
                        else if ( strcasecmp(action, "home")==0 )
                            strImagePath = "res/home_btn.wm.png";
                        else if ( strcasecmp(action, "refresh")==0 )
                            strImagePath = "res/refresh_btn.wm.png";
                        else if ( strcasecmp(action, "back")==0 )
                            strImagePath = "res/back_btn.wm.png";
                        else if ( strcasecmp(action, "forward")==0 )
                            strImagePath = "res/forward_btn.wm.png";
                        strImagePath = strImagePath.length() > 0 ? CFilePath::join( RHODESAPP().getRhodesPath(), "lib/framework/" + strImagePath) : String();
                    }

                    ((QtMainWindow*)qtMainWindow)->toolbarAddAction(QIcon(QString(strImagePath.c_str())), QString(label), action, wasSeparator);
                }
            }
        }
    }
	((QtMainWindow*)qtMainWindow)->setToolbarStyle(false, (m_rgbBackColor.get()!=NULL ? m_rgbBackColor->name() : ""));
    ((QtMainWindow*)qtMainWindow)->toolbarShow();
}

void CMainWindowProxy::menuClear()
{
    ((QtMainWindow*)qtMainWindow)->menuClear();
}

void CMainWindowProxy::menuAddSeparator()
{
    ((QtMainWindow*)qtMainWindow)->menuAddSeparator();
}

void CMainWindowProxy::menuAddAction(const char* label, int item)
{
    ((QtMainWindow*)qtMainWindow)->menuAddAction(QString(label), item);
}
<commit_msg>RhoSimulator: fixed Qt settings persistence (particularly saves the state of WebInpsector now)<commit_after>#pragma warning(disable:4996)
#include "MainWindowProxy.h"
#include "common/RhodesApp.h"
#include "common/RhoConf.h"
#include "common/RhoFilePath.h"
#include "NativeToolbarQt.h"
#include "rho/rubyext/NativeToolbarExt.h"
#undef null
#include <QString>
#include <QApplication>
#include <QtGui/QAction>
#include "QtMainWindow.h"

IMPLEMENT_LOGCLASS(CMainWindowProxy,"MainWindowProxy");

extern "C" int rho_wmsys_has_touchscreen();

using namespace rho;
using namespace rho::common;

CMainWindowProxy::CMainWindowProxy(void):
    qtApplication(NULL),
    qtMainWindow(NULL)
{
}

CMainWindowProxy::~CMainWindowProxy(void)
{
    if (qtMainWindow) delete (QtMainWindow*)qtMainWindow;
    if (qtApplication) delete (QApplication*)qtApplication;
}

void CMainWindowProxy::navigate(const wchar_t* url)
{
    LOG(INFO) + "navigate: '"+url+"'";
    ((QtMainWindow*)qtMainWindow)->navigate(QString::fromWCharArray(url));
}

void CMainWindowProxy::setCallback(IMainWindowCallback* callback)
{
    ((QtMainWindow*)qtMainWindow)->setCallback(callback);
}

void* CMainWindowProxy::init(IMainWindowCallback* callback, const wchar_t* title)
{
    int argc = 0;
	QCoreApplication::setOrganizationName("Rhomobile");
	QCoreApplication::setApplicationName("RhoSimulator");
    qtApplication = (void*)new QApplication(argc, 0);
    qtMainWindow = (void*)new QtMainWindow();
    ((QtMainWindow*)qtMainWindow)->setWindowTitle(QString::fromWCharArray(title));
    ((QtMainWindow*)qtMainWindow)->setCallback(callback);
    ((QtMainWindow*)qtMainWindow)->show();

    return (void*)((QtMainWindow*)qtMainWindow)->winId();
}

void CMainWindowProxy::messageLoop(void)
{
    qApp->exec();
}

void CMainWindowProxy::GoBack(void)
{
    LOG(INFO) + "back";
    ((QtMainWindow*)qtMainWindow)->GoBack();
}

void CMainWindowProxy::GoForward(void)
{
    LOG(INFO) + "forward";
    ((QtMainWindow*)qtMainWindow)->GoForward();
}

void CMainWindowProxy::Refresh(void)
{
    LOG(INFO) + "refresh";
    ((QtMainWindow*)qtMainWindow)->Refresh();
}

bool CMainWindowProxy::isStarted()
{
    return true;
}

int CMainWindowProxy::getHeight()
{
    return ((QtMainWindow*)qtMainWindow)->toolbarGetHeight();
}

void CMainWindowProxy::removeToolbar()
{
    ((QtMainWindow*)qtMainWindow)->toolbarHide();
}

void CMainWindowProxy::removeAllButtons()
{
    ((QtMainWindow*)qtMainWindow)->toolbarRemoveAllButtons();
}

static QColor getColorFromString(const char* szColor)
{
    if ( !szColor || !*szColor )
        return QColor(0, 0, 0);

    int c = atoi(szColor);

    int cR = (c & 0xFF0000) >> 16;
    int cG = (c & 0xFF00) >> 8;
    int cB = (c & 0xFF);

    return QColor(cR, cG, cB);
}

void CMainWindowProxy::createToolbar(rho_param *p)
{
    if (!rho_rhodesapp_check_mode() || !rho_wmsys_has_touchscreen() )
        return;

    int bar_type = TOOLBAR_TYPE;
	std::auto_ptr<QColor> m_rgbBackColor (NULL);
    std::auto_ptr<QColor> m_rgbMaskColor (NULL);
    int m_nHeight = CNativeToolbar::MIN_TOOLBAR_HEIGHT;

    rho_param *params = NULL;
    switch (p->type)
    {
        case RHO_PARAM_ARRAY:
            params = p;
            break;
        case RHO_PARAM_HASH:
            {
                for (int i = 0, lim = p->v.hash->size; i < lim; ++i)
                {
                    const char *name = p->v.hash->name[i];
                    rho_param *value = p->v.hash->value[i];

                    if (strcasecmp(name, "background_color") == 0)
                        m_rgbBackColor.reset(new QColor(getColorFromString(value->v.string)));
                    else if (strcasecmp(name, "mask_color") == 0)
                        m_rgbMaskColor.reset(new QColor(getColorFromString(value->v.string)));
                    else if (strcasecmp(name, "view_height") == 0)
                        m_nHeight = atoi(value->v.string);
                    else if (strcasecmp(name, "buttons") == 0 || strcasecmp(name, "tabs") == 0)
                        params = value;
                }
            }
            break;
        default: {
            LOG(ERROR) + "Unexpected parameter type for create_nativebar, should be Array or Hash";
            return;
        }
    }

    if (!params) {
        LOG(ERROR) + "Wrong parameters for create_nativebar";
        return;
    }

    int size = params->v.array->size;
    if ( size == 0 )
    {
        removeToolbar();
        return;
    }

    removeAllButtons();

    int nSeparators = 0;
    bool wasSeparator = false;
    for (int ipass=0; ipass < 2; ++ipass) {
        for (int i = 0; i < size; ++i)
        {
            rho_param *hash = params->v.array->value[i];
            if (hash->type != RHO_PARAM_HASH) {
                LOG(ERROR) + "Unexpected type of array item for create_nativebar, should be Hash";
                return;
            }

            const char *label = NULL;
            const char *action = NULL;
            const char *icon = NULL;
            const char *colored_icon = NULL;
            int  nItemWidth = 0;

            for (int j = 0, lim = hash->v.hash->size; j < lim; ++j)
            {
                const char *name = hash->v.hash->name[j];
                rho_param *value = hash->v.hash->value[j];
                if (value->type != RHO_PARAM_STRING) {
                    LOG(ERROR) + "Unexpected '" + name + "' type, should be String";
                    return;
                }

                if (strcasecmp(name, "label") == 0)
                    label = value->v.string;
                else if (strcasecmp(name, "action") == 0)
                    action = value->v.string;
                else if (strcasecmp(name, "icon") == 0)
                    icon = value->v.string;
                else if (strcasecmp(name, "colored_icon") == 0)
                    colored_icon = value->v.string;
                else if (strcasecmp(name, "width") == 0)
                    nItemWidth = atoi(value->v.string);
            }

            if (label == NULL && bar_type == TOOLBAR_TYPE)
                label = "";

            if ( label == NULL || action == NULL) {
                LOG(ERROR) + "Illegal argument for create_nativebar";
                return;
            }
            if ( strcasecmp(action, "forward") == 0 && rho_conf_getBool("jqtouch_mode") )
                continue;

            if (!action) action = "";

            if (ipass==0) {
                if (strcasecmp(action, "separator")==0)
                    ++nSeparators;
            } else {
                LOG(INFO) + "addToolbarButton: Label: '"+label+"';Action: '"+action+"'";
                if (strcasecmp(action, "separator")==0) {
                    if (nSeparators!=1)
                        ((QtMainWindow*)qtMainWindow)->toolbarAddSeparator();
                    else
                        wasSeparator = true;
                } else {
                    String strImagePath;
                    if ( icon && *icon )
                        strImagePath = rho::common::CFilePath::join( RHODESAPP().getRhoRootPath(), icon );
                    else {
                        if ( strcasecmp(action, "options")==0 )
                            strImagePath = "res/options_btn.wm.png";
                        else if ( strcasecmp(action, "home")==0 )
                            strImagePath = "res/home_btn.wm.png";
                        else if ( strcasecmp(action, "refresh")==0 )
                            strImagePath = "res/refresh_btn.wm.png";
                        else if ( strcasecmp(action, "back")==0 )
                            strImagePath = "res/back_btn.wm.png";
                        else if ( strcasecmp(action, "forward")==0 )
                            strImagePath = "res/forward_btn.wm.png";
                        strImagePath = strImagePath.length() > 0 ? CFilePath::join( RHODESAPP().getRhodesPath(), "lib/framework/" + strImagePath) : String();
                    }

                    ((QtMainWindow*)qtMainWindow)->toolbarAddAction(QIcon(QString(strImagePath.c_str())), QString(label), action, wasSeparator);
                }
            }
        }
    }
	((QtMainWindow*)qtMainWindow)->setToolbarStyle(false, (m_rgbBackColor.get()!=NULL ? m_rgbBackColor->name() : ""));
    ((QtMainWindow*)qtMainWindow)->toolbarShow();
}

void CMainWindowProxy::menuClear()
{
    ((QtMainWindow*)qtMainWindow)->menuClear();
}

void CMainWindowProxy::menuAddSeparator()
{
    ((QtMainWindow*)qtMainWindow)->menuAddSeparator();
}

void CMainWindowProxy::menuAddAction(const char* label, int item)
{
    ((QtMainWindow*)qtMainWindow)->menuAddAction(QString(label), item);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <forward_list>
#include <unordered_map>
#include <stack>

using namespace std;

struct Eng {
    static vector<string> units;
    static vector<string> base;
    static unordered_map<string, string> replacements;

    static string O;
    static string OO;
    static string OOO;
};

string Eng::O     = "teen";
string Eng::OO    = "ty";
string Eng::OOO   = "hundred";

vector<string> Eng::units { "", "thousand", "million", "billion" };

// basic names of numbers
vector<string> Eng::base { "zero", "one", "two", "three", "four",
                      "five", "six", "seven", "eight", "nine" };

// also known as convention
unordered_map<string, string> Eng::replacements {
    // teens
    {"teen","ten"},
    {"oneteen","eleven"},
    {"twoteen", "twelve"},
    {"threeteen", "thirteen"},
    {"fiveteen", "fifteen"},

    // tens
    {"onety", "ten"},
    {"twoty", "twenty"},
    {"threety", "thirty"},
    {"fourty", "forty"},
    {"fivety", "fifty"},
    {"eightty", "eighty"}
};

class Number {
public:
    explicit Number(const int integer) {
        this->value = integer;
    }

    string translate() {

        if ( value == 0 )
            return "";

        if ( value <  100 ) {
            return dealWithTwoNumbers(value);
        }
        else if ( value < 1000 ) {
            return dealWithThreeNumbers(value);
        } else {
            return "unknown";
        }
    }

// utilities
private:
    string toBase(const int value) {
        return Eng::base.at(value);
    }

    string toTeen(const int value) {
        int lastDigit = value % 10;

        // don't spell zero
        string output = "";
        if ( lastDigit > 0 ) {
            output = toBase(lastDigit);
        }

        output += Eng::O;

        try { output = Eng::replacements.at(output); }
        catch (out_of_range) {}

        return output;
    }

    string toTens(int value) {
        int firstDigit, lastDigit;

        // first digit
        firstDigit = value / 10;
        string output = toBase(firstDigit) + Eng::OO;

        try { output = Eng::replacements.at(output); }
        catch (out_of_range) {}

        // last digit
        lastDigit = value % 10;
        string lastDigitSpell = "";
        if ( lastDigit > 0 ) {
           lastDigitSpell = toBase(lastDigit);
        }

        return output + ( lastDigitSpell == "" ? "" : "-" + lastDigitSpell );
    }

    string dealWithTwoNumbers(int num) {
        if ( num == 00 ) {
            return "";
        }
        else if ( num < 10 ) {
            return toBase(num);
        }
        else if ( num < 20 ) {
            return toTeen(num);
        }
        else if ( num < 100 ) {
            return toTens(num);
        }

        return "unknown";
    }

    string dealWithThreeNumbers(int num) {
        const int firstDigit = num / 100;
        string output = toBase(firstDigit) + " " + Eng::OOO;

        const int theLastTwo = num % 100;
        string output2 = dealWithTwoNumbers(theLastTwo);

        return output + ( output2.empty() ? "" : " and " + output2 );
    }

private:
    int value;

};

class Speller {
public:
    explicit Speller(const string input) {
        this->input = input;

        isAbleToWork = false;

        this->validate();
    }

    bool ready() {
        return isAbleToWork;
    }

    string process(){

        if (input == "0") return Eng::base.at(0);

        string textualForm;

        vector<string> triples = group();

        for (unsigned int i=0; i<triples.size(); ++i) {
            unitStack.push( Eng::units.at(i) );
        }

        for (unsigned int i=0; i<triples.size(); ++i ) {

            string triple = triples.at(i);

            Number number( toNumber(triple) );

            string translated = number.translate();

            if ( !translated.empty() ) {
                textualForm
                        .append( translated )
                        .append( unitStack.top().empty() ? "" : " " )
                        .append( unitStack.top() )
                        .append( ", " );
            }

            unitStack.pop();
        }

        // remove the last ', '
        int idx = textualForm.find_last_of(", ");
        textualForm.replace(idx-1, 2, "");

        return textualForm;
    }

private:

    void validate() {
        isAbleToWork = isValid() && input.length() < 13;
    }

    bool isValid(){
        for (auto it = input.cbegin(); it!=input.cend(); ++it) {
            char c = *it;
            switch (c) {
            case '0': case '1': case '2': case '3': case '4':
            case '5': case '6': case '7': case '8': case '9':
                break;
            default:
                return false;
            }
        }
        return true;
    }

    int toNumber(const string num) {
        if (isValid()) {
            try {
                return stoi(num);
            } catch (out_of_range) {
                return -1;
            }
        }
        return -1;
    }

    vector<string> group() {
        vector<string> triples;

        unsigned int overhead = input.size()%3;

        string prefix;
        for (auto i=input.cbegin(); i!=input.cbegin()+overhead; ++i) {
            prefix.push_back(*i);
        }

        if (!prefix.empty()) triples.push_back(prefix);

        for ( auto x=overhead; x<input.length(); x+=3 ) {
            string triple;
            triple.push_back(input.at(x));
            triple.push_back(input.at(x+1));
            triple.push_back(input.at(x+2));

            triples.push_back(triple);
        }

        return triples;
    }

private:
    string input;

    bool isAbleToWork;

    stack<string> unitStack;
};

// =========================================================================

void printUsage() {
    cout
            << "usage: NumberSpeller [N]" << endl
            << "N: positive number from 0 to maximum of 999999999999" << endl
            << "example: NumberSpeller 2300" << endl;
}

int main(int argc, char* argv[])
{
    // check args
    if ( argc == 2 ) {
        string input = argv[1];

        // bussiness
        Speller robot(input);
        if ( robot.ready() ) {
            string output = robot.process();
            cout << output << endl;
        } else {
            cout << "invalid input!" << endl;
            printUsage();
        }

    } else {
        printUsage();
    }

    return 0;
}

<commit_msg>made into loosely decoupled system of spelling. don't even try to find the diff with the previous version :P<commit_after>#include <iostream>
#include <vector>
#include <forward_list>
#include <unordered_map>
#include <stack>

using namespace std;

/**
 * @brief The Language class
 * Base of all supported language
 * In order to support certain language into the system, one has to
 * provide:
 * - the basic names for basic number from 0 to 9
 *   e.g zero, one, two, three..
 *
 * - list of unit number for each 3 digits.
 *   e.g thousand, million, billion, ..
 *   note: must be started from thousand-equivalent
 *
 * - replacements dictionary.
 *   each language has its own rule and there are always exceptions to
 *   that rule.
 *   for example: obeying the rule, one would spell 12 as 'twoteen'.
 *   using exception, 12 then becomes 'twelve'.
 *
 */
class Language {
public:
    Language(){}

    virtual vector<string> base() = 0;

    virtual vector<string> units() = 0;

    virtual unordered_map<string, string> replacements() = 0;
};

/**
 * @brief The Eng class
 * Example implementation of English language
 */
class Eng: public Language {
public:
    Eng() : Language()
    {}

    vector<string> base() {
        return _base;
    }

    vector<string> units() {
        return _units;
    }

    unordered_map<string, string> replacements() {
        return _replacements;
    }

    const string O     = "teen";
    const string OO    = "ty";
    const string OOO   = "hundred";

private:
    // basic names of numbers
    vector<string> _base { "zero", "one", "two", "three", "four",
                          "five", "six", "seven", "eight", "nine" };

    // units of numbers
    vector<string> _units { "", "thousand", "million", "billion" };

    // also known as convention
    unordered_map<string, string> _replacements {
        // teens
        {"teen","ten"},
        {"oneteen","eleven"},
        {"twoteen", "twelve"},
        {"threeteen", "thirteen"},
        {"fiveteen", "fifteen"},

        // tens
        {"onety", "ten"},
        {"twoty", "twenty"},
        {"threety", "thirty"},
        {"fourty", "forty"},
        {"fivety", "fifty"},
        {"eightty", "eighty"}
    };

};

/**
 * @brief The Number class
 *
 * Base of translatable Number class
 *
 * Given an integer ranged from 0 - 999, it should be able
 * to translate the integer into it textual form.
 *
 * This is virtual class, thus it has to be subclassed,
 * and subclass has to override translate() method
 * to support the language that the number will be translated into.
 *
 *
 */

class Number {
public:
    explicit Number() {
        this->value = 0;
    }

    explicit Number(const int integer) {
        this->value = integer;
    }

    virtual string translate() = 0;

    virtual Language* lang() = 0;

protected:
    int value;
};

/**
 * @brief The EngNumber class
 * A Number which translate its value into English word.
 */
class EngNumber : public Number {
public:

    explicit EngNumber() : Number()
    {}

    explicit EngNumber(const int integer) :
    Number(integer) {}

    string translate() {

        if ( value == 0 )
            return "zero";

        // up to this point 0 still spelled
        // past this point 0 is ignored

        if ( value <  100 ) {
            return dealWithTwoNumbers(value);
        }
        else if ( value < 1000 ) {
            return dealWithThreeNumbers(value);
        } else {
            return "unknown";
        }
    }

    Language* lang() {
        return &conf;
    }

    void setValue(const int value) {
        this->value = value;
    }

// utilities
private:
    Eng conf = Eng();

    string toBase(const int value) {
        return conf.base().at(value);
    }

    string toTeen(const int value) {
        int lastDigit = value % 10;

        // don't spell zero
        string output = "";
        if ( lastDigit > 0 ) {
            output = toBase(lastDigit);
        }

        output += conf.O;

        try { output = conf.replacements().at(output); }
        catch (out_of_range) {}

        return output;
    }

    string toTens(int value) {
        int firstDigit, lastDigit;

        // first digit
        firstDigit = value / 10;
        string output = toBase(firstDigit) + conf.OO;

        try { output = conf.replacements().at(output); }
        catch (out_of_range) {}

        // last digit
        lastDigit = value % 10;
        string lastDigitSpell = "";
        if ( lastDigit > 0 ) {
           lastDigitSpell = toBase(lastDigit);
        }

        return output + ( lastDigitSpell == "" ? "" : "-" + lastDigitSpell );
    }

    string dealWithTwoNumbers(int num) {
        if ( num == 00 ) {
            return "";
        }
        else if ( num < 10 ) {
            return toBase(num);
        }
        else if ( num < 20 ) {
            return toTeen(num);
        }
        else if ( num < 100 ) {
            return toTens(num);
        }

        return "unknown";
    }

    string dealWithThreeNumbers(int num) {
        const int firstDigit = num / 100;
        string output = toBase(firstDigit) + " " + conf.OOO;

        const int theLastTwo = num % 100;
        string output2 = dealWithTwoNumbers(theLastTwo);

        return output + ( output2.empty() ? "" : " and " + output2 );
    }

};

/**
 * @brief The Speller class
 *  It splits the number into triples,
 *  turn each triple into Number object from which the textual form of particular number
 *  could be retreived,
 *  then form a complete textual form for each triple with their corresponding units respectively.
 *
 *  usage:
 *  Create new instance of Speller with number to spell, as in:
 *  Speller speller("1123");
 *
 *  The instance will be able to process() only if the number is valid
 *  i.e only contains digit character nothing else.
 *  the ability can be queried using ready() method.
 */
class Speller {
public:
    explicit Speller(const string input) {
        this->input = input;

        isAbleToWork = false;

        this->validate();
    }

    /**
     * @brief ready
     * @return
     *  Ask me prior to doing process()
     * to make sure the work done on the right thing
     */
    bool ready() {
        return isAbleToWork;
    }

    /**
     * @brief process
     * @return
     *
     * order the Speller to do its hard work converting
     * numbers into their textual form of their language
     *
     * don't forget to ask ready() before calling this function,
     * for best result.
     *
     */
    string process(){

        if ( !ready() ) return "unable to proceed!";

        string textualForm;

        vector<string> triples = group();

        EngNumber number;

        for (unsigned int i=0; i<triples.size(); ++i) {

            unitStack.push( number.lang()->units().at(i) );

        }

        for (unsigned int i=0; i<triples.size(); ++i ) {

            string triple = triples.at(i);

            number.setValue( toNumber(triple) );

            Number* base = &number;
            string translated = base->translate();

            if ( !translated.empty() ) {
                textualForm
                        .append( translated )
                        .append( unitStack.top().empty() ? "" : " " )
                        .append( unitStack.top() )
                        .append( ", " );
            }

            unitStack.pop();
        }

        // remove the last ', '
        int idx = textualForm.find_last_of(", ");
        textualForm.replace(idx-1, 2, "");

        return textualForm;
    }

// utilities
private:
    /**
     * @brief validate
     * check the input and update ready() status
     */
    void validate() {
        isAbleToWork = isValid() && input.length() < 13;
    }

    /**
     * @brief isValid
     * @return
     *
     * return true if input contains exactly digit characters only
     * return false otherwise
     *
     */
    bool isValid(){
        for (auto it = input.cbegin(); it!=input.cend(); ++it) {
            char c = *it;
            switch (c) {
            case '0': case '1': case '2': case '3': case '4':
            case '5': case '6': case '7': case '8': case '9':
                break;
            default:
                return false;
            }
        }
        return true;
    }

    /**
     * @brief toNumber
     * @param num
     * @return
     *
     * convert num char to its integer equivalent
     */
    int toNumber(const string num) {
        if (isValid()) {
            try {
                return stoi(num);
            } catch (out_of_range) {
                return -1;
            }
        }
        return -1;
    }

    /**
     * @brief group
     * @return
     *
     * take 3 char, group them and add them into triples
     * triples: vector of triple
     */
    vector<string> group() {
        vector<string> triples;

        unsigned int overhead = input.size()%3;

        string prefix;
        for (auto i=input.cbegin(); i!=input.cbegin()+overhead; ++i) {
            prefix.push_back(*i);
        }

        if (!prefix.empty()) triples.push_back(prefix);

        for ( auto x=overhead; x<input.length(); x+=3 ) {
            string triple;
            triple.push_back(input.at(x));
            triple.push_back(input.at(x+1));
            triple.push_back(input.at(x+2));

            triples.push_back(triple);
        }

        return triples;
    }

private:
    /**
     * @brief input
     * string of digit char that will be translated
     */
    string input;

    /**
     * @brief isAbleToWork
     * mark of capability to translate
     */
    bool isAbleToWork;

    /**
     * @brief unitStack
     * collection of units of number in the language
     */
    stack<string> unitStack;
};

// =========================================================================

void printUsage() {
    cout
            << "usage: NumberSpeller [n]" << endl
            << "n: positive number from 0 to maximum of 999999999999" << endl
            << "example: NumberSpeller 2300" << endl;
}

int main(int argc, char* argv[])
{
    // check args
    if ( argc == 2 ) {
        string input = argv[1];

        // bussiness
        Speller robot(input);
        if ( robot.ready() ) {
            string output = robot.process();
            cout << output << endl;
        } else {
            cout << "invalid input!" << endl;
            printUsage();
        }

    } else {
        printUsage();
    }

    return 0;
}

<|endoftext|>


<commit_before>422ce3eb-2748-11e6-9437-e0f84713e7b8<commit_msg>OKAY this time it should work<commit_after>423c75d1-2748-11e6-b45b-e0f84713e7b8<|endoftext|>


<commit_before><commit_msg>fix OUString conversion<commit_after><|endoftext|>


<commit_before>/*
    This file is part of KAddressBook.

    Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>

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

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

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

#include "aboutdata.h"
#include <kcmdlineargs.h>
#include <klocale.h>
#include <kuniqueapplication.h>
#include <akonadi/control.h>

#include "mainwindow.h"

int main( int argc, char **argv )
{
  AboutData about;

  KCmdLineArgs::init( argc, argv, &about );

  KCmdLineOptions options;
  KCmdLineArgs::addCmdLineOptions( options );
  KUniqueApplication::addCmdLineOptions();

  if ( !KUniqueApplication::start() )
    exit( 0 );

  KUniqueApplication app;
  KGlobal::locale()->insertCatalog( "libkdepim" );
  KGlobal::locale()->insertCatalog( "kabc" );
  KGlobal::locale()->insertCatalog( "libakonadi" );
  KGlobal::locale()->insertCatalog( "kabcakonadi" );

  MainWindow *window = new MainWindow;
  window->show();

  Akonadi::Control::start( window );

  return app.exec();
}
<commit_msg>Abort application if Akonadi couldn't be started<commit_after>/*
    This file is part of KAddressBook.

    Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>

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

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

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

#include "aboutdata.h"
#include "mainwindow.h"

#include <akonadi/control.h>
#include <kcmdlineargs.h>
#include <kdebug.h>
#include <klocale.h>
#include <kuniqueapplication.h>

int main( int argc, char **argv )
{
  AboutData about;

  KCmdLineArgs::init( argc, argv, &about );

  KCmdLineOptions options;
  KCmdLineArgs::addCmdLineOptions( options );
  KUniqueApplication::addCmdLineOptions();

  if ( !KUniqueApplication::start() )
    exit( 0 );

  KUniqueApplication app;
  KGlobal::locale()->insertCatalog( "libkdepim" );
  KGlobal::locale()->insertCatalog( "kabc" );
  KGlobal::locale()->insertCatalog( "libakonadi" );
  KGlobal::locale()->insertCatalog( "kabcakonadi" );

  MainWindow *window = new MainWindow;
  window->show();

  if ( !Akonadi::Control::start( window ) ) {
    //TODO: add message box after string freeze
    kWarning() << "Unable to start Akonadi server, exit application";
    return 1;
  }

  return app.exec();
}
<|endoftext|>


<commit_before>#include <fstream>
#include <string>
#include <cassert>
#include <iostream>

#include <stdio.h>

extern "C" {
#include <pg_config.h>
#include <postgres.h>
#include <storage/bufpage.h>
#include <storage/itemid.h>
#include <access/htup.h>
}
#define PAGE_SIZE (8*1024)

namespace {

char hexadecimate(unsigned value) {
	switch( value ) {
	case 0: return '0';
	case 1: return '1';
	case 2: return '2';
	case 3: return '3';
	case 4: return '4';
	case 5: return '5';
	case 6: return '6';
	case 7: return '7';
	case 8: return '8';
	case 9: return '9';
	case 10: return 'A';
	case 11: return 'B';
	case 12: return 'C';
	case 13: return 'D';
	case 14: return 'E';
	case 15: return 'F';
	}
	assert(false);
	return '?';
}

inline unsigned integral_division(unsigned dividend, unsigned divisor) {
	unsigned result = dividend/divisor;
	assert( dividend - (divisor*result) == 0 );
	return result;
}

struct Varlena : public varlena {
	unsigned _size() {
		return *reinterpret_cast<unsigned*>(vl_len_);
	}
	unsigned size() {
		assert(false);//WIP
		return _size();
	}
};

struct ItemHeader;
struct ItemData {
	ItemHeader* header;
	char* data;
	unsigned data_size;

	std::string hexadecimate_all(unsigned pos=0,unsigned max=-1) {
		std::string result;
		unsigned end = data_size;
		if( end > max )
			end = max;

		for( unsigned int i = pos; i < end; ++i ) {
			if( isalnum(data[i]) ) {
				result += data[i];
			} else if( data[i] == '\n' ) {
				result += "\\n";
			} else if( data[i] == ' ') {
				result += " ";
			} else {
//				result += std::to_string( data[i] );
//				result += hexadecimate( ((unsigned char)(data[i]))>>4 );
//				result += hexadecimate( data[i]&0xF );
				result += "X";
			}
//			result += " ";
		}
		return result;
	}

	unsigned get_serial(unsigned pos) {
		return *reinterpret_cast<unsigned*>( data+pos );
	};
	unsigned get_serial_size() {
		return 4;
	}

	Varlena* get_varlena(unsigned pos) {
		return reinterpret_cast<Varlena*>( data+pos );
	}
	unsigned get_varlena_size(unsigned pos) {
		return get_varlena(pos)->size();
	}

};

struct ItemHeader : public HeapTupleHeaderData {
	unsigned number_attributes() {
		return unsigned(t_infomask2 & HEAP_NATTS_MASK);
	}

	bool has_bitmap() {
		return bool(t_infomask & HEAP_HASNULL);
	}

	bool has_attribute(unsigned pos) {
		return !bool(att_isnull(pos,t_bits));
	}
};

struct PageData {
	union {
		PageHeaderData header;
		ItemIdData itens[1];
	};

	unsigned itemid_count() {
		return integral_division( header.pd_lower-sizeof(PageHeaderData)+sizeof(ItemIdData), sizeof(ItemIdData) );
	};

	ItemHeader* get_item_header(const ItemIdData& itemid) {
		return reinterpret_cast<ItemHeader*>( reinterpret_cast<char*>(this)+itemid.lp_off );
	};

	ItemData get_item_data(const ItemIdData& itemid) {
		ItemHeader* header = get_item_header(itemid);
		char* data = reinterpret_cast<char*>(header) + header->t_hoff;
		unsigned data_size = itemid.lp_len - header->t_hoff;

		ItemData result = {header,data,data_size};
		return result;
	}
};

char read_page_buffer[PAGE_SIZE];
PageData* read_page(std::istream& stream, unsigned pos) {
	stream.seekg(pos*PAGE_SIZE,std::istream::beg);
	stream.read(read_page_buffer,PAGE_SIZE);
	return reinterpret_cast<PageData*>(&read_page_buffer);
}

}

void user_code(ItemIdData& itemid, ItemHeader& itemheader, ItemData& itemdata);

int main(int argc, char** argv) {
	assert( sizeof(PageData) == 24+sizeof(ItemIdData) );
	assert( sizeof(ItemIdData) == 4 );

	if( argc < 2 ) {
		std::cerr << "Usage " << argv[0] << " input_file" << std::endl;
		return 1;
	}

	std::ifstream input(argv[1]);
	assert( input.good() );

	input.seekg(0, std::ifstream::end);
	unsigned size = input.tellg();
	input.seekg(0, std::ifstream::beg);
	unsigned pages = size/PAGE_SIZE;
	if( size - (pages*PAGE_SIZE) != 0 ) {
		std::cerr << "Given file is not aligned to " << PAGE_SIZE << " bytes" << std::endl;
		return 1;
	}

	if( pages == 0 ) {
		std::cerr << "Given file has zero pages" << std::endl;
		return 1;
	};

	for( unsigned int which_page=0;which_page<pages;++which_page) {
		PageData& page = *read_page(input,which_page);
//		std::cout << "Page " << which_page << std::endl;
		for( unsigned int i = 0; i < page.itemid_count(); ++i ) {
			ItemIdData& itemid = page.itens[i];
			if( itemid.lp_flags != LP_NORMAL ) {
//				std::cerr << "\tIgnoring item because it is not marked as LP_NORMAL" << std::endl;
			} else if( itemid.lp_len == 0 ) {
//				std::cerr << "\tIgnoring item because it has no storage" << std::endl;
			} else if( itemid.lp_off > PAGE_SIZE ) {
//				std::cerr << "\tIgnoring item because it's offset is outside of page" << std::endl;
			} else if( itemid.lp_off + itemid.lp_len > PAGE_SIZE ) {
//				std::cerr << "\tIgnoring item because it spans outsize of the page" << std::endl;
			} else {
				ItemHeader& itemheader = *page.get_item_header(itemid);
				std::cout << "\tItem (" << itemid.lp_off << "," << itemid.lp_len << ")~" << itemid.lp_flags;
				std::cout << ", number of attributes is " << itemheader.number_attributes();
				std::cout << " " << (itemheader.has_bitmap() ? "with" : "without") << " bitmap";
				if( itemheader.has_bitmap() ) {
					std::cout << ":\t";
					for( unsigned int j=0; j < itemheader.number_attributes(); ++j) {
						std::cout << " " << itemheader.has_attribute(j);
					}
				}
				ItemData itemdata = page.get_item_data(itemid);
				std::cout << ", data size is " << itemdata.data_size << std::endl;

				user_code(itemid,itemheader,itemdata);
			}
		};
	}

	return 0;
};

void user_code(ItemIdData& itemid, ItemHeader& itemheader, ItemData& itemdata) {
	std::cout << itemdata.hexadecimate_all() << std::endl;

	return;
};
<commit_msg>Bug fix on page memory layout<commit_after>#include <fstream>
#include <string>
#include <cassert>
#include <iostream>

#include <stdio.h>

extern "C" {
#include <pg_config.h>
#include <postgres.h>
#include <storage/bufpage.h>
#include <storage/itemid.h>
#include <access/htup.h>
}
#define PAGE_SIZE (8*1024)

namespace {

char hexadecimate(unsigned value) {
	switch( value ) {
	case 0: return '0';
	case 1: return '1';
	case 2: return '2';
	case 3: return '3';
	case 4: return '4';
	case 5: return '5';
	case 6: return '6';
	case 7: return '7';
	case 8: return '8';
	case 9: return '9';
	case 10: return 'A';
	case 11: return 'B';
	case 12: return 'C';
	case 13: return 'D';
	case 14: return 'E';
	case 15: return 'F';
	}
	assert(false);
	return '?';
}

inline unsigned integral_division(unsigned dividend, unsigned divisor) {
	unsigned result = dividend/divisor;
	assert( dividend - (divisor*result) == 0 );
	return result;
}

struct Varlena : public varlena {
	unsigned _size() {
		return *reinterpret_cast<unsigned*>(vl_len_);
	}
	unsigned size() {
		assert(false);//WIP
		return _size();
	}
};

struct ItemHeader;
struct ItemData {
	ItemHeader* header;
	char* data;
	unsigned data_size;

	std::string hexadecimate_all(unsigned pos=0,unsigned max=-1) {
		std::string result;
		unsigned end = data_size;
		if( end > max )
			end = max;

		for( unsigned int i = pos; i < end; ++i ) {
			if( isalnum(data[i]) ) {
				result += data[i];
			} else if( data[i] == '\n' ) {
				result += "\\n";
			} else if( data[i] == ' ') {
				result += " ";
			} else {
//				result += std::to_string( data[i] );
//				result += hexadecimate( ((unsigned char)(data[i]))>>4 );
//				result += hexadecimate( data[i]&0xF );
				result += "X";
			}
//			result += " ";
		}
		return result;
	}

	unsigned get_serial(unsigned pos) {
		return *reinterpret_cast<unsigned*>( data+pos );
	};
	unsigned get_serial_size() {
		return 4;
	}

	Varlena* get_varlena(unsigned pos) {
		return reinterpret_cast<Varlena*>( data+pos );
	}
	unsigned get_varlena_size(unsigned pos) {
		return get_varlena(pos)->size();
	}

};

struct ItemHeader : public HeapTupleHeaderData {
	unsigned number_attributes() {
		return unsigned(t_infomask2 & HEAP_NATTS_MASK);
	}

	bool has_bitmap() {
		return bool(t_infomask & HEAP_HASNULL);
	}

	bool has_attribute(unsigned pos) {
		return !bool(att_isnull(pos,t_bits));
	}
};

struct PageData : public PageHeaderData {
	unsigned itemid_count() {
		return integral_division( pd_lower-sizeof(PageHeaderData)+sizeof(ItemIdData), sizeof(ItemIdData) );
	};

	ItemHeader* get_item_header(const ItemIdData& itemid) {
		return reinterpret_cast<ItemHeader*>( reinterpret_cast<char*>(this)+itemid.lp_off );
	};

	ItemData get_item_data(const ItemIdData& itemid) {
		ItemHeader* header = get_item_header(itemid);
		char* data = reinterpret_cast<char*>(header) + header->t_hoff;
		unsigned data_size = itemid.lp_len - header->t_hoff;

		ItemData result = {header,data,data_size};
		return result;
	}
};

char read_page_buffer[PAGE_SIZE];
PageData* read_page(std::istream& stream, unsigned pos) {
	stream.seekg(pos*PAGE_SIZE,std::istream::beg);
	stream.read(read_page_buffer,PAGE_SIZE);
	return reinterpret_cast<PageData*>(&read_page_buffer);
}

}

void user_code(ItemIdData& itemid, ItemHeader& itemheader, ItemData& itemdata);

int main(int argc, char** argv) {
	assert( sizeof(PageData) == 24+sizeof(ItemIdData) );
	assert( sizeof(ItemIdData) == 4 );

	if( argc < 2 ) {
		std::cerr << "Usage " << argv[0] << " input_file" << std::endl;
		return 1;
	}

	std::ifstream input(argv[1]);
	assert( input.good() );

	input.seekg(0, std::ifstream::end);
	unsigned size = input.tellg();
	input.seekg(0, std::ifstream::beg);
	unsigned pages = size/PAGE_SIZE;
	if( size - (pages*PAGE_SIZE) != 0 ) {
		std::cerr << "Given file is not aligned to " << PAGE_SIZE << " bytes" << std::endl;
		return 1;
	}

	if( pages == 0 ) {
		std::cerr << "Given file has zero pages" << std::endl;
		return 1;
	};

	for( unsigned int which_page=0;which_page<pages;++which_page) {
		PageData& page = *read_page(input,which_page);
		std::cout << "Page " << which_page << "(" << page.itemid_count() << " itens)" << std::endl;
		for( unsigned int i = 0; i < page.itemid_count(); ++i ) {
			ItemIdData& itemid = page.pd_linp[i];
			if( itemid.lp_flags != LP_NORMAL ) {
				std::cerr << "\tIgnoring item because it is not marked as LP_NORMAL" << std::endl;
			} else if( itemid.lp_len == 0 ) {
				std::cerr << "\tIgnoring item because it has no storage" << std::endl;
			} else if( itemid.lp_off > PAGE_SIZE ) {
				std::cerr << "\tIgnoring item because it's offset is outside of page" << std::endl;
			} else if( itemid.lp_off + itemid.lp_len > PAGE_SIZE ) {
				std::cerr << "\tIgnoring item because it spans outsize of the page" << std::endl;
			} else {
				ItemHeader& itemheader = *page.get_item_header(itemid);
				std::cout << "\tItem (" << itemid.lp_off << "," << itemid.lp_len << ")~" << itemid.lp_flags;
				std::cout << ", number of attributes is " << itemheader.number_attributes();
				std::cout << " " << (itemheader.has_bitmap() ? "with" : "without") << " bitmap";
				if( itemheader.has_bitmap() ) {
					std::cout << ":\t";
					for( unsigned int j=0; j < itemheader.number_attributes(); ++j) {
						std::cout << " " << itemheader.has_attribute(j);
					}
				}
				ItemData itemdata = page.get_item_data(itemid);
				std::cout << ", data size is " << itemdata.data_size << std::endl;

				user_code(itemid,itemheader,itemdata);
			}
		};
	}

	return 0;
};

void user_code(ItemIdData& itemid, ItemHeader& itemheader, ItemData& itemdata) {
	std::cout << itemdata.hexadecimate_all() << std::endl;

	return;
};
<|endoftext|>


<commit_before><commit_msg>Modify WidgetWin::Init() such that it doesn't create the FocusManager if the window is style WS_CHILD and parented to the desktop. We intentionally set the parent to the desktop window to remove it from the FocusManager hierarchy while the window is hidden.<commit_after><|endoftext|>


<commit_before>8696615c-4b02-11e5-a57f-28cfe9171a43<commit_msg>update testing<commit_after>86a6e721-4b02-11e5-b615-28cfe9171a43<|endoftext|>


<commit_before>c5c21e8c-4b02-11e5-b05d-28cfe9171a43<commit_msg>fixes, fixes for everyone<commit_after>c5d0c719-4b02-11e5-af83-28cfe9171a43<|endoftext|>


<commit_before>#include <QtCore>
#include <iostream>

#include <pHash.h>

static QString TMPPATH;                 // name of temporary dir (usually below /tmp)
static const double THRESHOLD = 0.6;    // find at least x% dupe frames to consider video duped
static const int FRAMES = 10;        // how many frames to compare
static const int HAMMINGDIST = 10;      // hamming distance threshold for frame comparison

// create snapshots from video file
void
createSnaps( const QString& file, const QString& tmpPath )
{
    QStringList args;
    args << "-nosound" << "-vo" << "jpeg"               // output as jpegs
         << "-ss" << "00:01:30"                         // start 45 seconds into the video
         << "-frames" << QString::number( FRAMES )   // output x frames total
         //<< "-sstep" << "30"                            // only output keyframes in 10 second increments
         << file;

    QProcess p;
    p.setWorkingDirectory( tmpPath );
    p.start( "mplayer", args );
    p.waitForFinished( 60000 );     // wait one minute at most
}

// create perceptual hash for snapshots
QHash<ulong64, int>
hashSnaps( const QString& path )
{
    QHash<ulong64, int> hashes;

    QDir dir( path );
    QFileInfoList list = dir.entryInfoList();
    for ( int i = 0; i < list.size(); ++i )
    {
        QFileInfo fileInfo = list.at( i );
        if ( !fileInfo.fileName().endsWith( ".jpg" ) )
            continue;

        ulong64 hash;
        int err = ph_dct_imagehash( fileInfo.absoluteFilePath().toLocal8Bit(), hash );
        if ( err )
            continue;

        hashes.insertMulti( hash, i );

        // delete snapshot
        QFile::remove( fileInfo.absoluteFilePath() );
    }

    return hashes;
}

// finds similar hashes by hamming distance
QList <QPair <int, QString> >
closestHashes( QHash<ulong64, QPair<int, QString> >& hashes, const ulong64& searchKey )
{
    QList <QPair <int, QString> > res;

    for ( int i = 0; i < hashes.keys().count(); i++ )
    {
        ulong64 key = hashes.keys().at( i );
        if ( ph_hamming_distance( searchKey, key ) < HAMMINGDIST )
        {
            QPair<int, QString> pair = hashes.values().at( i );
            res << pair;
        }
    }

    return res;
}

void
scanDir( QHash<ulong64, QPair<int, QString> >& hashes, const QString& path )
{
//    qDebug() << "Scanning dir:" << path;

    QDir dir( path );
    QFileInfoList list = dir.entryInfoList();
    for ( int i = 0; i < list.size(); ++i )
    {
        QFileInfo fileInfo = list.at( i );
        if ( fileInfo.isSymLink() )
            continue;
        if ( fileInfo.fileName().startsWith( "." ) )
            continue;

        if ( fileInfo.isDir() )
        {
            // scan recursively
            scanDir( hashes, fileInfo.absolutePath() + "/" + fileInfo.fileName() );
            continue;
        }

        if ( !fileInfo.fileName().endsWith(".wmv") && !fileInfo.fileName().endsWith(".avi") &&
             !fileInfo.fileName().endsWith(".mp4") && !fileInfo.fileName().endsWith(".mkv") &&
             !fileInfo.fileName().endsWith(".flv") && !fileInfo.fileName().endsWith(".mpg") &&
             !fileInfo.fileName().endsWith(".m4v") && !fileInfo.fileName().endsWith(".mov") &&
             !fileInfo.fileName().endsWith(".divx") && !fileInfo.fileName().endsWith(".mpeg") )
        {
            // only index videos
            continue;
        }

        std::cout << "Indexing \"" << qPrintable( fileInfo.absoluteFilePath() ) << "\" - size: " << fileInfo.size() << std::endl;

        // create snapshots
        createSnaps( fileInfo.absoluteFilePath(), TMPPATH );
        // analyze and hash snapshots
        QHash<ulong64, int> hash = hashSnaps( TMPPATH );

        QPair<int, QString> pair;       // snapshot #, filename
        QHash<QString, int> matches;    // filename, matches

        // go through all extracted snapshots and find dupes
        for ( int j = 0; j < hash.keys().count(); j++ )
        {
            ulong64 key = hash.keys().at( j );  // hash
            int value = hash.values().at( j );  // snapshot #

            {
                QList<QPair<int, QString> > res;    // snapshot #, filename

                // find closest snapshots by hamming distance
                res = closestHashes( hashes, key );
                for ( int x = 0; x < res.count(); x++ )
                {
                    pair = res.at( x );
                    if ( pair.second == fileInfo.absoluteFilePath() )
                    {
                        // ignore matches to self
                        continue;
                    }

                    // add/increment match count
                    if ( !matches.contains( pair.second ) )
                        matches[pair.second] = 1;
                    else
                        matches[pair.second] = matches[pair.second] + 1;
                }
            }

            // store hashes for future comparisons
            pair.first = value;
            pair.second = fileInfo.absoluteFilePath();
            hashes.insertMulti( key, pair );
        }

        for ( int y = 0; y < matches.keys().count(); y++ )
        {
            // threshold of matched snapshots to consider duped
            if ( (double)matches.values().at( y ) / (double)hash.count() >= THRESHOLD )
            {
                std::cout << "   --> Dupe of \"" << qPrintable( matches.keys().at( y ) ) << "\" - size: " << QFileInfo( matches.keys().at( y ) ).size()
                          << " (scores " << qMin( FRAMES, matches.values().at( y ) ) << " out of " << qMin( FRAMES, hash.count() ) << ")" << std::endl;
            }
        }
    }
}

int
main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    if ( app.arguments().count() < 2 )
    {
        std::cout << "Usage: xray /some/dir/full/of/videos" << std::endl;
        std::cout << "xray indexes video files by their perceptual hash and finds duplicates." << std::endl
                  << "This means files are not compared byte for byte, but by their visual content." << std::endl
                  << "It will/should find dupes of videos, even when they are encoded in different formats and resolutions." << std::endl;
        return 1;
    }

    QHash<ulong64, QPair<int, QString> > hashes;    // perceptual hash, pair<snapshot #, filename>

    QTemporaryDir tmpDir;
    TMPPATH = tmpDir.path();
    scanDir( hashes, app.arguments().at( 1 ) );

    return 0;
}
<commit_msg>* Switched to analyzing frames spread out further apart and using ffmpeg.<commit_after>#include <QtCore>
#include <iostream>

#include <pHash.h>

static QString TMPPATH;                 // name of temporary dir (usually below /tmp)
static const double THRESHOLD = 0.6;    // find at least x% dupe frames to consider video duped
static const int FRAMES = 5;            // how many frames to compare
static const int HAMMINGDIST = 16;      // hamming distance threshold for frame comparison

QString
timeToString( int seconds )
{
    int mins = seconds / 60 % 60;
    int secs = seconds % 60;

    if ( seconds < 0 )
    {
        mins = secs = 0;
    }

    return QString( "%1:%2" )
        .arg( mins < 10 ? "0" + QString::number( mins ) : QString::number( mins ) )
        .arg( secs < 10 ? "0" + QString::number( secs ) : QString::number( secs ) );
}

// create snapshots from video file
void
createSnaps( const QString& file, const QString& tmpPath )
{
    for ( int i = 0; i < FRAMES; i++ )
    {
        QStringList args;
        args
             << "-ss" << timeToString( i * 60 + 90 )
             << "-i" << file
             << "-y"
             << "-f" << "image2"
             << "-vcodec" << "mjpeg"
             << "-vframes" << "1"
             << "-vf" << "scale=128:-1"
             << QString( "%1.jpg" ).arg( i );

        QProcess p;
        p.setWorkingDirectory( tmpPath );
        p.start( "ffmpeg", args );
        p.waitForFinished( 60000 );     // wait one minute at most
    }
}

// create perceptual hash for snapshots
QHash<ulong64, int>
hashSnaps( const QString& path )
{
    QHash<ulong64, int> hashes;

    QDir dir( path );
    QFileInfoList list = dir.entryInfoList();
    for ( int i = 0; i < list.size(); ++i )
    {
        QFileInfo fileInfo = list.at( i );
        if ( !fileInfo.fileName().endsWith( ".jpg" ) )
            continue;

        ulong64 hash;
        int err = ph_dct_imagehash( fileInfo.absoluteFilePath().toLocal8Bit(), hash );
        if ( err )
            continue;

        hashes.insertMulti( hash, i );

        // delete snapshot
        QFile::remove( fileInfo.absoluteFilePath() );
    }

    return hashes;
}

// finds similar hashes by hamming distance
QList <QPair <int, QString> >
closestHashes( QHash<ulong64, QPair<int, QString> >& hashes, const ulong64& searchKey )
{
    QList <QPair <int, QString> > res;

    for ( int i = 0; i < hashes.keys().count(); i++ )
    {
        ulong64 key = hashes.keys().at( i );
        if ( ph_hamming_distance( searchKey, key ) < HAMMINGDIST )
        {
            QPair<int, QString> pair = hashes.values().at( i );
            res << pair;
        }
    }

    return res;
}

void
scanDir( QHash<ulong64, QPair<int, QString> >& hashes, const QString& path )
{
//    qDebug() << "Scanning dir:" << path;

    QDir dir( path );
    QFileInfoList list = dir.entryInfoList();
    for ( int i = 0; i < list.size(); ++i )
    {
        QFileInfo fileInfo = list.at( i );
        if ( fileInfo.isSymLink() )
            continue;
        if ( fileInfo.fileName().startsWith( "." ) )
            continue;

        if ( fileInfo.isDir() )
        {
            // scan recursively
            scanDir( hashes, fileInfo.absolutePath() + "/" + fileInfo.fileName() );
            continue;
        }

        if ( !fileInfo.fileName().endsWith(".wmv") && !fileInfo.fileName().endsWith(".avi") &&
             !fileInfo.fileName().endsWith(".mp4") && !fileInfo.fileName().endsWith(".mkv") &&
             !fileInfo.fileName().endsWith(".flv") && !fileInfo.fileName().endsWith(".mpg") &&
             !fileInfo.fileName().endsWith(".m4v") && !fileInfo.fileName().endsWith(".mov") &&
             !fileInfo.fileName().endsWith(".divx") && !fileInfo.fileName().endsWith(".mpeg") )
        {
            // only index videos
            continue;
        }

        std::cout << "Indexing \"" << qPrintable( fileInfo.absoluteFilePath() ) << "\" - size: " << fileInfo.size() << std::endl;

        // create snapshots
        createSnaps( fileInfo.absoluteFilePath(), TMPPATH );
        // analyze and hash snapshots
        QHash<ulong64, int> hash = hashSnaps( TMPPATH );

        QPair<int, QString> pair;       // snapshot #, filename
        QHash<QString, int> matches;    // filename, matches

        // go through all extracted snapshots and find dupes
        for ( int j = 0; j < hash.keys().count(); j++ )
        {
            ulong64 key = hash.keys().at( j );  // hash
            int value = hash.values().at( j );  // snapshot #

            {
                QList<QPair<int, QString> > res;    // snapshot #, filename

                // find closest snapshots by hamming distance
                res = closestHashes( hashes, key );
                for ( int x = 0; x < res.count(); x++ )
                {
                    pair = res.at( x );
                    if ( pair.second == fileInfo.absoluteFilePath() )
                    {
                        // ignore matches to self
                        continue;
                    }

                    // add/increment match count
                    if ( !matches.contains( pair.second ) )
                        matches[pair.second] = 1;
                    else
                        matches[pair.second] = matches[pair.second] + 1;

                    break;
                }
            }

            // store hashes for future comparisons
            pair.first = value;
            pair.second = fileInfo.absoluteFilePath();
            hashes.insertMulti( key, pair );
        }

        for ( int y = 0; y < matches.keys().count(); y++ )
        {
            // threshold of matched snapshots to consider duped
            if ( (double)matches.values().at( y ) / (double)hash.count() >= THRESHOLD )
            {
                std::cout << "   --> Dupe of \"" << qPrintable( matches.keys().at( y ) ) << "\" - size: " << QFileInfo( matches.keys().at( y ) ).size()
                          << " (scores " << qMin( FRAMES, matches.values().at( y ) ) << " out of " << qMin( FRAMES, hash.count() ) << ")" << std::endl;
            }
        }
    }
}

int
main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    if ( app.arguments().count() < 2 )
    {
        std::cout << "Usage: xray /some/dir/full/of/videos" << std::endl;
        std::cout << "xray indexes video files by their perceptual hash and finds duplicates." << std::endl
                  << "This means files are not compared byte for byte, but by their visual content." << std::endl
                  << "It will/should find dupes of videos, even when they are encoded in different formats and resolutions." << std::endl;
        return 1;
    }

    QHash<ulong64, QPair<int, QString> > hashes;    // perceptual hash, pair<snapshot #, filename>

    QTemporaryDir tmpDir;
    TMPPATH = tmpDir.path();
    scanDir( hashes, app.arguments().at( 1 ) );

    return 0;
}
<|endoftext|>