JFreeChart histogram with varying bin sizes - scala

How would I go about creating a histogram plot with JFreeChart, where the bins are exponentially growing, e.g. having intervals [0, 0.1), [0.1, 0.2), [0.2, 0.4), [0.4, 0.8) etc.
There is a HistogramBin class but it only seems to be used by HistogramDataset, which in turn doesn't seem to support varying bin sizes.

I can use a regular XY bar chart with pre-binning. Here is an example using scala-chart and a few extra numeric operations:
import de.sciss.numbers.Implicits._
import scalax.chart.{ChartFactories, Charting}
import Charting._
def mkHisto(durations: Seq[Double]): Chart[_] = {
// ..., -0.54, -0.18, -0.06, +0.06, +0.18, +0.54, ....
def bin(dur: Double) =
((dur.abs / 0.06).log / 3.log + 1).toInt.clip(0, 10) * dur.signum
val binned = durations.map(bin).counted.toSeq.sortBy(_._1)
val ds = binned.toXYSeriesCollection()
val ch = ChartFactories.XYBarChart(ds,
domainAxisLabel = "bin", rangeAxisLabel = "frequency", legend = false)
ChartFactories.XYBarChart(ds)
}
implicit class RichIterable[A, CC[~] <: Iterable[~]](it: CC[A]) {
def counted: Map[A, Int] = (Map.empty[A, Int].withDefaultValue(0) /: it)((m, e) =>
m.updated(e, m(e) + 1))
}
Without further plot/renderer customisation, this looks like this, given particular input data:
Test data:
val x = Vector(22.23312925170068, 15.460136054421769, 10.453968253968254, 0.7362131519274376, 1.9141043083900227, -80.39263038548752, 5.153378684807256, 44.46625850340136, -0.2944897959183673, -192.94580498866213, 7.566507936507937, -295.0935827664399, -11.909251700680272, -16.433492063492064, -15.60591836734694, 23.64532879818594, -22.69950113378685, 108.23530612244897, 2.352925170068027, 27.058820861678004, -22.352925170068026, -4.705873015873016, -4.5397278911564625, -1.7646938775510204, 81.76471655328798, -6.470589569160998, 30.967732426303854, 13.76344671201814, 2.867392290249433, 26.379931972789116, -17.51825396825397, 23.746961451247167, -30.410430839002267, -13.722630385487529, -146.28009070294786, -130.3674603174603, 1.4976643990929706, 0.936031746031746, 2.3244444444444445, -61.95258503401361, -50.051859410430836, -47.48528344671202, -69.55430839002267, -119.96390022675737, -3.2929931972789115, -3.2929931972789115, -5.447936507936508, -18.498798185941045, -18.78934240362812, 18.498798185941045, 58.11138321995465, 33.510884353741496, 44.55206349206349, 30.02421768707483, -113.5108843537415, 27.40918367346939, -1.1934920634920634, -120.73696145124717, 5.617437641723356, 5.617437641723356, 3.8740816326530614, 3.8740816326530614, -126.38659863945578, 17.820839002267572, 18.5956462585034, -26.731224489795917, -16.920226757369615, -52.91142857142857, -24.26716553287982, 7.346938775510204, -11.354353741496599, -11.13172335600907, -1.7810657596371882, -0.7305215419501134, -117.56074829931973, -2.240249433106576, 0.12176870748299319, -113.44839002267574, -13.12498866213152, -86.2028798185941, -5.47891156462585, -2.240249433106576, -0.09741496598639456, -1.168843537414966, -10.227256235827664, -4.577936507936508, -51.70156462585034, -0.4870068027210884, -0.7548752834467121, -5.405827664399093, 6.185079365079365, -29.959365079365078, -1.6558503401360545, -7.183424036281179, -1.0714285714285714, -16.747414965986394, -2.897732426303855, -0.9740362811791383, -63.77263038548753, -8.098163265306123, -18.388820861678006, -6.699387755102041, 17.079750566893424, 33.644172335600906, -37.55328798185941, -6.772993197278912, 28.564421768707483, -3.7546031746031745, -14.47281179138322, -5.963197278911565, 26.282222222222224, 16.35233560090703, 11.564761904761905, 12.0, 9.015555555555556, -13.994920634920636, -4.041451247165533, -4.103628117913832, -9.994149659863945, -3.35750566893424, -0.7461224489795918, -0.6839455782312925, -21.39922902494331, -1.7409297052154196, -4.414512471655329, -2.4248526077097505, -5.4714965986394555, -32.42954648526077, -2.549206349206349, 11.626938775510204, -18.03108843537415, -7.150272108843537, 2.7357596371882087, -0.06217687074829932, 0.18653061224489795, -2.3005215419501135, -39.17097505668934, -0.3730612244897959, 0.6217687074829932, 1.181360544217687, 1.1191836734693879, 0.13990929705215419, 0.09326530612244897, 0.09326530612244897, 0.21759637188208616, 0.1554421768707483, 0.1554421768707483, 46.169160997732426, 1.1940136054421768, 60.49750566893424, 6.965192743764172, -5.572154195011338, 19.041315192743763, 109.88430839002268, 54.30657596371882, -5.252517006802721, 202.51149659863947, 4.96172335600907, -50.526326530612245, -1.1271655328798187, -10.404625850340135, -31.21387755102041, -1.7774603174603174, -3.8150340136054424, -4.638730158730159, -86.35839002267574, -14.132947845804988, 6.936417233560091, -107.85619047619048, 0.8880498866213152, -9.766190476190475, 3.8756009070294786, 65.26315192743765, -283.5050793650794, -0.5741723356009071, -0.1953061224489796, 0.5524943310657596, -37.47823129251701, -21.6, -6.4, -19.771428571428572, -100.0, -22.514285714285716, 18.742857142857144, -16.9443537414966, -2.0285714285714285, 13.057142857142857, -5.457142857142857, -15.342857142857143, 11.257142857142858, -15.480544217687076, -8.657142857142857, 1.7428571428571429, 3.914285714285714, 4.857142857142857, -8.485714285714286, 0.8857142857142857, -0.7714285714285715, -0.6857142857142857, 92.43299319727892, -5.503673469387755, -12.972993197278912, -8.255510204081633, -181.06972789115648, -180.77814058956915, -25.25798185941043, -25.25798185941043, -30.27027210884354, -31.449637188208616, -13.759229024943311, -11.007392290249433, -2.358730158730159, -1.2226757369614512, 9.106235827664399, -307.3968934240363, 2.0236054421768706, -10.522766439909297, -9.409773242630385, -8.600340136054422, -8.39798185941043, -7.48734693877551, 44.11467120181406, 66.37437641723356, 58.988185941043085, 92.58009070294784, 62.7318820861678, -82.63780045351474, -76.79596371882086, -65.26138321995465, -103.40639455782313, -139.21777777777777, 77.70657596371882, 93.18718820861677, 93.18716553287982, -31.044104308390022, 33.69308390022676, -32.37773242630386, 50.084331065759635, 48.971337868480724, -5.261383219954649, -19.189886621315193, 1.9224263038548752, 0.8094557823129251, -1.5177097505668935, -1.6188888888888888, -0.6078911564625851, 0.089297052154195, -21.281791383219954, -2.2843990929705216, -1.9088662131519274, 1.3155555555555556, -2.734308390022676, -26.930340136054422, 135.16766439909298, -112.22884353741496, 21.358548752834466, -31.16079365079365, -16.921768707482993, 30.02580498866213, -33.637142857142855, -21.874467120181407, -0.5675056689342404, 90.3869387755102, -35.49442176870748, -3.0954421768707485, 3.0954421768707485, -15.033968253968254, -0.6792290249433106, 0.9962131519274376, 14.671700680272108, -6.520748299319728, 0.8603854875283447, 4.709433106575964, 7.290566893424036, -25.17736961451247, -28.8, -3.079251700680272, -0.9962358276643991, 145.2679365079365, -113.0264172335601, 41.660385487528345, -1.0868027210884355, -119.54716553287982, 22.0981179138322, -279.7477551020408, -47.021519274376416, 3.227641723356009, 3.006802721088435, -0.9173242630385487, 1.2910430839002267, -153.88185941043085, 1.0074603174603174, 2.0149433106575962, -1.5671655328798186, 0.5596825396825397, -154.90068027210884, -34.02984126984127, -34.25371882086168, -41.082086167800455, -37.16417233560091, -0.11192743764172336, -37.879886621315194, -24.738798185941043, -2.4626757369614514, -19.25374149659864, -24.40299319727891, -6.380589569160998, -0.27984126984126984, -0.3078231292517007, -0.13990929705215419, -0.13990929705215419, -1.063424036281179, -1.7910430839002267, -0.12594104308390022, 0.30784580498866215, -0.09938775510204081, -0.10480725623582766, -0.10480725623582766, -39.196507936507935, 18.213061224489795, 13.785895691609978, -6.266326530612245, -0.8355102040816327, 14.830272108843538, -2.786077097505669, -9.43718820861678, 0.23512471655328798, 0.2821315192743764, -26.80249433106576, 0.721655328798186, -84.25963718820861, 27.050362811791384, 27.050362811791384)
Test:
mkHisto(x).show()
What remains to be done is customising x-axis labelling. The following addition to mkHisto changes colours and puts the proper x-axis labels:
import java.awt.Color
import org.jfree.chart.axis.{NumberTickUnit, NumberAxis}
import org.jfree.chart.plot.ValueMarker
import org.jfree.chart.renderer.xy.{StandardXYBarPainter, XYBarRenderer}
def lim(idx: Int) =
if (idx == 0) 0.0 else ((idx.abs - 1) * 3.log).exp * 0.06 * idx.signum
val plot = ch.plot
plot.getRenderer.asInstanceOf[XYBarRenderer].setBarPainter(new StandardXYBarPainter())
plot.addDomainMarker(new ValueMarker(0))
plot.setBackgroundPaint (Color.white )
plot.setDomainGridlinePaint (Color.lightGray)
plot.setRangeGridlinePaint (Color.lightGray)
plot.getRenderer.setSeriesPaint(0, Color.darkGray )
val xAxis = plot.getDomainAxis.asInstanceOf[NumberAxis]
xAxis.setTickUnit(new NumberTickUnit(1) {
override def valueToString(bin: Double) = {
val sig = if (bin < 0) "\u2212" else if (bin > 0) "+" else ""
f"""$sig${lim(bin.toInt).abs}%1.2f""""
}
})
xAxis.setVerticalTickLabels(true)
val yAxis = plot.getRangeAxis
yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits())
Final result:

