1
/***************************************************************************
2
 * Copyright (c) 2009 Enrico Ros                                           *
3
 *         2009 Enrico Ros <enrico.ros@email.it>                           *
4
 *         2009 Alberto Scarpa <skaal.sl@gmail.com>                        *
5
 *                                                                         *
6
 * Permission is hereby granted, free of charge, to any person             *
7
 * obtaining a copy of this software and associated documentation          *
8
 * files (the "Software"), to deal in the Software without                 *
9
 * restriction, including without limitation the rights to use,            *
10
 * copy, modify, merge, publish, distribute, sublicense, and/or sell       *
11
 * copies of the Software, and to permit persons to whom the               *
12
 * Software is furnished to do so, subject to the following                *
13
 * conditions:                                                             *
14
 *                                                                         *
15
 * The above copyright notice and this permission notice shall be          *
16
 * included in all copies or substantial portions of the Software.         *
17
 *                                                                         *
18
 ***************************************************************************/
19
20
#include "WCGame.h"
21
22
#include "Scrambler.h"
23
#include "ScreenCapture.h"
24
#include "InputUtils.h"
25
#include "ocr/Ocr.h"
26
#include "ui_AppWidget.h"
27
#include <QTimer>
28
#include <QDebug>
29
#include <QPainter>
30
31
//BEGIN portableMSleep
32
#ifdef Q_OS_UNIX
33
#include <unistd.h>
34
void portableMSleep( int ms ) {
35
    ::usleep( ms * 1000 );
36
}
37
#else
38
#ifdef Q_OS_WIN32
39
#include <windows.h>
40
void portableMSleep( int ms ) {
41
    Sleep( ms );
42
}
43
#endif
44
#endif
45
//END portableMSleep
46
47
48
//static const int WC_CAP_L = 114;
49
//static const int WC_CAP_T = 245;
50
static const int WC_BASELINE_H[] = { 7, 61, 116, 170, 224, 279 };
51
static const int WC_BASELINE_V[] = { 3,  3,   3,   3,   3,   3 };
52
static const int WC_LETTER_W = 35;
53
static const int WC_LETTER_H = 37;
54
55
WCGame::WCGame( QObject * parent )
56
    : AbstractGame( parent )
57
    , m_wordsDictionary( new Scrambler() )
58
    , m_namesDictionary( new Scrambler() )
59
{
60
    // load the dictionaries
61
    m_wordsDictionary->addDictionary( "dic-it.txt" );
62
    m_namesDictionary->addDictionary( "dic-enrico.txt" );
63
}
64
65
WCGame::~WCGame()
66
{
67
    delete m_wordsDictionary;
68
    delete m_namesDictionary;
69
}
70
71
QPixmap WCGame::highlightPixmap( const QPixmap & pixmap ) const
72
{
73
    QPixmap pix = pixmap;
74
    QPainter pp( &pix );
75
    pp.setPen( Qt::red );
76
    for ( int i = 0; i < 6; i++ )
77
        pp.drawRect( WC_BASELINE_H[ i ], WC_BASELINE_V[ i ], WC_LETTER_W - 1, WC_LETTER_H - 1 );
78
    pp.end();
79
    return pix;
80
}
81
82
void WCGame::train( Ocr * ocr, QString lettersText, const QImage & gamePixmap ) const
83
{
84
    for ( int i = 0; i < 6; i++ ) {
85
        QImage letterImage = gamePixmap.copy( WC_BASELINE_H[ i ], WC_BASELINE_V[ i ], WC_LETTER_W, WC_LETTER_H );
86
        QChar character = lettersText.at( i );
87
        letterImage.save( QString( "wc-glyphs/glyph_%1.png" ).arg( character.toLatin1() ), "PNG" );
88
        ocr->trainGlyph( letterImage, character );
89
    }
90
}
91
92
void WCGame::run( Ui::AppWidgetClass * ui, const ScreenCapture * capture, const Ocr * ocr )
93
{
94
    if ( m_time.isNull() )
95
        m_time.start();
96
    if ( m_time.elapsed() > (60 * 60 * 1000) )
97
        return;
98
99
    // OCR screen -> 6Chars + mean color identification
100
    QString letters;
101
    QImage gamePixmap = capture->lastPixmap().toImage();
102
    int meanR = 0, meanG = 0, meanB = 0;
103
    for ( int i = 0; i < 6; i++ ) {
104
        // accumulate intermediate color (yellow for normal, pink for name)
105
        if ( i > 1 ) {
106
            int sampleX = (WC_BASELINE_H[ i ] + WC_BASELINE_H[ i - 1 ] + WC_LETTER_W) >> 1;
107
            int sampleY = (WC_BASELINE_V[ i ] + WC_LETTER_H) >> 1;
108
            QRgb sampleColor = gamePixmap.pixel( sampleX, sampleY );
109
            meanR += qRed( sampleColor );
110
            meanG += qGreen( sampleColor );
111
            meanB += qBlue( sampleColor );
112
        }
113
        QImage letterImage = gamePixmap.copy( WC_BASELINE_H[ i ], WC_BASELINE_V[ i ], WC_LETTER_W, WC_LETTER_H );
114
        OcrResult res = ocr->recognizeGlyph( letterImage );
115
        if ( res.confidence > 0.1 )
116
            letters.append( res.character.toLower() );
117
        //qWarning() << res.character << res.confidence;
118
    }
119
    ui->currentLetters->setText( letters );
120
    if ( letters.length() != 6 )
121
        return;
122
123
    // select the dictionary based on the game type
124
    qreal meanHue = QColor( meanR / 5, meanG / 5, meanB / 5 ).hueF();
125
    Scrambler * scrambler = (meanHue > 0.89 && meanHue < 0.99) ? m_namesDictionary : m_wordsDictionary;
126
127
    // Do Anagram
128
    QStringList words = scrambler->words( letters, ui->minLetters->value(), ui->maxLetters->value() );
129
    ui->anagramWords->setText(QString::number(words.size()));
130
131
    // Write Words
132
    InputUtils::mouseMove( capture->geometry().center() );
133
    InputUtils::mouseLeftClick();
134
    portableMSleep( 200 );
135
    int count = words.size();
136
    for ( int i = 0; i < count; i++ ) {
137
        InputUtils::keyWrite( words.at( i ) + '\n' );
138
        portableMSleep( 10 );
139
    }
140
    InputUtils::keyClickSpecial( Qt::Key_Control );
141
}