diff options
Diffstat (limited to 'knights/challenge_graph.cpp')
-rw-r--r-- | knights/challenge_graph.cpp | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/knights/challenge_graph.cpp b/knights/challenge_graph.cpp new file mode 100644 index 0000000..5d36ff1 --- /dev/null +++ b/knights/challenge_graph.cpp @@ -0,0 +1,460 @@ +/*************************************************************************** + challenge_graph.cpp - description + ------------------- + begin : Mon Jan 7 2002 + copyright : (C) 2003 by Eric Faccer + email : e.faccer@qut.edu.au + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include <unistd.h> +#include <string.h> +#include <stdlib.h> + +#include <kiconloader.h> +#include <kstddirs.h> +#include <kpopupmenu.h> + +#include <qapplication.h> +#include <qcanvas.h> +#include <qlabel.h> +#include <qpen.h> +#include <qscrollview.h> +#include <qwidget.h> +#include <qrect.h> +#include <qbrush.h> +#include <qpainter.h> +#include <qregexp.h> + +#include "challenge_graph.moc" +#include "challenge_graph_view.h" +#include "challenge_rectangle.h" +#include "command.h" +#include "definitions.h" + +/* SIZE is for the size of the challenge square. It could become a class variable */ +#define SIZE 8 +#define OFFSET 2 +#define SPACER SIZE+OFFSET + +/////////////////////////////////////// +// +// Challenge_Graph::Constructor +// +/////////////////////////////////////// +Challenge_Graph::Challenge_Graph( QWidget* parent, const char* name, resource *Rsrc ) + : QVBox(parent, name), myResource(Rsrc) +{ + max_rating = 2600; + max_time = 60; + seek = FALSE; + + graph = new QCanvas( 0, "Challenge_Graph" ); + myStatusBar = new QLabel( this, "Challenge_Graph_Status_Bar" ); + myView = new Challenge_Graph_View( *graph, this, "Challenge_Graph_View", 0, myStatusBar ); + + QObject::connect(myView, SIGNAL(leftClick(int)), SLOT(selectMatch(int))); + QObject::connect(myView, SIGNAL(rightClick(Challenge_Game*, const QPoint&)), SLOT(display_menuSeek(Challenge_Game*, const QPoint&))); + + + /* Setup Style for myStatusBar */ + myStatusBar->setAlignment( Qt::AlignAuto | Qt::AlignVCenter | Qt::SingleLine ); + myStatusBar->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + clear(); + + menuSeek = new KPopupMenu( this ); + menuSeek->setCheckable( TRUE ); + menuSeek->insertItem( i18n("Seek Matches"), this, SLOT( menuFunct(int) ), 0, MENU_SEEK ); + menuSeek->insertSeparator(); + menuSeek->insertItem( i18n("Accept This Match"), this, SLOT( menuFunct(int) ), 0, MENU_ACCEPT_MATCH ); + menuSeek->insertItem( i18n("Tell..."), this, SLOT( menuFunct(int) ), 0, MENU_TELL ); + menuSeek->insertItem( i18n("Assess..."), this, SLOT( menuFunct(int) ), 0, MENU_ASSESS ); + menuSeek->insertItem( i18n("Player Info"), this, SLOT( menuFunct(int) ), 0, MENU_FINGER ); + menuSeek->insertItem( QIconSet( myResource->LoadIcon( QString("history"), KIcon::Small ) ), + i18n("Player History"), this, SLOT( menuFunct(int) ), 0, MENU_HISTORY ); + menuSeek->insertSeparator(); + menuSeek->insertItem( i18n("Add to Friends"), this, SLOT( menuFunct(int) ), 0, MENU_NOTIFY ); + menuSeek->insertItem( i18n("Ignore This Player"), this, SLOT( menuFunct(int) ), 0, MENU_CENSOR ); + menuSeek->setItemChecked( MENU_SEEK, FALSE ); +} +/////////////////////////////////////// +// +// Challenge_Graph::Destructor +// +/////////////////////////////////////// +Challenge_Graph::~Challenge_Graph() +{ +} +/////////////////////////////////////// +// +// Challenge_Graph::resizeEvent +// +/////////////////////////////////////// +void Challenge_Graph::resizeEvent( QResizeEvent *e ) +{ + if( e->size() != e->oldSize() ) + { + QSize newsize = e->size(); + x_size = newsize.width() - 8; + y_size = newsize.height() - myStatusBar->height(); + graph->resize( x_size, y_size ); + createBackground(); + } +} +/////////////////////////////////////// +// +// Challenge_Graph::add +// +/////////////////////////////////////// +void Challenge_Graph::add(Challenge_Game *seek) +{ + double AdjustedClock = (float)seek->clock() + ( ( (float)seek->increment() / 60.0 ) * 20.0 ); + double my_x = (float)x_size / (float)max_time * AdjustedClock; + double mag = (float)max_rating / (float)y_size; + double my_y = ( max_rating - seek->rating() ) / mag; + + //bleah + //a bit of a hack for the status bar real estate & values larger then MAX + if ( seek->rating() < 250) + my_y = (max_rating - 250) / mag; + else if ( seek->rating() >= max_rating ) + my_y = 10; + + if ( seek->clock() > (max_time-3) ) + my_x = x_size/max_time * (max_time-3); + + int time_control_x = (int)(my_x); + int rating_y = (int)(my_y); + + if ( isEmpty(time_control_x, rating_y) ) + drawChallenge(time_control_x, rating_y, seek->rated(), seek); + else + addTo_Nearest_Neighbour(time_control_x, rating_y, seek->rated(), seek); +} +/////////////////////////////////////// +// +// Challenge_Graph::clear +// +/////////////////////////////////////// +void Challenge_Graph::clear() +{ + myView->reset(); + graph->update(); +} +/////////////////////////////////////// +// +// Challenge_Graph::drawChallenge +// +/////////////////////////////////////// +void Challenge_Graph::drawChallenge(int time_control_x, int rating_y, bool rated, Challenge_Game *challenge) +{ + /* This next peice of unelegant code is fairly unnecessary. It is to keep everything on the screen */ + /* It's based on the theory of prophylaxis */ + int my_x = time_control_x; + int my_y = rating_y; + + if( my_y >= y_size - SPACER) + my_y = y_size - SPACER; + if( my_y < SPACER ) + my_y = SPACER; + if( my_x >= x_size - ( SPACER ) ) + my_x = x_size - ( SPACER ); /*Since squares draw from the top left */ + if( my_x < SPACER ) + my_x = SIZE; + + QCanvasPolygonalItem *item = new Challenge_Rectangle(my_x, my_y, SIZE, SIZE, graph, challenge); + + item->setPen( myResource->COLOR_GraphForeground ); + item->move( time_control_x, rating_y ); + item->show(); + + if( rated ) + item->setBrush( QBrush(myResource->COLOR_GraphForeground) ); + else + item->setBrush( QBrush(myResource->COLOR_GraphBackground, Qt::SolidPattern) ); + + item->show(); + graph->update(); +} +/////////////////////////////////////// +// +// Challenge_Graph::isEmpty +// +/////////////////////////////////////// +bool Challenge_Graph::isEmpty(int x, int y) +{ + QCanvasItemList l = graph->collisions( QRect(x, y, SIZE, SIZE) ); + + if( l.count() ) + return false; + return true; +} + +/* This function does a spiral search for the nearest neighbour */ +/* Pre: TRUE + Post: Finds the nearest non-overlapping position to the original coordinates */ +/////////////////////////////////////// +// +// Challenge_Graph::addTo_Nearest_Neighbour +// +/////////////////////////////////////// +bool Challenge_Graph::addTo_Nearest_Neighbour(int orig_x, int orig_y, bool rated, Challenge_Game * challenge, int searchdepth) +{ + int right = 1; + int down = 2; + int left = 2; + int up = 3; + + int x = orig_x; + int y = orig_y - ( SIZE + OFFSET ); + + /* Check the location on top*/ + if ( isEmpty( x, y ) ) + { + drawChallenge( x, y, rated, challenge ); + return true; + } + + /* Now search in a spiral */ + while( right < searchdepth ) + { + for( int i = 0; i < right; i++ ) + { + x += SPACER; + if( isEmpty( x, y ) ) + { + drawChallenge( x, y, rated, challenge ); + return true; + } + } + for( int i = 0; i < down; i++ ) + { + y += SPACER; + if( isEmpty( x, y ) ) + { + drawChallenge( x, y, rated, challenge ); + return true; + } + } + for( int i = 0; i < left; i++ ) + { + x -= SPACER; + if( isEmpty( x, y) ) + { + drawChallenge( x, y, rated, challenge ); + return true; + } + } + for( int i = 0; i < up; i++ ) + { + y -= SPACER; + if( isEmpty( x, y ) ) + { + drawChallenge( x, y, rated, challenge ); + return true; + } + } + + /* Grow the spiral bounds */ + right += 2; + down += 2; + left += 2; + up += 2; + } + return false; +} +/////////////////////////////////////// +// +// Challenge_Graph::createBackground +// +/////////////////////////////////////// +void Challenge_Graph::createBackground( void ) +{ + QPainter painter; + QColor ink; + QWMatrix matrix; + int colorTotal; + + background.resize( y_size, x_size ); + background.fill( myResource->COLOR_GraphBackground ); + + /* Find out if we have a dark bgcolor or a light one. */ + colorTotal = ( myResource->COLOR_GraphBackground.red() + + myResource->COLOR_GraphBackground.blue() + + myResource->COLOR_GraphBackground.green() ); + + /* Set our ink to something that will contrast well */ + if( colorTotal < 384 ) // 384 = 50% gray + ink = myResource->COLOR_GraphBackground.light(); + else + ink = myResource->COLOR_GraphBackground.dark(); + + /* Paint the text on */ + painter.begin( &background ); + painter.setFont( myResource->FONT_Standard ); + painter.setPen( ink ); + painter.drawText( 64, 12, i18n( "Rating" ) ); + painter.end(); + matrix.rotate( -90.0 ); + background = background.xForm( matrix ); + painter.begin( &background ); + painter.setFont( myResource->FONT_Standard ); + painter.setPen( ink ); + painter.drawText( 64, y_size - 8, i18n( "Time" ) ); + painter.end(); + + graph->setBackgroundPixmap( background ); +} +/////////////////////////////////////// +// +// Challenge_Graph::selectMatch +// +/////////////////////////////////////// +void Challenge_Graph::selectMatch( int matchID ) +{ + if( matchID ) + emit sendCMD( Command( 0, CMD_Start_Match, QString::number( matchID ) ) ); +} +/////////////////////////////////////// +// +// Challenge_Graph::menuFunct +// +/////////////////////////////////////// +void Challenge_Graph::menuFunct( int funct ) +{ + switch( funct ) + { + case MENU_SEEK: + emit sendCMD( Command( 0, CMD_Toggle_Seek ) ); + break; + case MENU_FINGER: + emit sendCMD( Command( 0, CMD_Player_Finger, selectedPlayerName ) ); + break; + case MENU_TELL: + emit sendCMD( Command( 0, CMD_Set_Input, QString( "tell %1 " ).arg( selectedPlayerName ) ) ); + break; + case MENU_NOTIFY: + emit sendCMD( Command( 0, CMD_Add_Friend, selectedPlayerName ) ); + break; + case MENU_CENSOR: + emit sendCMD( Command( 0, CMD_Ignore_Player, selectedPlayerName ) ); + break; + case MENU_HISTORY: + emit sendCMD( Command( 0, CMD_Player_History, selectedPlayerName ) ); + break; + case MENU_ACCEPT_MATCH: + emit sendCMD( Command( 0, CMD_Start_Match, QString::number( selectedMatchID ) ) ); + break; + case MENU_ASSESS: + emit sendCMD( Command( 0, CMD_Assess, selectedPlayerName ) ); + break; + default: + break; + } +} +/////////////////////////////////////// +// +// Challenge_Graph::updateSoughtList +// +/////////////////////////////////////// +void Challenge_Graph::updateSoughtList( void ) +{ + unsigned int loop; + Challenge_Game *cg; + + clear(); + for( loop = 0; loop < SF_01.count(); loop++ ) + { + cg = new Challenge_Game( SF_01[loop], + SF_02[loop], + SF_03[loop], + SF_04[loop], + SF_05[loop], + SF_06[loop], + SF_07[loop] ); + add( cg ); + } + SF_01.clear(); + SF_02.clear(); + SF_03.clear(); + SF_04.clear(); + SF_05.clear(); + SF_06.clear(); + SF_07.clear(); + seek = TRUE; +} +/////////////////////////////////////// +// +// Challenge_Graph::addSoughtItem +// +/////////////////////////////////////// +void Challenge_Graph::addSoughtItem( const QString &src ) +{ + QStringList fields = QStringList::split( QChar(' '), src, FALSE ); + SF_01 << fields[2]; // Name + SF_02 << fields[1]; // Rating + SF_03 << fields[6]; // Match Type + SF_04 << fields[5]; // Is Rated? + SF_05 << fields[3]; // Base Time + SF_06 << fields[4]; // Increment + SF_07 << fields[0]; // ID# +} +/////////////////////////////////////// +// +// Challenge_Graph::display_menuSeek +// +/////////////////////////////////////// +void Challenge_Graph::display_menuSeek( Challenge_Game *Item, const QPoint &Pos ) +{ + bool enable; + if( Item != NULL ) + { + selectedPlayerName = Item->_player.replace( QRegExp("\\(.+\\)"), QString("") ); + selectedMatchID = Item->id(); + enable = TRUE; + } + else + { + enable = FALSE; + } + menuSeek->setItemChecked( MENU_SEEK, seek ); + menuSeek->setItemEnabled( MENU_FINGER, enable ); + menuSeek->setItemEnabled( MENU_TELL, enable ); + menuSeek->setItemEnabled( MENU_NOTIFY, enable ); + menuSeek->setItemEnabled( MENU_CENSOR, enable ); + menuSeek->setItemEnabled( MENU_HISTORY, enable ); + menuSeek->setItemEnabled( MENU_ACCEPT_MATCH, enable ); + menuSeek->setItemEnabled( MENU_ASSESS, enable ); + menuSeek->popup( Pos ); +} +/////////////////////////////////////// +// +// Challenge_Graph::recvCMD +// +/////////////////////////////////////// +void Challenge_Graph::recvCMD( const Command& command ) +{ + switch(((Command)command).getCommand()) + { + case CMD_Add_Sought_Match: + addSoughtItem( ((Command)command).getData() ); + break; + case CMD_Show_Sought_List: + updateSoughtList(); + break; + case CMD_Hide_Sought_List: + clear(); + seek = FALSE; + break; + default: + break; + } +} |