CREATE TABLE PDIndicatorsHistory
(
RecId int PRIMARY KEY IDENTITY(1,1),
ItemId int,
ReportDate datetime,
PD int
);
INSERT INTO PDIndicatorsHistory (ItemId,ReportDate,PD) VALUES
(1, '2025-07-06', 2), (1, '2025-07-07', NULL), (1, '2025-07-08', NULL);
SELECT * FROM PDIndicatorsHistory;
CREATE FUNCTION dbo.GetPD
(
@prev_RecId INT, -- идентификатор предыдущей записи, её исходное состояние
@next_RecId int, -- идентификатор текущей записи, её исходное состояние
@prev_PD INT -- значения отдельных полей обновлённой предыдущей записи
)
RETURNS int
AS
BEGIN
-- требуемая сложная логика, опирающаяся на идентификаторы текущей и предыдущей записей
-- что позволяет получить значения полей записей ДО запуска SELECT или там UPDATE,
-- а также на значения полей модифицированного состояния предыдущей записи, переданных по отдельности
RETURN @prev_PD * 2;
END;
WITH
-- первый CTE, просто нумерует записи по возрастанию даты для каждого ItemId отдельно
cte1 AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY ItemId ORDER BY ReportDate ASC) rn
FROM PDIndicatorsHistory
),
-- рекурсивно обрабатываем записи в порядке возрастания номера
cte2 AS (
SELECT RecId, ItemId, ReportDate, PD, rn
FROM cte1
WHERE rn = 1 -- начинаем с первой
UNION ALL
SELECT cte1.RecId,
cte1.ItemId,
cte1.ReportDate,
dbo.GetPD(cte2.RecId, cte1.RecId, cte2.PD),
cte1.rn
FROM cte1
JOIN cte2 ON cte1.ItemId = cte2.ItemId
AND cte1.rn = cte2.rn + 1 -- а потом вторая, третья... пока не кончатся
)
-- посчитав значения, которые нужно использовать при обновлении, выполняем само обновление
UPDATE PDIndicatorsHistory
SET PD = cte2.PD
FROM cte2
WHERE PDIndicatorsHistory.RecID = cte2.RecId;
description = f"""У тебя , **{ctx.author}** вот столько балов!**{cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]} :polegar_para_cima:**"""
description = f"""У тебя , **{ctx.author}** вот столько балов!**{cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]} :polegar_para_cima:**"""
score = cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]
description = f"""У тебя , **{ctx.author}** вот столько балов!**{score} :polegar_para_cima:**"""
score = cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id))
score = cursor.execute("SELECT cash FROM users WHERE id = ?", (ctx.author.id,) )
score = cursor.execute("SELECT cash FROM users WHERE id = ?", (ctx.author.id,) ).fetchone()[0]
description = f"""У тебя , **{ctx.author}** вот столько балов!**{score} :polegar_para_cima:**"""
score_row = cursor.execute("SELECT cash FROM users WHERE id = ?", (ctx.author.id,) ).fetchone()
if score_row is not None:
description = f"""У тебя , **{ctx.author}** вот столько балов!**{score_row[0]} :polegar_para_cima:**"""
else:
# что делать, если такого юзера еще нет в базе?
cursor.execute("INSERT INTO users (id, cash) VALUES (?, 0)", (ctx.author.id,) ) # можно его добавить
description = f"""У тебя , **{ctx.author}** пока нет ничего! Но скоро будет!"""
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
namespace SimpleMessageBus
{
/// <summary>
/// Рассылает события заинтересованным подписчикам
/// в рамках одного приложения.
/// </summary>
/// <remarks>Используются WeakReference, чтобы не было утечек памяти
/// на случай, если кто-то забудет отписаться. Поэтому не рекомендуется
/// использовать лямбда-обработчики событий.</remarks>
public static class MessageBus
{
private static readonly Dictionary<string, List<WeakReference<Action<string, object>>>> Subscribers =
new Dictionary<string, List<WeakReference<Action<string, object>>>>();
/// <summary>
/// Оформляет подписку на событие
/// </summary>
/// <param name="topic">Тип события</param>
/// <param name="handler">Подписчик</param>
public static void Subscribe(string topic,
Action<string, object> handler)
{
if (String.IsNullOrEmpty(topic))
throw new ArgumentNullException(nameof(topic));
if (handler == null)
throw new ArgumentNullException(nameof(handler));
List<WeakReference<Action<string, object>>> handlers;
lock (Subscribers)
if (!Subscribers.TryGetValue(topic, out handlers))
handlers = Subscribers[topic] = new List<WeakReference<Action<string, object>>>();
lock (handlers)
handlers.Add(new WeakReference<Action<string, object>>(handler));
}
/// <summary>
/// Отменяет подписку на событие
/// </summary>
/// <param name="topic">Тип события</param>
/// <param name="handler">Подписчик</param>
public static void Unsubscribe(string topic,
Action<string, object> handler)
{
if (String.IsNullOrEmpty(topic))
throw new ArgumentNullException(nameof(topic));
if (handler == null)
throw new ArgumentNullException(nameof(handler));
List<WeakReference<Action<string, object>>> list;
lock (Subscribers)
if (!Subscribers.TryGetValue(topic, out list))
return;
lock (list)
{
var i = 0;
while (i < list.Count)
{
var reference = list[i];
if (!reference.TryGetTarget(out var target))
list.RemoveAt(i); // Заодно очищаем список от мертвых подписчиков
else if (target == handler)
{
list.RemoveAt(i);
return;
}
}
}
}
/// <summary>
/// Оповещает подписчиков о наступлении события
/// </summary>
/// <param name="topic">Тип события</param>
/// <param name="data">Данные события</param>
public static void Publish(string topic, object data = null)
{
if (String.IsNullOrEmpty(topic))
throw new ArgumentNullException(nameof(topic));
List<WeakReference<Action<string, object>>> list;
lock (Subscribers)
if (!Subscribers.TryGetValue(topic, out list))
return;
var handlers = new List<Action<string, object>>();
lock (list)
{
var i = 0;
while (i < list.Count)
{
var reference = list[i];
if (!reference.TryGetTarget(out var target))
list.RemoveAt(i);
else
{
handlers.Add(target);
++i;
}
}
}
// В Unity вызывать обработчики событий, наверное,
// нужно как-то так:
UnityEngine.WSA.Application.InvokeOnAppThread(() =>
// А в обычном консольном приложении так:
// Task.Run(() =>
{
foreach (var handler in handlers)
{
try
{
handler.Invoke(topic, data);
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
}, false);
}
}
}
using System.Diagnostics;
using System.Threading.Tasks;
namespace SimpleMessageBus
{
public static class Program
{
public static async Task Main(string[] args)
{
Debug.WriteLine("Started.");
MessageBus.Subscribe("Rain", RainHandler);
MessageBus.Publish("Rain");
await Task.Delay(100); // Ждем, пока событие поступит
MessageBus.Unsubscribe("Rain", RainHandler);
Debug.WriteLine("Finished.");
}
private static void RainHandler(string topic, object data)
{
Debug.WriteLine("Event: " + topic);
}
}
}
UnityEngine.WSA.Application.InvokeOnAppThread()
— все-таки у нас целевая платформа Unity. курсов типа GB,Skill..,YA?
Насколько это реально?
Вкратце о себе, мне 28 лет, работаю манагером.
Изучаю Python уже полгода, но чисто для себя, учусь делать боты, хочу попробовать поделать парсеры, это как хобби
Так как продажи уже зае...ли
решил промониторить рынок и наткнулся на вакансии тестировщиков и автотестировщиков.
что тестировщиком попроще войти в рынок it чем программистом.
Типа гарантированное трудоустройство и туда и сюда. НО я же сам продажник и понимаю что никаких гарантий нет.
Сколько времени это примерно у вас заняло?
подбором персонала "Рассматриваете ли вы реально кандидатов после курсов в возрасте от 28 лет? Вообще приходят ли к вам люди с какими то знаниями ? Даете ли шанс? Или сливаете?"
на реальную работу я даже не рассчитываю.
поизучаю Pythonчик и сделаю года через полтора годика какого нибудь крутого бота
var source = "Test";
// v.1 Заменит первое вхождение этой буквы в слове на удвоенную
var ch = 's';
var i = source.IndexOf(ch);
var result = source.Substring(0, i) + ch + source.Substring(i);
// v.2 Заменит все вхождения этой буквы в слове на удвоенную
var ch = "s";
var result = source.Replace(ch, ch + ch);
11:12 p.m. PST: The team is currently testing a fix for this issue. In the meantime, signing of new extensions is disabled until the fix is in place.
Update: Firefox developers are currently reviewing a patch that will fix this issue.
void get_disks(char * allDisks[]) { char buf[128]; ... for (char *s = buf; *s; s += strlen(s) + 1) { ... allDisks[i] = s; ... allDisks[7] = "ABC"; allDisks[8] = "DEF"; } }
После прохождения массива функцией get_files список дисков исчезает, но "ABC" и "DEF" остаются.
Подскажите, почему так происходит, куда теряются первые строки и как исправить?
allDisks
указатели на стековый массив buf
, который разрушается после выхода из функции get_disks
. А строчки "ABC" и "DEF" -- константные строчки, существуют всё время выполнения программы.allDisks
:void get_disks(char * allDisks[])
{
char buf[128];
int i = 0;
GetLogicalDriveStringsA(sizeof(buf), buf);
for (char *s = buf; *s; s += strlen(s) + 1)
{
if (GetDriveTypeA(s) == 2 || GetDriveTypeA(s) == 3)
{
allDisks[i] = strdup(s);
++i;
allDisks[7] = "ABC";
allDisks[8] = "DEF";
}
}
}