Related

CallBack Error updating graph.figure - DASH

New here and to the world of python.
Generating a histogram plot where it changes color when a postcode is selected.
Now I have the main histogram but when the postcode is selected from the dropdown it gives the error. Unable to figure out how to resolve this. I have provided my full code below.
Let me know if more info is required to figure out the error. Something to do with input
import pandas as pd
import plotly.express as px
from dash import Dash, html, dcc, Input, Output
app = Dash(__name__)
app.title = "EGMs in NSW"
# Load your data : br = .....
datalist=pd.read_excel('premises-list-Aug-2022.xlsx',skiprows=[0,1,2])
datalist['Licence type'] = datalist['Licence type'].str.split(" - ").str.get(1)
datalist['Licence type'] = datalist['Licence type'].str.title()
postcode = datalist['Postcode']
postcode = postcode.sort_values(ascending=True)
postcode=list(dict.fromkeys(postcode))
pd.Series(datalist['Postcode'].unique()).sort_values(ascending=True)
def make_histogram_plot():
# Create scatter plot
fig=px.histogram(
data_frame = datalist,
x='Licence type',y='EGMs',color='Postcode',title='EGMs by Licence Type in NSW',
histfunc='avg'
)
fig.update_traces(marker=dict(color="#002664"))
fig.update_layout(
plot_bgcolor='#EAEDF4',
xaxis_title=None,
yaxis_title='Average EGMs'
)
return fig
app.layout = html.Div(children=[
html.Div([
dcc.Dropdown(postcode,value=[], placeholder="Select postcodes", multi=True, id='postcodes')
]),
dcc.Graph(id = 'graph',figure = make_histogram_plot())
])
#app.callback(
Output('graph','figure'),
Input('postcodes','value')
)
def dropdown_changed(postcodes):
if postcodes==[]:
fig = make_histogram_plot()
else:
datalist2 = datalist[datalist['Postcode'].isin(postcodes)],
# Create scatter plot
fig=px.histogram(
data_frame = datalist2,
x='Licence type',y='EGMs',color='Postcode',title='EGMs by Licence Type in NSW',
histfunc='avg'
)
fig.update_traces(marker=dict(color="#002664"))
fig.update_layout(
plot_bgcolor='#EAEDF4',
xaxis_title=None,
yaxis_title='Average EGMs'
)
return fig
# Start the server
if __name__ == '__main__':
app.run_server(debug=True)

