This commit is contained in:
7
Define.h
Normal file
7
Define.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef __DEFINE__
|
||||
#define __DEFINE__
|
||||
|
||||
#define WINDOW_WIDTH 700
|
||||
#define WINDOW_HEIGHT 400
|
||||
|
||||
#endif
|
||||
167
PatternChecker.cpp
Normal file
167
PatternChecker.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
#include "Define.h"
|
||||
#include "PatternChecker.h"
|
||||
|
||||
#define HOR_GAP 4
|
||||
|
||||
#define _MAX_DATA (WINDOW_WIDTH/HOR_GAP)
|
||||
#define _MAX_DELTA 10
|
||||
|
||||
|
||||
#define SCALE_FACTOR_PLUS_X 0.5f
|
||||
#define SCALE_FACTOR_PLUS_Y 0.1f
|
||||
|
||||
CPatternChecker::CPatternChecker()
|
||||
{
|
||||
m_iCamX = 0;
|
||||
m_iCamY = 0;
|
||||
m_fScaleFactorX = 1.0f;
|
||||
m_fScaleFactorY = 1.0f;
|
||||
}
|
||||
|
||||
CPatternChecker::~CPatternChecker()
|
||||
{
|
||||
}
|
||||
|
||||
void CPatternChecker::GenerateOne(void)
|
||||
{
|
||||
int iDelta = rand()%(_MAX_DELTA<<1);
|
||||
iDelta -= _MAX_DELTA;
|
||||
|
||||
if(m_DataSet.size() == 0)
|
||||
{
|
||||
m_DataSet.push_back(iDelta);
|
||||
}
|
||||
else
|
||||
{
|
||||
int iNewData = m_DataSet[m_DataSet.size()-1] + iDelta;
|
||||
m_DataSet.push_back(iNewData);
|
||||
}
|
||||
|
||||
if(m_DataSet.size() > _MAX_DATA)
|
||||
m_DataSet.erase(m_DataSet.begin());
|
||||
}
|
||||
|
||||
void CPatternChecker::ScaleUp(const int iX, const int iY)
|
||||
{
|
||||
if(m_fScaleFactorX < 20.0f)
|
||||
{
|
||||
float fOrgX = m_iCamX + iX/m_fScaleFactorX;
|
||||
m_iCamX = (int)(fOrgX - fOrgX/(m_fScaleFactorX+SCALE_FACTOR_PLUS_X) + 0.5f);
|
||||
|
||||
float fOrgY = m_iCamY + iY/m_fScaleFactorY;
|
||||
m_iCamY = (int)(fOrgY - fOrgY/(m_fScaleFactorY+SCALE_FACTOR_PLUS_Y) + 0.5f);
|
||||
|
||||
m_fScaleFactorX += SCALE_FACTOR_PLUS_X;
|
||||
m_fScaleFactorY += SCALE_FACTOR_PLUS_Y;
|
||||
}
|
||||
}
|
||||
|
||||
void CPatternChecker::ScaleDown(const int iX, const int iY)
|
||||
{
|
||||
if(m_fScaleFactorX > 1.0f)
|
||||
{
|
||||
float fOrgX = m_iCamX + iX/m_fScaleFactorX;
|
||||
m_iCamX = (int)(fOrgX - fOrgX/(m_fScaleFactorX-SCALE_FACTOR_PLUS_X) + 0.5f);
|
||||
|
||||
float fOrgY = m_iCamY + iY/m_fScaleFactorY;
|
||||
m_iCamY = (int)(fOrgY - fOrgY/(m_fScaleFactorY-SCALE_FACTOR_PLUS_Y) + 0.5f);
|
||||
|
||||
m_fScaleFactorX -= SCALE_FACTOR_PLUS_X;
|
||||
m_fScaleFactorY -= SCALE_FACTOR_PLUS_Y;
|
||||
}
|
||||
}
|
||||
|
||||
void CPatternChecker::ResetScale(void)
|
||||
{
|
||||
m_iCamX = 0;
|
||||
m_iCamY = 0;
|
||||
m_fScaleFactorX = 1.0f;
|
||||
m_fScaleFactorY = 1.0f;
|
||||
}
|
||||
|
||||
void CPatternChecker::MoveScr(const int iX, const int iY)
|
||||
{
|
||||
const int iVirtualScrW = (int)(WINDOW_WIDTH/m_fScaleFactorX);
|
||||
float fMove = iX/m_fScaleFactorX;
|
||||
fMove = (fMove > 0.0f) ? (fMove+0.5f) : (fMove-0.5f);
|
||||
|
||||
m_iCamX -= (int)fMove;
|
||||
if(m_iCamX < 0)
|
||||
m_iCamX = 0;
|
||||
else if(m_iCamX > WINDOW_WIDTH-iVirtualScrW)
|
||||
m_iCamX = WINDOW_WIDTH-iVirtualScrW;
|
||||
|
||||
const int iVirtualScrH = (int)(WINDOW_HEIGHT/m_fScaleFactorY);
|
||||
|
||||
fMove = iY/m_fScaleFactorX;
|
||||
fMove = (fMove > 0.0f) ? (fMove+0.5f) : (fMove-0.5f);
|
||||
|
||||
m_iCamY -= (int)fMove;
|
||||
if(m_iCamY < 0)
|
||||
m_iCamY = 0;
|
||||
else if(m_iCamY > WINDOW_HEIGHT-iVirtualScrH)
|
||||
m_iCamY = WINDOW_HEIGHT-iVirtualScrH;
|
||||
}
|
||||
|
||||
void CPatternChecker::Reset(void)
|
||||
{
|
||||
m_DataSet.clear();
|
||||
ResetScale();
|
||||
}
|
||||
|
||||
void CPatternChecker::Draw(HDC hDC)
|
||||
{
|
||||
Rectangle(hDC, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
|
||||
|
||||
//char corrd[100] = {0, };
|
||||
//sprintf_s(corrd, 100, "(%d, %d) ", m_iCamX, m_iCamY);
|
||||
//TextOut(hDC, 0, 0, corrd, RGB(200, 0, 0));
|
||||
|
||||
|
||||
int iHY = (WINDOW_HEIGHT>>1);
|
||||
iHY -= m_iCamY;
|
||||
iHY = (int)(iHY*m_fScaleFactorY);
|
||||
|
||||
MoveToEx(hDC, 0, iHY, NULL);
|
||||
LineTo(hDC, WINDOW_WIDTH, iHY);
|
||||
|
||||
HPEN hRedPen = CreatePen(PS_SOLID, 1, RGB(200, 0, 0));
|
||||
HPEN hOldPen = (HPEN)SelectObject(hDC, hRedPen);
|
||||
|
||||
HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 200));
|
||||
|
||||
MoveToEx(hDC, 0, WINDOW_HEIGHT>>1, NULL);
|
||||
int iPrevX=0;
|
||||
int iX;
|
||||
int iY;
|
||||
|
||||
RECT Stick;
|
||||
|
||||
for(unsigned int i=0; i<m_DataSet.size(); i++)
|
||||
{
|
||||
iX = i*HOR_GAP;
|
||||
iX -= m_iCamX;
|
||||
iX = (int)(iX*m_fScaleFactorX);
|
||||
|
||||
iY = (WINDOW_HEIGHT>>1)-m_DataSet[i];
|
||||
iY -= m_iCamY;
|
||||
iY = (int)(iY*m_fScaleFactorY);
|
||||
|
||||
Stick.left = iPrevX+1;
|
||||
Stick.right = iX;
|
||||
Stick.top = iY;
|
||||
Stick.bottom = iHY;
|
||||
|
||||
FillRect(hDC, &Stick, hBrush);
|
||||
|
||||
//Rectangle(hDC, iPrevX, iY, iX, iHY);
|
||||
LineTo(hDC, iX, iY);
|
||||
|
||||
iPrevX = iX;
|
||||
}
|
||||
|
||||
SelectObject(hDC, hOldPen);
|
||||
DeleteObject(hRedPen);
|
||||
DeleteObject(hBrush);
|
||||
}
|
||||
33
PatternChecker.h
Normal file
33
PatternChecker.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <Windows.h>
|
||||
|
||||
using std::vector;
|
||||
using std::list;
|
||||
|
||||
class CPatternChecker
|
||||
{
|
||||
public:
|
||||
CPatternChecker();
|
||||
~CPatternChecker();
|
||||
|
||||
void GenerateOne(void);
|
||||
void Draw(HDC hDC);
|
||||
|
||||
void ScaleUp(const int iX, const int iY);
|
||||
void ScaleDown(const int iX, const int iY);
|
||||
void ResetScale(void);
|
||||
|
||||
void MoveScr(const int iX, const int iY);
|
||||
|
||||
void Reset(void);
|
||||
|
||||
private:
|
||||
vector<int> m_DataSet;
|
||||
|
||||
int m_iCamX;
|
||||
int m_iCamY;
|
||||
float m_fScaleFactorX;
|
||||
float m_fScaleFactorY;
|
||||
|
||||
};
|
||||
20
PatternChecker.sln
Normal file
20
PatternChecker.sln
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PatternChecker", "PatternChecker.vcproj", "{1472B2B0-D2BF-4607-9712-12D662F28844}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{1472B2B0-D2BF-4607-9712-12D662F28844}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{1472B2B0-D2BF-4607-9712-12D662F28844}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{1472B2B0-D2BF-4607-9712-12D662F28844}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{1472B2B0-D2BF-4607-9712-12D662F28844}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
196
PatternChecker.vcproj
Normal file
196
PatternChecker.vcproj
Normal file
@@ -0,0 +1,196 @@
|
||||
<?xml version="1.0" encoding="ks_c_5601-1987"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="PatternChecker"
|
||||
ProjectGUID="{1472B2B0-D2BF-4607-9712-12D662F28844}"
|
||||
RootNamespace="PatternChecker"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
GenerateDebugInformation="true"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
GenerateDebugInformation="true"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\PatternChecker.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\WinMain.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Define.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\PatternChecker.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
161
WinMain.cpp
Normal file
161
WinMain.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
#include <windows.h>
|
||||
#include "Define.h"
|
||||
#include "PatternChecker.h"
|
||||
#include <time.h>
|
||||
|
||||
HINSTANCE g_hInst;
|
||||
LPSTR lpszClass="PatternChecker";
|
||||
|
||||
CPatternChecker* pPC = NULL;
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
|
||||
{
|
||||
static HDC hDC = GetDC(hWnd);
|
||||
static HDC hMemDC = NULL;
|
||||
static HBITMAP hOldBitmap = NULL;
|
||||
static BOOL bLButtonDown = FALSE;
|
||||
static POINT LButtonPos;
|
||||
static BOOL bGenerate = TRUE;
|
||||
static int iTimerElapse = 100;
|
||||
|
||||
if(hMemDC == NULL)
|
||||
{
|
||||
HBITMAP hBit = CreateCompatibleBitmap(hDC, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
hMemDC = CreateCompatibleDC(hDC);
|
||||
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBit);
|
||||
}
|
||||
|
||||
|
||||
switch(iMessage)
|
||||
{
|
||||
case WM_CREATE:
|
||||
srand((int)time(NULL));
|
||||
SetTimer(hWnd, 0, iTimerElapse, NULL);
|
||||
SetFocus(hWnd);
|
||||
break;
|
||||
|
||||
case WM_TIMER:
|
||||
if(bGenerate == TRUE)
|
||||
pPC->GenerateOne();
|
||||
pPC->Draw(hMemDC);
|
||||
InvalidateRect(hWnd, NULL, FALSE);
|
||||
break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
if(wParam == VK_ESCAPE)
|
||||
pPC->Reset();
|
||||
|
||||
if(wParam == VK_F5)
|
||||
bGenerate = !bGenerate;
|
||||
|
||||
if(wParam == VK_UP && iTimerElapse > 10)
|
||||
{
|
||||
iTimerElapse -= 10;
|
||||
SetTimer(hWnd, 0, iTimerElapse, NULL);
|
||||
}
|
||||
if(wParam == VK_DOWN && iTimerElapse < 1000)
|
||||
{
|
||||
iTimerElapse += 10;
|
||||
SetTimer(hWnd, 0, iTimerElapse, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_PAINT:
|
||||
BitBlt(hDC, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, hMemDC, 0, 0, SRCCOPY);
|
||||
break;
|
||||
|
||||
case WM_MOUSEWHEEL:
|
||||
{
|
||||
RECT WindowRect;
|
||||
GetWindowRect(hWnd, &WindowRect);
|
||||
|
||||
int xPos = LOWORD(lParam) - WindowRect.left;
|
||||
int yPos = HIWORD(lParam) - WindowRect.top;
|
||||
|
||||
short zDelta = (short)HIWORD(wParam);
|
||||
if(zDelta < 0)
|
||||
pPC->ScaleDown(xPos, yPos);
|
||||
else
|
||||
pPC->ScaleUp(xPos, yPos);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_MBUTTONDOWN:
|
||||
pPC->ResetScale();
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
bLButtonDown = TRUE;
|
||||
LButtonPos.x = (short)LOWORD(lParam);
|
||||
LButtonPos.y = (short)HIWORD(lParam);
|
||||
break;
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
bLButtonDown = FALSE;
|
||||
break;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
if(bLButtonDown == TRUE)
|
||||
{
|
||||
int iX = (short)LOWORD(lParam);
|
||||
int iY = (short)HIWORD(lParam);
|
||||
|
||||
pPC->MoveScr(iX-LButtonPos.x, iY-LButtonPos.y);
|
||||
|
||||
LButtonPos.x = iX;
|
||||
LButtonPos.y = iY;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
SelectObject(hMemDC, hOldBitmap);
|
||||
DeleteObject(hOldBitmap);
|
||||
ReleaseDC(hWnd, hMemDC);
|
||||
|
||||
ReleaseDC(hWnd, hDC);
|
||||
KillTimer(hWnd, 0);
|
||||
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProc(hWnd,iMessage,wParam,lParam);
|
||||
}
|
||||
|
||||
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
|
||||
,LPSTR lpszCmdParam,int nCmdShow)
|
||||
{
|
||||
HWND hWnd;
|
||||
MSG Message;
|
||||
WNDCLASS WndClass;
|
||||
g_hInst=hInstance;
|
||||
|
||||
WndClass.cbClsExtra=0;
|
||||
WndClass.cbWndExtra=0;
|
||||
WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
|
||||
WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
|
||||
WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
|
||||
WndClass.hInstance=hInstance;
|
||||
WndClass.lpfnWndProc=(WNDPROC)WndProc;
|
||||
WndClass.lpszClassName=lpszClass;
|
||||
WndClass.lpszMenuName=NULL;
|
||||
WndClass.style=CS_HREDRAW | CS_VREDRAW;
|
||||
RegisterClass(&WndClass);
|
||||
|
||||
hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT,CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT,
|
||||
NULL,(HMENU)NULL,hInstance,NULL);
|
||||
ShowWindow(hWnd,nCmdShow);
|
||||
|
||||
pPC = new CPatternChecker();
|
||||
|
||||
while(GetMessage(&Message,0,0,0)) {
|
||||
TranslateMessage(&Message);
|
||||
DispatchMessage(&Message);
|
||||
}
|
||||
|
||||
delete pPC;
|
||||
pPC = NULL;
|
||||
|
||||
return Message.wParam;
|
||||
}
|
||||
Reference in New Issue
Block a user