bootstrap docs

Bootstrap

  1. Media Query
    @media (min-width:992px) {
     /* CSS Style*/
    }
    
  2. 针对移动网页优化
  3. bootstrap grid
    • pull-sm-5, push-sm-7, 在小屏幕下,左移5个,右移7个grid。
    • flex-sm-first, flex-sm-last,在小屏幕下,成为第一个元素,成为最后一个元素。
    • class=”row align-items-center”, 在竖直方向居中
    • class=”row justify-content-center”, 在内部如果有class=”col-auto”, 基于内容自动调整占用列数,用于水平居中
    • class=”col-sm-4 offset-sm-1”,右移1个格子。
  4. classes
    • 适用超大屏幕
    • col-sm 不指定数字就是剩余所有
  5. Something
    • text-align: center
    • color: ** 是字体的颜色
  6. href
    • tel:+86xxx 调用外部打电话软件
    • mailto:xxx 调用发邮件
  7. label 和 input
    • <label for=”firstname”
    • <input id=”firstname”
    • label的for与input的id对应,在点击label的文字时,相应的input会被激活。
  8. closet tag
    • 需要闭合,否则页面无法显示。

    • 无需闭合
  9. media
    • 嵌入一个内容 ```go

```

  1. margin
    • margin top 0: class="mt-0"
    • margin left 3: class="ml-3"
  2. dispaly: flex
    • webkit前缀: display: -webkit-flex
    • flex-shrink.
  3. class=”hidden-xs-down” 在超小屏幕下隐藏

celery————分布式任务队列

Install

  • Broker: RabbitMQ
    sudo apt-get install rabbitmq-server
    
  • Celery: A distributed task queue
    pip install celery
    

Usage

  1. define a function ```python from celery import Celery

app = Celery(‘tasks’, backend=’amqp’, broker=’amqp://’)

@app.task def add(x, y): return x+y

tasks是当前模块的名称,即当前文件写在`tasks.py`中,`broker`='amqp://localhost'代表所用的messageQueue是rabbitmq,也可以采用redis,为`'redis://localhost'`。backend用来保存task的运行结果。

2. Lanuch a worker
```bash
celery -A tasks worker --loglevel=info

如果是在django项目中,把tasks改为项目名称。-A为–app。

  1. use task
    >>> from tasks import add
    >>> result = add.delay(4, 4)
    >>> result.ready()
    True
    >>> result.get(timeout=1)
    8
    

    通过result.state可以查看状态,如果一直处于PENDING状态,可以查看result.backend是否正确配置。

  2. Config
    • 直接配置
      app.conf.update(
       task_serializer='json',
       accept_content=['json'],  # Ignore other content
       result_serializer='json',
       timezone='Europe/Oslo',
       enable_utc=True,
      )
      
    • 从模块中读配置文件
      app.config_from_object('celeryconfig')
      

      celeryconfig.py ```python broker_url = ‘pyamqp://’ result_backend = ‘rpc://’

task_serializer = ‘json’ result_serializer = ‘json’ accept_content = [‘json’] timezone = ‘Europe/Oslo’ enable_utc = True


* 配置任务速率(celeryconfig.py), `Error`
```python
# 加入到低优先级队列
task_routes = {
    'tasks.add': 'low-priority',
}
# tasks.add的速度限制为1分钟10次
task_annotations = {
    'tasks.add': {'rate_limit': '10/m'}
}
  1. Others
    • app定义在主要的文件中,如celery.py中定义
      app = Celery('proj',
              broker='amqp://',
              backend='amqp://',
              include=['proj.tasks'])
      

      proj/tasks.py

      from .celery.py import app
      @app.task
      def ...
       ...
      
  • 延迟执行+简化参数
    >>> s1 = add.signature((2, 2), countdown = 10)
    >>> res = s1.delay()
    >>> res.state
    'PENDING'
    >>> res.state
    'SUCCESS'
    
  • Timezone
    app.conf.timezone = 'Europe/London'
    
  • rabbitmq C实现
    $ pip install librabbitmq
    
  • 定时任务
    1. periodic_task.py ```python from celery import Celery from celery.schedules import crontab

app = Celery()

@app.on_after_configure.connect def setup_periodic_tasks(sender, **kwargs): sender.add_periodic_task(10.0, test.s(‘hello’), name=’add every 10’)

@app.task def test(msg): print(msg)


2. 启动定时检测
```bash
celery -A periodic_task beat
  1. 启动worker
    celery -A periodic_task worker
    

    结果:

    [2017-11-07 11:17:36,061: WARNING/ForkPoolWorker-2] hello
    [2017-11-07 11:17:46,058: WARNING/ForkPoolWorker-1] hello
    [2017-11-07 11:17:56,060: WARNING/ForkPoolWorker-2] hello
    [2017-11-07 11:18:06,060: WARNING/ForkPoolWorker-1] hello
    [2017-11-07 11:18:16,060: WARNING/ForkPoolWorker-2] hello
    [2017-11-07 11:18:26,059: WARNING/ForkPoolWorker-1] hello
    [2017-11-07 11:18:36,058: WARNING/ForkPoolWorker-2] hello
    [2017-11-07 11:18:46,059: WARNING/ForkPoolWorker-1] hello
    [2017-11-07 11:18:56,062: WARNING/ForkPoolWorker-2] hello
    
  2. 高级设置
    # Executes every Monday morning at 7:30 a.m.
     sender.add_periodic_task(
         crontab(hour=7, minute=30, day_of_week=1),
         test.s('Happy Mondays!'),
     )
    
  3. 参考博客 http://www.cnblogs.com/alex3714/p/6351797.html