How to get filepath from droped file with pyqt5?

I want to get path of the file dropped on QLabel. So I code like this, but label doesn't accept the file. What is the problem..?
Here is my code. So long code sorry and thank you!
import random
import sys
import pygame
import time
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import QWidget, QLabel, QApplication, QDesktopWidget
class Example(QWidget):
size=100
imgNum=0
frameCount=4
isXmin = False
isXmax = False
isYmin = False
isYmax = False
isLeft= True
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
sizeObject = QDesktopWidget().screenGeometry()
# print(" Screen size : " + str(sizeObject.height()) + "x" + str(sizeObject.width()))
self.xMax=sizeObject.width()-10
self.yMax=sizeObject.height()-10
print(self.xMax)
print(self.yMax)
self.setWindowFlags(Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
self.setStyleSheet("background-color:transparent;")
self.setGeometry(100, 100, 100, 100)
self.setWindowFlags(Qt.SplashScreen | Qt.WindowStaysOnTopHint)
self.setAcceptDrops(True)
self.label=QLabel(self)
self.label.setAcceptDrops(True)
self.pixmaps=[QPixmap('left.png'),QPixmap('stand.png'),QPixmap('right.png'),QPixmap('stand.png'),QPixmap('leftR.png'),QPixmap('standR.png'),QPixmap('rightR.png'),QPixmap('standR.png')]
for x in range(len(self.pixmaps)):
self.pixmaps[x]=self.pixmaps[x].scaled(self.size,self.size,Qt.KeepAspectRatio)
self.resize(self.pixmaps[2].width(),self.pixmaps[2].height())
self.label.setPixmap(self.pixmaps[len(self.pixmaps)-1])
self.changeTimer=QTimer(self)
self.changeTimer.timeout.connect(self.changeFoot)
self.moveTimer=QTimer(self)
self.moveTimer.timeout.connect(self.moving)
self.setAcceptDrops(True)
pygame.init()
pygame.mixer.music.load('hoi_imtemmie.mp3')
pygame.mixer.music.play()
self.show()
def dragEnterEvent(self, event):
if event.mimeData().hasUrls:
event.accept()
else:
event.ingore()
def dropEvent(self, event):
self.path=event.mimeData.urls()
def moving(self):
if self.distance == 0:
print(self.distance)
print(self.x(),"x",self.y())
self.label.setPixmap(self.pixmaps[1])
self.moveTimer.stop()
self.changeTimer.stop()
time.sleep(3)
self.setMovement()
return 0
else:
self.move(self.x()+self.direct[0],self.y()+self.direct[1])
self.distance-=1
if self.x()<=-10 :
self.distance=0
print("xm")
self.isXmin = True
if self.y()<=-10 :
self.distance=0
print("ym")
self.isYmin = True
if self.x()>=self.xMax:
self.distance=0
print("xM")
self.isXmax=True
if self.y()>=self.yMax :
self.distance=0
print("yM")
self.isYmax=True
def setMovement(self):
self.direct=[0,0]
while(self.direct[0]==0 and self.direct[1]==0):
self.direct=[random.randint(-1,1),random.randint(-1,1)]
if self.isXmax:
self.direct[0]=-1
if self.isXmin:
self.direct[0]=1
if self.isYmin:
self.direct[1]=1
if self.isYmax:
self.direct[1]=-1
if self.direct[0]== -1:
self.isLeft=True
self.imgNum=0
elif self.direct[0]== 1:
self.isLeft=False
self.imgNum=4
self.isXmax = False
self.isXmin = False
self.isYmin = False
self.isYmax = False
# if direct[0]*direct[1]==0 : self.delta = QPoint(dX*direct[0],dY*direct[1])
# else: self.delta=QPoint(direct[0]*(dX**(1/2)),direct[1]*(dY**1/2))
self.distance=random.randint(200,400)
self.changeTimer.start(300)
self.moveTimer.start(30)
def changeFoot(self):
self.label.setPixmap(self.pixmaps[self.imgNum])
if self.isLeft:
if self.imgNum<self.frameCount-1:
self.imgNum+=1
else :
self.imgNum=0
else:
if self.imgNum<2*self.frameCount-1:
self.imgNum+=1
else :
self.imgNum=self.frameCount
def mousePressEvent(self, QMouseEvent):
self.setMovement()
pygame.mixer.music.load('hoi_imtemmie.mp3')
pygame.mixer.music.play()
def keyPressEvent(self, QKeyEvent):
if QKeyEvent.key() == Qt.Key_Escape:
sys.exit()
# if QKeyEvent.key() == Qt.Key_G:
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
i set AcceptDrops(True)
self.setAcceptDrops(True)
and code about get filepath ▼
def dragEnterEvent(self, event):
if event.mimeData().hasUrls:
event.accept()
else:
event.ingore()
def dropEvent(self, event):
self.path=event.mimeData.urls()
Try to loop through event.mimeData().urls()
for url in event.mimeData().urls():
self.path = url.toLocalFile()

leafletR map doesn't load in shiny on start

I have the following little piece of code (more less as described HERE) - I want to control the number of points to be shown by a slider in shiny. You can see that the initial map is loaded after a little while (watch console output), but it will only show up after you used the slider once.
But I'd like the map to show up after it is created during launch of the shiny app - any hints how to do that?
## app.R ##
library(shiny)
library(shinydashboard)
library(httr)
library(leafletR)
data(quakes)
# dest_dir=tempdir()
dest_dir="foo_map"
dest_file = paste(dest_dir,"quakes","quakes.html",sep="\\")
dat = quakes
createMapHTML <- function(inputFreq=1) {
q.dat <- toGeoJSON(data=dat[seq(from = 1, to = nrow(dat), by=inputFreq), ],
dest=dest_dir, name="quakes")
sty <- styleSingle(col="darkblue", fill="darkblue", rad=6)
# create map
q.map <- leaflet(data=q.dat, dest=dest_dir, size = c(1200, 600), incl.data=TRUE,
base.map=list("osm"), style=sty, popup="*", controls="all")
}
# createMapHTML()
runApp(list(
ui = dashboardPage(
dashboardHeader(title = "quakes"),
dashboardSidebar(
sliderInput("slider", "#observations frequency:", 1, 100, 1)
),
dashboardBody(
htmlOutput("inc")
)
),
server = function(input, output, session) {
createMap <- reactive({
createMapHTML(input$slider)
return(includeHTML(dest_file))
})
output$inc<-renderUI({ createMap() })
}
))
so the bottleneck with the leafletR package is the conversion to GeoJson. Additionally the "includeHTML & htmlOutput" workaround for embedding the html out is flaky..
To avoid both I just switched to the leaflet packackage:
## app.R ##
library(shiny)
library(shinydashboard)
library(leaflet)
data(quakes)
dat = quakes
runApp(list(
ui = dashboardPage(
dashboardHeader(title = "quakes"),
dashboardSidebar(
sliderInput("slider", "#observations frequency:", 1, 100, 1)
),
dashboardBody(
leafletOutput("map", height = 600)
)
),
server = function(input, output) {
output$map <- renderLeaflet({
map <- leaflet() %>% addTiles()
map %>% addCircles(data=dat[seq(from = 1, to = nrow(dat), by=input$slider), ], #input$slider
lat = ~lat, lng = ~long, fillOpacity = 1.0)
})
}
))

scala sortWith: negative numbers are not getting sorted

val reslist = List(200.0,-100.00,50.80,-400.83, 800.003,-6.513214114672146E85, -1.2425461624057028E86, -4.7624471630469706E86, -3.6046499228286203E86, 0.0, -8.833653923554989E85, 0.000, -4.795843631190487E85, -5.34142100270833E86, -3.48087737474366E85, -2.811146396971388E86, -6.923235225460886E86, -6.513214114672146E85, 0.00000, -1.2425461624057028E86, -7.073704018243951E85, -9.633244016491059E86, -1.1418901590222212E86, -2.115257701350766E86, -1.1418901590222212E86, -3.48087737474366E85,-1.0676381955303372E86,500.56, 2.900556,400.56,-48956.00,4509.0005);
val weightlistzi = reslist.zipWithIndex
// List((200.0,0), (-100.0,1), (50.8,2), (-400.83,3), (800.003,4), (-6.513214114672146E85,5), (-1.2425461624057028E86,6), (-4.7624471630469706E86,7), (-3.6046499228286203E86,8), (0.0,9), (-8.833653923554989E85,10), (0.0,11), (-4.795843631190487E85,12), (-5.34142100270833E86,13), (-3.48087737474366E85,14), (-2.811146396971388E86,15), (-6.923235225460886E86,16), (-6.513214114672146E85,17), (0.0,18), (-1.2425461624057028E86,19), (-7.073704018243951E85,20), (-9.633244016491059E86,21), (-1.1418901590222212E86,22), (-2.115257701350766E86,23), (-1.1418901590222212E86,24), (-3.48087737474366E85,25), (-1.0676381955303372E86,26), (500.56,27), (2.900556,28), (400.56,29), (-48956.0,30), (4509.0005,31))
// I am sorting it here.
val resultlist = weightlistzi.sortWith { (x: (Double,Int), y: (Double,Int)) => x._1 > y._1 }
Here is the resulting list. As you can see, -100.0, -400.83, -48956.0 are occurring before -3 and the rest....
// List[(Double, Int)] = List((4509.0005,31), (800.003,4), (500.56,27), (400.56,29), (200.0,0), (50.8,2), (2.900556,28), (0.0,9), (0.0,11), (0.0,18), (-100.0,1), (-400.83,3), (-48956.0,30), (-3.48087737474366E85,14), (-3.48087737474366E85,25), (-4.795843631190487E85,12), (-6.513214114672146E85,5), (-6.513214114672146E85,17), (-7.073704018243951E85,20), (-8.833653923554989E85,10), (-1.0676381955303372E86,26), (-1.1418901590222212E86,22), (-1.1418901590222212E86,24), (-1.2425461624057028E86,6), (-1.2425461624057028E86,19), (-2.115257701350766E86,23), (-2.811146396971388E86,15), (-3.6046499228286203E86,8), (-4.7624471630469706E86,7), (-5.34142100270833E86,13), (-6.923235225460886E86,16), (-9.633244016491059E86,21))
There is E character in your numbers. This is Scientific notation.
-1.1E86 means -1.1 * (10^86). And -1.1 * (10^86) is less than -400.83 (-4.0083 * 10^2).

NameError: global name 'Carnage' is not defined

I know it was asked a million times before, but I need a little help getting this working, as the code is not mine.
so like that i update a code hope it will make some undarstands of it
# coding=utf-8
import urllib, re, sys, threading, cookielib, urllib2
from BeautifulSoup import BeautifulSoup
### Головная функция
def main():
agent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)'
aCarnage = Carnage('YourNick', 'YourPass', 'arkaim.carnage.ru', 'cp1251', agent)
aCarnage.login()
me = aCarnage.inf(aCarnage.user)
# Если ранен - выйти
if me['inj']:
aCarnage.logout()
exit(1)
aCarnage.urlopen('main.pl')
# Подождать пока здоровье восстановится
while(me['hp_wait']):
time.sleep(me['hp_wait'])
me = aCarnage.inf(aCarnage.user)
# Найти подходящую заявку
aCarnage.find()
me = aCarnage.inf(aCarnage.user)
# Если заявка состоялась - в бой!
if me['battle']: aCarnage.fight()
# После боя - выход из игры
aCarnage.logout()
class Opener:
def __init__(self, host, encoding, agent):
self.host = host
self.encoding = encoding
self.agent = agent
self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookielib.CookieJar()))
def urlopen(self, goto, data = None):
f = self.opener.open(urllib2.Request(
"http://%s/%s" % (self.host, goto),
self.urlencode(data),
{"User-agent" : self.agent}
))
result = f.read()
self.soup = BeautifulSoup(result)
def urlencode(self, data):
if data is None: return None
for key in data:
data[key] = data[key].encode(self.encoding, 'ignore')
return urllib.urlencode(data)
class CarnageBot(Opener):
### Конструктор принимает логин, пароль, кодировку (cp1251) и идентификатор браузера
def __init__(self, user, password, host, encoding, agent):
self.user = user
self.password = password
Opener.__init__(self, host, encoding, agent)
### Получить информацию об игроке - например о самом себе
def inf(self, user):
self.urlopen('inf.pl?' + self.urlencode({'user': user}))
# Кол-во жизни
onmouseover = self.soup.find('img', onmouseover = re.compile(unicode('Уровень жизни:', 'utf8')))
m = re.search('([0-9]+).([0-9]+)', onmouseover['onmouseover'])
hp = int(m.group(1))
hp_max = int(m.group(2))
hp_wait = (100 - (hp * 100) / hp_max) * 18
# Уровень
td = self.soup.find('td', text = re.compile(unicode('Уровень:', 'utf8')))
level = int(td.next.string)
# Ранен или нет
inj = 0
if self.soup.find(src = re.compile(unicode('travma.gif', 'utf8'))): inj = 1
# В бою или нет
battle = 0
if self.soup.find(text = re.compile(unicode('Персонаж находится в бою', 'utf8'))): battle = 1
hero = {'level': level, 'hp': hp, 'hp_max': hp_max, 'hp_wait': hp_wait, 'inj': inj, 'battle': battle}
return hero
### Войти в игру
def login(self):
data = {'action': 'enter', 'user_carnage': self.user, 'pass_carnage': self.password}
self.urlopen('enter.pl', data)
self.urlopen('main.pl')
### Выйти из игры
def logout(self):
self.urlopen('main.pl?action=exit')
### В бой!!!
def fight(self):
self.urlopen('battle.pl')
while True:
# Добить по таймауту
if self.soup.find(text = re.compile(unicode('Противник потерял сознание', 'utf8'))):
self.urlopen('battle.pl?cmd=timeout&status=win')
break
if self.soup.find(text = re.compile(unicode('Бой закончен.', 'utf8'))):
break
reg = re.compile(unicode('Для вас бой закончен. Ждите окончания боя.', 'utf8'))
if self.soup.find(text = reg):
break
cmd = self.soup.find('input', {'name' : 'cmd', 'type' : 'hidden'})
to = self.soup.find('input', {'name' : 'to', 'type' : 'hidden'})
# Есть ли по кому бить?!
if cmd and to:
a = random.randint(1, 4)
b0 = random.randint(1, 4)
b1 = random.randint(1, 4)
while b1 == b0: b1 = random.randint(1, 4)
pos = 2
arg = (cmd['value'], to['value'], pos, a, a, b0, b0, b1, b1)
self.urlopen('battle.pl?cmd=%s&to=%s&pos=%s&A%s=%s&D%s=%s&D%s=%s' % arg)
else:
self.urlopen('battle.pl')
time.sleep(random.randint(5, 30))
### Найти заявку - подающий заявку должен быть на 1 уровень ниже нашего
def find(self):
me = self.inf(self.user)
while True:
v = ''
self.urlopen('zayavka.pl?cmd=haot.show')
reg = re.compile(unicode('Текущие заявки на бой', 'utf8'))
script = self.soup.find('fieldset', text = reg).findNext('script')
m = re.findall('.*', script.string)
for value in m:
if value.find('group.gif') < 0: continue
if value.find('(%i-%i)' % (me['level'] - 2, me['level'])) < 0: continue
t = re.search(',([0-9]{1,2}),u', value)
if not t: continue
t = int(t.group(1))
v = re.search('tr\(([0-9]+)', value).group(1)
print 'Found battle t=%i v=%s' % (t, v)
break
if v: break
time.sleep(80)
nd = self.soup.find('input', {'name' : 'nd', 'type' : 'hidden'})
self.urlopen('zayavka.pl?cmd=haot.accept&nd=%s&battle_id=%s' % (nd['value'], v))
time.sleep(t + 30)
if __name__ == '__main__': main()
The error is:
NameError: global name 'Carnage' is not defined
The cause of your error is that Carnage has not been defined. Maybe you forgot to import a library which provides Carnage?
Also, your code as posted is incorrectly indented, which is a syntax error.
Update: Apparently you took this code from http://github.com/Ejz/Common/tree/master/carnage-bot . Reading that source, it looks like the line
aCarnage = Carnage('YourNick', 'YourPass', 'arkaim.carnage.ru', 'cp1251', agent)
Should be
aCarnage = CarnageBot('YourNick', 'YourPass', 'arkaim.carnage.ru', 'cp1251', agent)
Because the methods called on aCarnage are defined further down the file for class CarnageBot.