You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
461 lines
13 KiB
461 lines
13 KiB
/***************************************************************************
|
|
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 <tdepopupmenu.h>
|
|
|
|
#include <tqapplication.h>
|
|
#include <tqcanvas.h>
|
|
#include <tqlabel.h>
|
|
#include <tqpen.h>
|
|
#include <tqscrollview.h>
|
|
#include <tqwidget.h>
|
|
#include <tqrect.h>
|
|
#include <tqbrush.h>
|
|
#include <tqpainter.h>
|
|
#include <tqregexp.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( TQWidget* parent, const char* name, resource *Rsrc )
|
|
: TQVBox(parent, name), myResource(Rsrc)
|
|
{
|
|
max_rating = 2600;
|
|
max_time = 60;
|
|
seek = FALSE;
|
|
|
|
graph = new TQCanvas( 0, "Challenge_Graph" );
|
|
myStatusBar = new TQLabel( this, "Challenge_Graph_Status_Bar" );
|
|
myView = new Challenge_Graph_View( *graph, this, "Challenge_Graph_View", 0, myStatusBar );
|
|
|
|
TQT_BASE_OBJECT_NAME::connect(myView, TQT_SIGNAL(leftClick(int)), TQT_SLOT(selectMatch(int)));
|
|
TQT_BASE_OBJECT_NAME::connect(myView, TQT_SIGNAL(rightClick(Challenge_Game*, const TQPoint&)), TQT_SLOT(display_menuSeek(Challenge_Game*, const TQPoint&)));
|
|
|
|
|
|
/* Setup Style for myStatusBar */
|
|
myStatusBar->setAlignment( TQt::AlignAuto | TQt::AlignVCenter | TQt::SingleLine );
|
|
myStatusBar->setFrameStyle( TQFrame::Panel | TQFrame::Sunken );
|
|
clear();
|
|
|
|
menuSeek = new TDEPopupMenu( this );
|
|
menuSeek->setCheckable( TRUE );
|
|
menuSeek->insertItem( i18n("Seek Matches"), this, TQT_SLOT( menuFunct(int) ), 0, MENU_SEEK );
|
|
menuSeek->insertSeparator();
|
|
menuSeek->insertItem( i18n("Accept This Match"), this, TQT_SLOT( menuFunct(int) ), 0, MENU_ACCEPT_MATCH );
|
|
menuSeek->insertItem( i18n("Tell..."), this, TQT_SLOT( menuFunct(int) ), 0, MENU_TELL );
|
|
menuSeek->insertItem( i18n("Assess..."), this, TQT_SLOT( menuFunct(int) ), 0, MENU_ASSESS );
|
|
menuSeek->insertItem( i18n("Player Info"), this, TQT_SLOT( menuFunct(int) ), 0, MENU_FINGER );
|
|
menuSeek->insertItem( TQIconSet( myResource->LoadIcon( TQString("history"), TDEIcon::Small ) ),
|
|
i18n("Player History"), this, TQT_SLOT( menuFunct(int) ), 0, MENU_HISTORY );
|
|
menuSeek->insertSeparator();
|
|
menuSeek->insertItem( i18n("Add to Friends"), this, TQT_SLOT( menuFunct(int) ), 0, MENU_NOTIFY );
|
|
menuSeek->insertItem( i18n("Ignore This Player"), this, TQT_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( TQResizeEvent *e )
|
|
{
|
|
if( e->size() != e->oldSize() )
|
|
{
|
|
TQSize 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;
|
|
|
|
TQCanvasPolygonalItem *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( TQBrush(myResource->COLOR_GraphForeground) );
|
|
else
|
|
item->setBrush( TQBrush(myResource->COLOR_GraphBackground, TQt::SolidPattern) );
|
|
|
|
item->show();
|
|
graph->update();
|
|
}
|
|
///////////////////////////////////////
|
|
//
|
|
// Challenge_Graph::isEmpty
|
|
//
|
|
///////////////////////////////////////
|
|
bool Challenge_Graph::isEmpty(int x, int y)
|
|
{
|
|
TQCanvasItemList l = graph->collisions( TQRect(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 )
|
|
{
|
|
TQPainter painter;
|
|
TQColor ink;
|
|
TQWMatrix 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, TQString::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, TQString( "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, TQString::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 TQString &src )
|
|
{
|
|
TQStringList fields = TQStringList::split( TQChar(' '), 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 TQPoint &Pos )
|
|
{
|
|
bool enable;
|
|
if( Item != NULL )
|
|
{
|
|
selectedPlayerName = Item->_player.replace( TQRegExp("\\(.+\\)"), TQString("") );
|
|
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;
|
|
}
|
|
}
|