Latex

基础Tips

  1. 多个空格或tab按一个算,行末一个回车按空格算。
  2. 保留字符 # $ % ^ & _ { } ~ \,使用前加入\即可
    注: \\不会生成反斜杠,是断行命令。
    $\backslash$是反斜杠
    
  3. 注释 %会忽略一行之后的文本及下一行开头空白文本。
    \usepackage{verbatim}
    \begin{comment}
    非常笨拙的,
    然而却很有效。
    \end{comment}
    
  4. 文档结构 ```tex \documentclass{…} \usepackage{…} %使用其他宏集,增加功能 % 导言区 % 导言区 \begin{document} %开始文档

\end{document}


5. 为便于读者理解,应该把文档划分为章,节和子节。
```tex
% 对article风格的文档,有下列分节命令:
\section{...} \paragraph{...}
\subsection{...} \subparagraph{...}
\subsubsection{...}
% 对 report 和 book 风格的文档,还有其他两个分节命令:
\part{...}
\chapter{...}
  1. \tableofcontents
    在其出现的位置插入目录。为了得到正确的目录内容,一个新文档必须编
    译两次。有时还要编译三次。届时 L A TEX 会通知你。
    
  2. \footnote 脚注 ``` Footnotes\footnote{This is a footnote.} are often used by people using \LaTeX.

会在文末有一个注释

## 命令
* \textsl{lean} 斜体
* \newline 换行
* \pagestyle{style}
* \thispagestyle{style} % 改变本页样式

plain 页眉为空,页脚由居中的的页码组成。这是默认的页面式样。 headings 页眉由当前的章节标题和页码组成,页脚为空。 empty 设置页眉、页脚均为空。

* \include{filename} 大型文档由多个文件构成

* \\* 另起一行,非段
* \newpage 另起一页。
* \slppy 降低LATEX排版标准
* \fussy 恢复

* \- 当一个字需要换行的时候,指定换行位置,自主断字点。
```tex
I think this is: su\-per\-cal\-%
i\-frag\-i\-lis\-tic\-ex\-pi\-%
al\-i\-do\-cious

结果为
I think this is: supercalifragilisticexpialido-
cious
  • \hyphenation{FORTRAN Hy-phen-a-tion}

  • 当发生(盒子溢出)时,虽然 L A TEX 给出一个警告并显示溢出的那一行,但是不太容易发现溢出的行。如果你在 \documentclass 命令中使用选项 draft,LATEX 就在溢出行的右边标以粗黑线。
  • \mbox{text} 保证把几个单词排在同一行上。
  • \fbox{text} 在mbox基础上把文本用矩形框围起来

  • \appendix 不带参量,只把章的序号改用为字母标记。

  • 强调重要的单词 \underline{text}下划线 \emph{text}强调

  • 含有多项的一段 itemize 环境用于简单的列表,enumerate 环境用于带序号的列表,description环境用于带描述的列表。 ```tex \flushleft \begin{enumerate} \item You can mix the list environments to your taste: \begin{itemize} \item But it might start to look silly. \item[-] With a dash. \end{itemize}

% 把描述当作Item的命名 \item Therefore remember: \begin{description} \item[Stupid] things will not become smart because they are in a list. \item[Smart] things, though, can be presented beautifully in a list. \end{description} \end{enumerate}


* 对齐

begin{flushleft} end{flushleft} \flushleft左对其 \flushright右 \center


* 引用一段话

\begin{quote} On average, no line should be longer than 66 characters. \end{quote}

quotation 和 verse 环境。quotation 环境用于超过几段的较长引用,因为它对段落进行缩进。verse 环境用于诗歌,在诗歌中断行很重要。在一行的末尾用 \ 断行,在每一段后留一空行。


* 纯文本,不转义命令

位于 \begin{verbatim} 和 \end{verbatim} 之间的文本将直接打印,包括所有的断行和空白,就像在打字机上键入一样,不执行任何 L A TEX 命令。 \verb| text | 可以实现相同的效果

verbatim* 命令会把空格标注出来 \verb*| text |同上

* 制表

\begin{tabular}{table spec} l左对齐,r右对齐,c居中,p{width}产生一个宽度为width的列,自动断行; |表示铅直表线

& 下一列 \ 新的一行 \hline水平表线 \cline{j-i},添加部分表线,j和i分别为起始列和终止列。 @{}去掉表列之间的间隔,如 @{} l @{},那么本行两边不会有间隔,可以应用于小数点对齐 \begin{tabular}{c r @{.} l} Pi-expression & \multicolumn{2}{c}{Value} \ % multicolumn 值为Value \hline $\pi$ & 3&1416
$\pi^{\pi}$ & 36&46
$(\pi^{\pi})^{\pi}$ & 80662&7 \ \end{tabular}


* 浮动体——用于表格和图片(当前页面放不下表格或图片)

包围于环境 figure 或环境 table 中的任何材料都将被视为浮动内容。 \begin{figure}[placement specifier ] or \begin{table}[placement specifier ]

\begin{table}[!hbp]
放置说明符 [!hbp] 允许 L A TEX 把表格就放当前页,或放在某页的底部 (b),或放在一个专门的浮动页上 (p),严格按照放置说明符放置即使看起来不好 (!)如果没有给定放置说明符,缺省值为 [tbp]。

\caption{caption text}命令,可以给浮动体定义一个标题。序号和字符串“图”或“表”将由L A TEX 自动添加。 \caption[Short]{LLLLLoooooonnnnnggggg} Short是短标题,用在表目录或图目录中。

\clearpage or even the \cleardoublepagecommand. 它命令 L A TEX 立即安排等待序列中所有剩下的浮动体,并且开一新页。命令 \cleardoublepage 甚至会命令 L A TEX 新开奇数页面。

* 保护脆弱命令

\protect 仅仅保护紧跟其右侧的命令,连它的参量也不惠及。在大多数情形下,过多的 \protect 并不碍事。 \section{I am considerate \protect\footnote{and protect my footnotes}}


## 强大的数学公式
* 段落中的数学表达式应该置于 \( 和 \), $ 和 $ 或者 \begin{math} 和\end{math} 之间。
* 公式不编号

\begin{displaymath} c^{2}=a^{2}+b^{2} \end{displaymath}

* 引用公式

\begin{equation} \label{eq:eps} \epsilon > 0 \end{equation} From (\ref{eq:eps}), we gather \ldots


## 有用的
* \today
* \TeX
* \LaTeX
* \LaTeXe
* 标点

‘-’ 连字号,‘–’ 短破折号,‘—’ 长破折号和 ‘−’ 减 号。

~ http://www.rich.edu/ ̃bush $\sim$ http://www.clever.edu/∼demo

^{\circ}\mathrm{C} 摄氏度

\ldots 省略号

shelf\mbox{}ful 禁止连字

* 如果句号紧跟一个大写字母,它就不视为句子的结尾。因为一般在有缩写地方,才出现句号紧跟大写字母的情况。

cf.~Fig.~5 将会在句号后产生一个不能伸长的空格 用于名字 句号前的命令 \@ 说明这个句号是句子的末尾,即使它紧跟一 个大写字母。

\frenchspacing 能禁止在句号后插入额外的空间,它告诉 LATEX 在句号后不要插入比正常字母更多的空间。除了参考文献,这在非英语语言中非常普遍。 ```

  • a 与公式中的$a$不同

Jump More

跳一跳

记一个无聊的下午,研究跳一跳辅助程序的历程。
  1. Jump More
    首先去Github找到了红火的辅助项目,学习思路,因为第一次接触肯定是手足无措,学习先人的经验还是很有必要的。
    
  2. 简单思路
    • adb来截图手机,上传到项目目录,打开图片,标注两个点,跳。
    • adb 下载地址https://adb.clockworkmod.com/
    • 截图命令
      adb shell screencap -p /sdcard/autojump.png
      
    • 截图推到项目
      adb pull /sdcard/autojump.png .
      
    • 找到棋子点和目标板点
      首先找到目标点的最顶端的一个点,通过逐行扫描元素,发现与其他元素不一致的部分,因为肯定是一行像素颜色都是相同的,如果没有板子的话。
      从这个点向下275px往上搜索与这个点像素颜色相差不大的第一个点,就是我们要找的板子点,这样x,y都定下来了。
      棋子则是找固定的颜色区间,因为底座有一个颜色范围,取平均值即可。
      获取距离。
      
    • 跳跃
      一个简单的系数乘,或是复杂的公式,计算按压时间。
      
      press_time = int( max(distance * press_coefficient, 200))
      
      head_diameter = 60
      x1, y1, x2, y2 = get_swipe_button()
      scale = 0.945 * 2 / head_diameter
      actual_distance = distance * scale * (math.sqrt(6) / 2)
      press_time = (-945 + math.sqrt(945 ** 2 + 4 * 105 * 36 * actual_distance)) / (2 * 105) * 1000
      
  • adb 按压
    adb shell input swipe {x1} {y1} {x2} {y2} {duration}
    
  1. Tips
    用 from PIL import ImageDraw 在图上标注点Debug。
    
  2. 无聊的下午Over…

Pdf Extract JPG

PDF JPG

问题

如何从一个pdf文件中提取图片

思路

分析pdf文件,分析Pdf的文件流内容。pdf内的图片都是jpg格式,所以进一步分析jpg格式文件,然后把bytes数组保存到一个文件即可。

具体做法

  1. 找到”stream”
  2. 查看这个stream是否是jpg,在20个字节内寻找十六进制为0xff, 0xd8,是jpg文件的开头。
  3. 如果不是的话继续下一个stream
  4. 如果是找到”endstream”
  5. 在endstream位置前20个字节内寻找十六进制为0xff, 0xd9,是jpg文件的结尾。
  6. 把区间的bytes数组保存到文件
  7. 继续循环寻找下一个stream
  8. 文件全部找完,退出。

代码

Go 实现

// ExtractPdfImages gets JPG images via parse protocol in pdf stream.
func ExtractPdfImages(pdfname string) ([][]byte, error) {
	file, err := os.Open(pdfname)
	defer file.Close()
	content, err := ioutil.ReadAll(file)
	if err != nil { return nil, err	}
	startLoc, resultImageBytes := 0, make([][]byte, 0)
	for {
		streamStart := bytesFind(content, []byte("stream"), startLoc)
		if streamStart == -1 { break}
		jpgStart := bytesFind(content[:streamStart+20], []byte{0xff, 0xd8}, streamStart)
		if jpgStart == -1 {
			startLoc = streamStart + 20
			continue
		}
		streamEnd := bytesFind(content, []byte("endstream"), jpgStart)
		if streamEnd == -1 { return nil, Error{"pdf don't have stream end..."}}
		jpgEnd := bytesFind(content, []byte{0xff, 0xd9}, streamEnd - 20)
		if jpgEnd == -1 { return nil, Error{"pdf don't have jpg end..."}	}
		resultImageBytes = append(resultImageBytes, content[jpgStart+1: jpgEnd+1])
		if err != nil { return nil, err}
		startLoc = jpgEnd
	}
	return resultImageBytes, nil
}

第一次离去

光辉岁月

人生有梦,各自精彩。

第一次离职

    每个人都有第一次离职的时候,2017年12月13日是我从啸谷离开的日子,学生时代的一次离职。小公司,最大的好处就是可以直接与CEO对话,传道授业解惑,收获颇丰。
    我知道你也会经历离职,这件事和其他分别并没有什么不同吧,像是分手亦或合作终止,稀松平常。从分别中获取更多,正如“爱情会使人成长”,甜蜜的爱情并不会。
    我的经验:
    1. 要善于读log和错误信息。以前除了错误,一大串英文也是懒得看,但是当一个个字母看过去,其实问题很容易解决。
    2. 做事要认真。别总想着其他,代码是你工作时的唯一。
    3. 那就做个职场小白,没有任何期待,不轻信未来,只相信现在和你拥有的,比如月薪而非承诺。
    4. 没人是朋友,除了机器。
    5. Docker是个好东西,让不兼容的兼容,http协议可以跨语言编程。
    6. ubuntu很好用,相比windows更合适开发,要学会shell,不然也没用。
    7. 计算机理论基础大部分是没用的,不过总会进入另外百分之二十的领域。比如Golang的并发编程,如何同步线程,至少要会操作系统吧。
    8. 勤写单元测试,1999年(Fowler《重构》)就很重视的东西,没理由现在不写,省去大部分没有意义的Debug。

搓澡师傅

    苏烨是个搓澡师傅。
    他儿子是个初中生,学习成绩不佳,想必是经常挨打,每次都会和我聊两句,那年我大一。
    他儿子好像中考完了,去了个技校学手艺,闲聊,他暑假要去校外工作,男人相必都不容易,没有感慨,只是我大二了。
    后来大三,我去了浑南,隔了二十公里,去的少了,偶尔去一次,专程去,没什么理由。
    现在大四了,时间过得真快,总有一天我会失去我拥有的一切吧,只不过那天远到不足以使我恐惧。突然想问他,为什么来搓澡。“十多岁出来卖菜,那菜放的时间短,后来我就去卖水果去了。但这玩意累,然后我就去倒腾服装,有天我哥们来跟我显摆,说他一个月挣一万多。那时候我卖服装一个月也得六七千呢,他说他现在搓澡呢。当晚我就去他们洗浴中心体会了一下,那个火啊,六个人搓澡搓不过来,一天能挣四百多,那就去干吧,完事别人教我搓一把,我又试着给俩服务员搓。感觉挺好,第二天我就跟边上那床子说,把服装都卖他了。后来又自己做洗头膏、沐浴露卖给那些洗浴中心,搓澡那帮哥们也帮着联系。反正后来被一个本地的大牌子给惹急眼了,后来做了小半年就停了。”
    生活不总是沉重,我二十二岁,新的旅途。